Chapter 8. Configure observability


Configure logging, monitoring, and telemetry for OpenShift Dev Spaces to gain visibility into workspace health, operator performance, and usage patterns.

8.1. Configure the Woopra telemetry plugin

The Woopra Telemetry Plugin sends telemetry from a Red Hat OpenShift Dev Spaces installation to Segment and Woopra. Any Red Hat OpenShift Dev Spaces deployment can use this plugin with a valid Woopra domain and Segment Write key.

The devfile v2 for the plugin, plugin.yaml, has four environment variables that can be passed to the plugin:

  • WOOPRA_DOMAIN - The Woopra domain to send events to.
  • SEGMENT_WRITE_KEY - The write key to send events to Segment and Woopra.
  • WOOPRA_DOMAIN_ENDPOINT - If you prefer not to pass in the Woopra domain directly, the plugin gets it from a supplied HTTP endpoint that returns the Woopra Domain.
  • SEGMENT_WRITE_KEY_ENDPOINT - If you prefer not to pass in the Segment write key directly, the plugin gets it from a supplied HTTP endpoint that returns the Segment write key.

To enable the Woopra plugin on the Red Hat OpenShift Dev Spaces installation:

Procedure

  1. Deploy the plugin.yaml devfile v2 file to an HTTP server with the environment variables set correctly.
  2. Configure the CheCluster Custom Resource. See Section 2.2, “Use the CLI to configure the CheCluster Custom Resource”.

    spec:
      devEnvironments:
        defaultPlugins:
        - editor: eclipse/che-theia/next
          plugins:
          - '<your_plugin_url>'

    where:

    editor
    The editorId to set the telemetry plugin for.
    plugins
    The URL to the telemetry plugin’s devfile v2 definition, for example, https://your-web-server/plugin.yaml.

8.2. Telemetry plugin overview

Create a telemetry plugin for OpenShift Dev Spaces to collect workspace usage data and send it to your analytics backend. The plugin extends the AbstractAnalyticsManager class with methods for event handling, activity tracking, and shutdown.

The AbstractAnalyticsManager class requires the following method implementations:

  • isEnabled() - determines whether the telemetry backend is functioning correctly. This can mean always returning true, or have more complex checks, for example, returning false when a connection property is missing.
  • destroy() - cleanup method that is run before shutting down the telemetry backend. This method sends the WORKSPACE_STOPPED event.
  • onActivity() - notifies that some activity is still happening for a given user. This is mainly used to send WORKSPACE_INACTIVE events.
  • onEvent() - submits telemetry events to the telemetry server, such as WORKSPACE_USED or WORKSPACE_STARTED.
  • increaseDuration() - increases the duration of a current event rather than sending many events in a small frame of time.

A finished example of the telemetry backend is available in the devworkspace-telemetry-example-plugin repository.

8.2.1. Create a telemetry server

Create a server that receives telemetry events from the OpenShift Dev Spaces telemetry plugin and writes them to standard output. For production, consider integrating with a third-party telemetry system such as Segment or Woopra.

Prerequisites

  • You have a running instance of Red Hat OpenShift Dev Spaces.

Procedure

  1. Create a main.go file for a Go application that starts a server on port 8080 and writes events to standard output:

    package main
    
    import (
    	"io/ioutil"
    	"net/http"
    
    	"go.uber.org/zap"
    )
    
    var logger *zap.SugaredLogger
    
    func event(w http.ResponseWriter, req *http.Request) {
    	switch req.Method {
    	case "GET":
    		logger.Info("GET /event")
    	case "POST":
    		logger.Info("POST /event")
    	}
    	body, err := req.GetBody()
    	if err != nil {
    		logger.With("err", err).Info("error getting body")
    		return
    	}
    	responseBody, err := ioutil.ReadAll(body)
    	if err != nil {
    		logger.With("error", err).Info("error reading response body")
    		return
    	}
    	logger.With("body", string(responseBody)).Info("got event")
    }
    
    func activity(w http.ResponseWriter, req *http.Request) {
    	switch req.Method {
    	case "GET":
    		logger.Info("GET /activity, doing nothing")
    	case "POST":
    		logger.Info("POST /activity")
    		body, err := req.GetBody()
    		if err != nil {
    			logger.With("error", err).Info("error getting body")
    			return
    		}
    		responseBody, err := ioutil.ReadAll(body)
    		if err != nil {
    			logger.With("error", err).Info("error reading response body")
    			return
    		}
    		logger.With("body", string(responseBody)).Info("got activity")
    	}
    }
    
    func main() {
    
    	log, _ := zap.NewProduction()
    	logger = log.Sugar()
    
    	http.HandleFunc("/event", event)
    	http.HandleFunc("/activity", activity)
    	logger.Info("Added Handlers")
    
    	logger.Info("Starting to serve")
    	http.ListenAndServe(":8080", nil)
    }

    The code for the example telemetry server is available in the telemetry-server-example repository.

  2. Create a container image based on this code and expose it as a deployment in OpenShift in the openshift-devspaces project. Clone the repository and build the container:

    $ git clone https://github.com/che-incubator/telemetry-server-example
    $ cd telemetry-server-example
    $ podman build -t registry/organization/telemetry-server-example:latest .
    $ podman push registry/organization/telemetry-server-example:latest
  3. Deploy the telemetry server to OpenShift.

    Both manifest_with_ingress.yaml and manifest_with_route contain definitions for a Deployment and Service. The former also defines a Kubernetes Ingress, while the latter defines an OpenShift Route.

    In the manifest file, replace the image and host fields to match the image you pushed, and the public hostname of your OpenShift cluster. Then run:

    $ oc apply -f manifest_with_[ingress|route].yaml -n openshift-devspaces

Verification

  • Verify that the telemetry server pod is running:

    oc get pods -n openshift-devspaces -l app=telemetry-server-example

8.2.2. Create a telemetry backend

Create a Quarkus-based telemetry backend that extends the OpenShift Dev Spaces telemetry client and implements custom event handling logic.

Note

For fast feedback when developing, develop inside a Dev Workspace. This way, you can run the application in a cluster and receive events from the front-end telemetry plugin.

Prerequisites

Procedure

  1. Create a Maven Quarkus project:

    mvn io.quarkus:quarkus-maven-plugin:2.7.1.Final:create \
        -DprojectGroupId=mygroup -DprojectArtifactId=devworkspace-telemetry-example-plugin \
    -DprojectVersion=1.0.0-SNAPSHOT
  2. Remove the files under src/main/java/mygroup and src/test/java/mygroup.
  3. Consult the GitHub packages for the latest version of backend-base and add the following dependencies to your pom.xml:

    <!-- Required -->
    <dependency>
        <groupId>org.eclipse.che.incubator.workspace-telemetry</groupId>
        <artifactId>backend-base</artifactId>
        <version><latest_version></version>
    </dependency>
    
    
    <!-- Used to make http requests to the telemetry server -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-jackson</artifactId>
    </dependency>
  4. Create a personal access token with read:packages permissions from GitHub packages and add your GitHub username, the token, and che-incubator repository details in your ~/.m2/settings.xml file:

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
    http://maven.apache.org/xsd/settings-1.0.0.xsd">
       <servers>
          <server>
             <id>che-incubator</id>
             <username><github_username></username>
             <password><github_token></password>
          </server>
       </servers>
    
       <profiles>
          <profile>
             <id>github</id>
             <activation>
                <activeByDefault>true</activeByDefault>
             </activation>
             <repositories>
                <repository>
                   <id>central</id>
                   <url>https://repo1.maven.org/maven2</url>
                   <releases><enabled>true</enabled></releases>
                   <snapshots><enabled>false</enabled></snapshots>
                   </repository>
                   <repository>
                   <id>che-incubator</id>
                   <url>https://maven.pkg.github.com/che-incubator/che-workspace-telemetry-client</url>
                </repository>
             </repositories>
          </profile>
       </profiles>
    </settings>
  5. Create MainConfiguration.java under src/main/java/mygroup. This file contains configuration provided to AnalyticsManager:

    package org.my.group;
    
    import java.util.Optional;
    
    import javax.enterprise.context.Dependent;
    import javax.enterprise.inject.Alternative;
    
    import org.eclipse.che.incubator.workspace.telemetry.base.BaseConfiguration;
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    
    @Dependent
    @Alternative
    public class MainConfiguration extends BaseConfiguration {
        @ConfigProperty(name = "welcome.message")
        Optional<String> welcomeMessage;
    }

    where:

    @ConfigProperty(name = "welcome.message")
    A MicroProfile configuration annotation that injects the welcome.message configuration. For more details on how to set configuration properties specific to your backend, see the Quarkus Configuration Reference Guide.
  6. Create AnalyticsManager.java under src/main/java/mygroup. This file contains logic specific to the telemetry system:

    package org.my.group;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.enterprise.context.Dependent;
    import javax.enterprise.inject.Alternative;
    import javax.inject.Inject;
    
    import org.eclipse.che.incubator.workspace.telemetry.base.AbstractAnalyticsManager;
    import org.eclipse.che.incubator.workspace.telemetry.base.AnalyticsEvent;
    import org.eclipse.che.incubator.workspace.telemetry.finder.DevWorkspaceFinder;
    import org.eclipse.che.incubator.workspace.telemetry.finder.UsernameFinder;
    import org.eclipse.microprofile.rest.client.inject.RestClient;
    import org.slf4j.Logger;
    
    import static org.slf4j.LoggerFactory.getLogger;
    
    @Dependent
    @Alternative
    public class AnalyticsManager extends AbstractAnalyticsManager {
    
        private static final Logger LOG = getLogger(AbstractAnalyticsManager.class);
    
        public AnalyticsManager(MainConfiguration mainConfiguration, DevWorkspaceFinder devworkspaceFinder, UsernameFinder usernameFinder) {
            super(mainConfiguration, devworkspaceFinder, usernameFinder);
    
            mainConfiguration.welcomeMessage.ifPresentOrElse(
                (str) -> LOG.info("The welcome message is: {}", str),
                () -> LOG.info("No welcome message provided")
            );
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    
        @Override
        public void destroy() {}
    
        @Override
        public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) {
            LOG.info("The received event is: {}", event);
        }
    
        @Override
        public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) { }
    
        @Override
        public void onActivity() {}
    }

    where:

    ifPresentOrElse()
    Log the welcome message if it was provided.
    LOG.info("The received event is: {}", event)
    Log the event received from the front-end plugin.
  7. Add the quarkus.arc.selected-alternatives property to src/main/resources/application.properties to specify the alternative beans org.my.group.AnalyticsManager and org.my.group.MainConfiguration:

    quarkus.arc.selected-alternatives=MainConfiguration,AnalyticsManager

Verification

  • Run the Quarkus application and verify that it starts without errors:

    mvn quarkus:dev

Implement the AnalyticsManager event handling methods in your telemetry backend and test the backend in a running Dev Workspace to verify that events are received from the front-end plugin.

Prerequisites

Procedure

  1. Set the DEVWORKSPACE_TELEMETRY_BACKEND_PORT environment variable in the Dev Workspace. Here, the value is set to 4167.

    spec:
      template:
        attributes:
          workspaceEnv:
            - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT
              value: '4167'
  2. Restart the Dev Workspace from the Red Hat OpenShift Dev Spaces dashboard.
  3. Run the following command within a Dev Workspace’s terminal window to start the application. Use the --settings flag to specify the path to the settings.xml file that contains the GitHub access token.

    $ mvn --settings=settings.xml quarkus:dev -Dquarkus.http.port=${DEVWORKSPACE_TELEMETRY_BACKEND_PORT}

    The application now receives telemetry events through port 4167 from the front-end plugin. Verify that the following output is logged:

    INFO  [org.ecl.che.inc.AnalyticsManager] (Quarkus Main Thread) No welcome message provided
    INFO  [io.quarkus] (Quarkus Main Thread) devworkspace-telemetry-example-plugin 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.2.Final) started in 0.323s. Listening on: http://localhost:4167
    INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
    INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes-client, rest-client, rest-client-jackson, resteasy, resteasy-jsonb, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx]
  4. Customize isEnabled() in AnalyticsManager.java. For this example, the method always returns true:

    @Override
    public boolean isEnabled() {
        return true;
    }

    The hosted OpenShift Dev Spaces Woopra backend demonstrates a more advanced isEnabled() implementation that checks for a configuration property before enabling the backend.

  5. Implement onEvent() to send events to the telemetry server. For the example application, it sends an HTTP POST payload to the /event endpoint.

    1. Configure the RESTEasy REST Client by creating a TelemetryService.java interface:

      package org.my.group;
      
      import java.util.Map;
      
      import javax.ws.rs.Consumes;
      import javax.ws.rs.POST;
      import javax.ws.rs.Path;
      import javax.ws.rs.core.MediaType;
      import javax.ws.rs.core.Response;
      
      import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
      
      @RegisterRestClient
      public interface TelemetryService {
          @POST
          @Path("/event")
          @Consumes(MediaType.APPLICATION_JSON)
          Response sendEvent(Map<String, Object> payload);
      }

      where:

      @Path("/event")
      The endpoint to make the POST request to.
    2. Specify the base URL for TelemetryService in src/main/resources/application.properties:

      org.my.group.TelemetryService/mp-rest/url=http://little-telemetry-server-che.apps-crc.testing
    3. Inject TelemetryService into AnalyticsManager.java and send a POST request in onEvent():

      @Dependent
      @Alternative
      public class AnalyticsManager extends AbstractAnalyticsManager {
          @Inject
          @RestClient
          TelemetryService telemetryService;
      
      ...
      
      @Override
      public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) {
          Map<String, Object> payload = new HashMap<String, Object>(properties);
          payload.put("event", event);
          telemetryService.sendEvent(payload);
      }

      This sends an HTTP request to the telemetry server and automatically delays identical events for a small period of time. The default duration is 1500 milliseconds.

  6. Implement increaseDuration() in AnalyticsManager.java. Many telemetry systems recognize event duration. The AbstractAnalyticsManager merges similar events that happen in the same frame of time into one event. This implementation is a no-op:

    @Override
    public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) {}
  7. Implement onActivity() in AnalyticsManager.java. Set an inactive timeout limit and send a WORKSPACE_INACTIVE event if the last event time exceeds the timeout:

    public class AnalyticsManager extends AbstractAnalyticsManager {
    
        ...
    
        private long inactiveTimeLimit = 60000 * 3;
    
        ...
    
        @Override
        public void onActivity() {
            if (System.currentTimeMillis() - lastEventTime >= inactiveTimeLimit) {
                onEvent(WORKSPACE_INACTIVE, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties);
            }
        }
  8. Implement destroy() in AnalyticsManager.java. When called, send a WORKSPACE_STOPPED event and shut down any resources such as connection pools:

    @Override
    public void destroy() {
        onEvent(WORKSPACE_STOPPED, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties);
    }

Verification

  1. To verify that the onEvent() method receives events from the front-end plugin, press the l key to disable Quarkus live coding and edit any file within the IDE. The following output should be logged:

    INFO  [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload disabled
    INFO  [org.ecl.che.inc.AnalyticsManager] (executor-thread-2) The received event is: Edit Workspace File in Che
  2. Stop the application with Ctrl+C and verify that a WORKSPACE_STOPPED event is sent to the server.

8.2.4. Deploy a telemetry plugin

Package the telemetry backend as a container image, create a devfile v2 plugin, and host the plugin on a web server so that Dev Workspaces can load it.

This guide demonstrates hosting the plugin on an Apache web server on OpenShift. In production, deploy the plugin file to a corporate web server.

Prerequisites

Procedure

  1. Package the Quarkus application as a container image and push it to a container registry by using one of the following options. See the Quarkus documentation for details.

    Option A: JVM image
    1. Create a Dockerfile.jvm:

      FROM registry.access.redhat.com/ubi8/openjdk-11:1.11
      
      ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
      
      COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
      COPY --chown=185 target/quarkus-app/*.jar /deployments/
      COPY --chown=185 target/quarkus-app/app/ /deployments/app/
      COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
      
      EXPOSE 8080
      USER 185
      
      ENTRYPOINT ["java", "-Dquarkus.http.host=0.0.0.0", "-Djava.util.logging.manager=org.jboss.logmanager.LogManager", "-Dquarkus.http.port=${DEVWORKSPACE_TELEMETRY_BACKEND_PORT}", "-jar", "/deployments/quarkus-run.jar"]
    2. Build and push the image:

      mvn package && \
      podman build -f src/main/docker/Dockerfile.jvm -t image:tag .
    Option B: Native image
    1. Create a Dockerfile.native:

      FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
      WORKDIR /work/
      RUN chown 1001 /work \
          && chmod "g+rwX" /work \
          && chown 1001:root /work
      COPY --chown=1001:root target/*-runner /work/application
      
      EXPOSE 8080
      USER 1001
      
      CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=${DEVWORKSPACE_TELEMETRY_BACKEND_PORT}"]
    2. Build and push the image:

      mvn package -Pnative -Dquarkus.native.container-build=true && \
      podman build -f src/main/docker/Dockerfile.native -t image:tag .
  2. Create a plugin.yaml devfile v2 file representing a Dev Workspace plugin that runs your custom backend in a Dev Workspace Pod. For more information about devfile v2, see Devfile v2 documentation.

    schemaVersion: 2.1.0
    metadata:
      name: devworkspace-telemetry-backend-plugin
      version: 0.0.1
      description: A Demo telemetry backend
      displayName: Devworkspace Telemetry Backend
    components:
      - name: devworkspace-telemetry-backend-plugin
        attributes:
          workspaceEnv:
            - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT
              value: '4167'
        container:
          image: <your_image>
          env:
            - name: WELCOME_MESSAGE
              value: 'hello world!'

    where:

    <your_image>
    The container image built in the previous step.
    WELCOME_MESSAGE
    Set the value for the welcome.message optional configuration property.
  3. Create a ConfigMap object that references the plugin.yaml file:

    $ oc create configmap --from-file=plugin.yaml -n openshift-devspaces telemetry-plugin-yaml
  4. Create a manifest.yaml file with a Deployment, a Service, and a Route to expose the Apache web server. The Deployment references this ConfigMap object and places the plugin.yaml in the /var/www/html directory.

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: apache
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: apache
      template:
        metadata:
          labels:
            app: apache
        spec:
          volumes:
            - name: plugin-yaml
              configMap:
                name: telemetry-plugin-yaml
                defaultMode: 420
          containers:
            - name: apache
              image: 'registry.redhat.io/rhscl/httpd-24-rhel7:latest'
              ports:
                - containerPort: 8080
                  protocol: TCP
              resources: {}
              volumeMounts:
                - name: plugin-yaml
                  mountPath: /var/www/html
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 25%
          maxSurge: 25%
      revisionHistoryLimit: 10
      progressDeadlineSeconds: 600
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: apache
    spec:
      ports:
        - protocol: TCP
          port: 8080
          targetPort: 8080
      selector:
        app: apache
      type: ClusterIP
    ---
    kind: Route
    apiVersion: route.openshift.io/v1
    metadata:
      name: apache
    spec:
      host: apache-che.apps-crc.testing
      to:
        kind: Service
        name: apache
        weight: 100
      port:
        targetPort: 8080
      wildcardPolicy: None
  5. Apply the manifest:

    $ {orch-cli} apply -f manifest.yaml

Verification

  • After the deployment has started, confirm that plugin.yaml is available in the web server:

    $ curl apache-che.apps-crc.testing/plugin.yaml

Add the telemetry plugin to Dev Workspaces so that workspace activity events are sent to your telemetry backend for collection and analysis.

Prerequisites

Procedure

  1. Add the telemetry plugin to the components field of an existing Dev Workspace:

    components:
      ...
      - name: telemetry-plugin
        plugin:
          uri: <telemetry_plugin_url>
  2. Start the Dev Workspace from the OpenShift Dev Spaces dashboard.
  3. Optional: Configure the CheCluster Custom Resource to apply the telemetry plugin as a default for all Dev Workspaces. Default plugins are applied on Dev Workspace startup for new and existing Dev Workspaces.

    spec:
      devEnvironments:
        defaultPlugins:
        - editor: eclipse/che-theia/next
          plugins:
          - '<telemetry_plugin_url>'

    where:

    editor
    The editor identification to set the default plugins for.
    plugins
    List of URLs to devfile v2 plugins.

Verification

  1. Verify that the telemetry plugin container is running in the Dev Workspace pod by checking the Workspace view within the editor.

    Dev Workspace telemetry plugin
  2. Edit files within the editor and observe their events in the example telemetry server’s logs.

8.3. Server logging

Fine-tune the log levels of individual loggers available in the OpenShift Dev Spaces server to control output verbosity and isolate issues during troubleshooting.

The log level of the whole OpenShift Dev Spaces server is configured globally using the cheLogLevel configuration property of the Operator. To set the global log level in installations not managed by the Operator, specify the CHE_LOG_LEVEL environment variable in the che ConfigMap.

It is possible to configure the log levels of the individual loggers in the OpenShift Dev Spaces server using the CHE_LOGGER_CONFIG environment variable.

The names of the loggers follow the class names of the internal server classes that use those loggers.

8.3.1. Configure log levels

Configure the log levels of individual loggers in the OpenShift Dev Spaces server using the CHE_LOGGER_CONFIG environment variable to control log verbosity and simplify troubleshooting.

Prerequisites

Procedure

  1. Configure the CheCluster Custom Resource. See Section 2.2, “Use the CLI to configure the CheCluster Custom Resource”.

    spec:
      components:
        cheServer:
          extraProperties:
            CHE_LOGGER_CONFIG: "<key1=value1,key2=value2>"

    where:

    <key1=value1,key2=value2>

    Comma-separated list of key-value pairs, where keys are the names of the loggers as seen in the OpenShift Dev Spaces server log output and values are the required log levels.

    For example, to configure debug mode for the WorkspaceManager:

    spec:
      components:
        cheServer:
          extraProperties:
            CHE_LOGGER_CONFIG: "org.eclipse.che.api.workspace.server.WorkspaceManager=DEBUG"

Verification

  • Verify that the log level is applied by checking the OpenShift Dev Spaces server logs:

    $ oc logs deployment/devspaces -n openshift-devspaces | grep -i "log level"

8.3.2. Log HTTP traffic

Log the HTTP traffic between the OpenShift Dev Spaces server and the API server of the Kubernetes or OpenShift cluster to troubleshoot communication issues and debug API errors.

Prerequisites

Procedure

  1. Configure the CheCluster Custom Resource:

    spec:
      components:
        cheServer:
          extraProperties:
            CHE_LOGGER_CONFIG: "che.infra.request-logging=TRACE"

Verification

  • Verify that HTTP traffic is logged in the OpenShift Dev Spaces server logs:

    $ oc logs deploy/devspaces -n openshift-devspaces | grep "request-logging"

8.4. Log collection with dsc

The dsc management tool provides commands to collect OpenShift Dev Spaces logs for troubleshooting and diagnostics. These commands automate log collection from the multiple containers that comprise a Red Hat OpenShift Dev Spaces installation in the OpenShift cluster.

dsc server:logs

Collects existing Red Hat OpenShift Dev Spaces server logs and stores them in a directory on the local machine. By default, logs are downloaded to a temporary directory on the machine. However, this can be overwritten by specifying the -d parameter. For example, to download OpenShift Dev Spaces logs to the /home/user/che-logs/ directory, use the command

dsc server:logs -d /home/user/che-logs/

When run, dsc server:logs prints a message in the console specifying the directory that stores the log files:

Red Hat OpenShift Dev Spaces logs will be available in '/tmp/chectl-logs/1648575098344'

If Red Hat OpenShift Dev Spaces is installed in a non-default project, dsc server:logs requires the -n <NAMESPACE> parameter. <NAMESPACE> is the project in which Red Hat OpenShift Dev Spaces was installed. For example, to get logs from OpenShift Dev Spaces in the my-namespace project, use the command

dsc server:logs -n my-namespace
dsc server:deploy
Logs are automatically collected during the OpenShift Dev Spaces installation when installed using dsc. As with dsc server:logs, the directory logs are stored in can be specified using the -d parameter.

8.5. Dev Workspace Operator metrics

The Dev Workspace Operator exposes workspace startup, failure, and performance metrics on port 8443 on the /metrics endpoint of the devworkspace-controller-metrics Service. The OpenShift in-cluster monitoring stack can scrape these metrics to help administrators track workspace health and diagnose startup failures.

8.5.1. Dev Workspace-specific metrics

The following tables describe the Dev Workspace-specific metrics exposed by the devworkspace-controller-metrics Service.

Expand
Table 8.1. Metrics
NameTypeDescriptionLabels

devworkspace_started_total

Counter

Number of Dev Workspace starting events.

source, routingclass

devworkspace_started_success_total

Counter

Number of Dev Workspaces successfully entering the Running phase.

source, routingclass

devworkspace_fail_total

Counter

Number of failed Dev Workspaces.

source, reason

devworkspace_startup_time

Histogram

Total time taken to start a Dev Workspace, in seconds.

source, routingclass

Expand
Table 8.2. Labels
NameDescriptionValues

source

The controller.devfile.io/devworkspace-source label of the Dev Workspace.

string

routingclass

The spec.routingclass of the Dev Workspace.

"basic|cluster|cluster-tls|web-terminal"

reason

The workspace startup failure reason.

"BadRequest|InfrastructureFailure|Unknown"

Expand
Table 8.3. Startup failure reasons
NameDescription

BadRequest

Startup failure due to an invalid devfile used to create a Dev Workspace.

InfrastructureFailure

Startup failure due to the following errors: CreateContainerError, RunContainerError, FailedScheduling, FailedMount.

Unknown

Unknown failure reason.

8.5.2. Dev Workspace Operator dashboard panels

The OpenShift web console custom dashboard is based on Grafana 6.x and displays the following metrics from the Dev Workspace Operator.

Note

Not all features for Grafana 6.x dashboards are supported as an OpenShift web console dashboard.

The Dev Workspace Metrics panel displays Dev Workspace-specific metrics.

Figure 8.1. The Dev Workspace Metrics panel

Grafana dashboard panels that contain metrics related to DevWorkspace startup
Average workspace start time
The average workspace startup duration.
Workspace starts
The number of successful and failed workspace startups.
Dev Workspace successes and failures
A comparison between successful and failed Dev Workspace startups.
Dev Workspace failure rate
The ratio between the number of failed workspace startups and the number of total workspace startups.
Dev Workspace startup failure reasons

A pie chart that displays the distribution of workspace startup failures:

  • BadRequest
  • InfrastructureFailure
  • Unknown

The Operator Metrics panel displays Operator-specific metrics.

Figure 8.2. The Operator Metrics panel

Grafana dashboard panels that contain Operator metrics
Webhooks in flight
A comparison between the number of different webhook requests.
Work queue depth
The number of reconcile requests that are in the work queue.
Memory
Memory usage for the Dev Workspace controller and the Dev Workspace webhook server.
Average reconcile counts per second (DWO)
The average per-second number of reconcile counts for the Dev Workspace controller.

Create the required ServiceMonitor and enable namespace monitoring to collect, store, and query Dev Workspace Operator metrics from the in-cluster Prometheus instance.

Prerequisites

  • You have an instance of OpenShift Dev Spaces installed and running in OpenShift.
  • You have an active oc session with administrative permissions to the destination OpenShift cluster. See Getting started with the CLI.
  • You have the devworkspace-controller-metrics Service with metrics exposed on port 8443. This is preconfigured by default.

Procedure

  1. Create the ServiceMonitor for detecting the Dev Workspace Operator metrics Service:

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: devworkspace-controller
      namespace: openshift-devspaces
    spec:
      endpoints:
        - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
          interval: 10s
          port: metrics
          scheme: https
          tlsConfig:
            insecureSkipVerify: true
      namespaceSelector:
        matchNames:
          - openshift-operators
      selector:
        matchLabels:
          app.kubernetes.io/name: devworkspace-controller

    where:

    namespace
    The OpenShift Dev Spaces namespace. The default is openshift-devspaces.
    interval
    The rate at which a target is scraped.
  2. Allow the in-cluster Prometheus instance to detect the ServiceMonitor by labeling the OpenShift Dev Spaces namespace:

    $ oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true

Verification

  1. For a fresh installation of OpenShift Dev Spaces, generate metrics by creating an OpenShift Dev Spaces workspace from the Dashboard.
  2. In the Administrator view of the OpenShift web console, go to Observe Metrics.
  3. Run a PromQL query to confirm that the metrics are available. For example, enter devworkspace_started_total and click Run queries. The query returns data points showing the total number of started workspaces.

Troubleshooting

  • To troubleshoot missing metrics, view the Prometheus container logs for possible RBAC-related errors.

    1. Get the name of the Prometheus pod:

      $ oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
    2. Print the last 20 lines of the Prometheus container logs from the Prometheus pod from the previous step:

      $ oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring

View Dev Workspace Operator metrics on a custom dashboard in the Administrator perspective of the OpenShift web console. This dashboard helps you monitor operator health and detect workspace provisioning issues.

Prerequisites

Procedure

  1. Create a ConfigMap for the dashboard definition in the openshift-config-managed project and apply the necessary label.

    1. $ oc create configmap grafana-dashboard-dwo \
        --from-literal=dwo-dashboard.json="$(curl https://raw.githubusercontent.com/devfile/devworkspace-operator/main/docs/grafana/openshift-console-dashboard.json)" \
        -n openshift-config-managed
      Note

      The previous command contains a link to material from the upstream community. This material represents the very latest available content and the most recent best practices. These tips have not yet been vetted by Red Hat’s QE department, and they have not yet been proven by a wide user group. Please, use this information cautiously.

    2. $ oc label configmap grafana-dashboard-dwo console.openshift.io/dashboard=true -n openshift-config-managed
      Note

      The dashboard definition is based on Grafana 6.x dashboards. Not all Grafana 6.x dashboard features are supported in the OpenShift web console.

Verification

  1. In the Administrator view of the OpenShift web console, go to Observe Dashboards.
  2. Go to Dashboard Dev Workspace Operator and verify that the dashboard panels contain data.

8.8. OpenShift Dev Spaces server monitoring

The OpenShift Dev Spaces server exposes JVM metrics such as memory usage and class loading on port 8087 on the /metrics endpoint. Monitoring these metrics helps administrators identify performance bottlenecks and plan server capacity.

OpenShift Dev Spaces exposes the JVM metrics on port 8087 of the che-host Service. Configure this behavior to support performance monitoring and capacity planning.

Prerequisites

Procedure

  1. Configure the CheCluster Custom Resource. See Section 2.2, “Use the CLI to configure the CheCluster Custom Resource”.

    spec:
      components:
        metrics:
          enable: <boolean>

    where:

    <boolean>
    true to enable, false to disable.

Verification

  • Verify the metrics endpoint is accessible:

    oc get service che-host -n openshift-devspaces -o jsonpath='{.spec.ports[?(@.port==8087)]}'

Create the required ServiceMonitor, Role, and RoleBinding objects to collect, store, and query JVM metrics for the OpenShift Dev Spaces Server from the in-cluster Prometheus instance.

Prerequisites

Procedure

  1. Create the ServiceMonitor for detecting the OpenShift Dev Spaces JVM metrics Service:

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: che-host
      namespace: openshift-devspaces
    spec:
      endpoints:
        - interval: 10s
          port: metrics
          scheme: http
      namespaceSelector:
        matchNames:
          - openshift-devspaces
      selector:
        matchLabels:
          app.kubernetes.io/name: devspaces

    where:

    namespace
    The OpenShift Dev Spaces namespace. The default is openshift-devspaces.
    interval
    The rate at which a target is scraped.
  2. Create a Role to allow Prometheus to view the metrics:

    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: prometheus-k8s
      namespace: openshift-devspaces
    rules:
      - verbs:
          - get
          - list
          - watch
        apiGroups:
          - ''
        resources:
          - services
          - endpoints
          - pods

    where:

    namespace
    The OpenShift Dev Spaces namespace. The default is openshift-devspaces.
  3. Create a RoleBinding to bind the Role to the Prometheus service account:

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: view-devspaces-openshift-monitoring-prometheus-k8s
      namespace: openshift-devspaces
    subjects:
      - kind: ServiceAccount
        name: prometheus-k8s
        namespace: openshift-monitoring
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: prometheus-k8s

    where:

    namespace
    The OpenShift Dev Spaces namespace. The default is openshift-devspaces.
  4. Allow the in-cluster Prometheus instance to detect the ServiceMonitor by labeling the OpenShift Dev Spaces namespace:

    $ oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true

Verification

  1. In the Administrator view of the OpenShift web console, go to Observe Metrics.
  2. Run a PromQL query to confirm that the metrics are available. For example, enter process_uptime_seconds{job="che-host"} and click Run queries. The query returns data points showing the OpenShift Dev Spaces Server uptime.

Troubleshooting

To troubleshoot missing metrics, view the Prometheus container logs for possible RBAC-related errors.

  1. Get the name of the Prometheus pod:

    $ oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
  2. Print the last 20 lines of the Prometheus container logs from the Prometheus pod from the previous step:

    $ oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring

View OpenShift Dev Spaces Server JVM metrics on a custom dashboard in the Administrator perspective of the OpenShift web console. This dashboard helps you identify performance bottlenecks and monitor server health.

Prerequisites

Procedure

  1. Create a ConfigMap for the dashboard definition in the openshift-config-managed project and apply the necessary label.

    1. $ oc create configmap grafana-dashboard-devspaces-server \
        --from-literal=devspaces-server-dashboard.json="$(curl https://raw.githubusercontent.com/eclipse-che/che-server/main/docs/grafana/openshift-console-dashboard.json)" \
        -n openshift-config-managed
      Note

      The previous command contains a link to material from the upstream community. This material represents the very latest available content and the most recent best practices. These tips have not yet been vetted by Red Hat’s QE department, and they have not yet been proven by a wide user group. Please, use this information cautiously.

    2. $ oc label configmap grafana-dashboard-devspaces-server console.openshift.io/dashboard=true -n openshift-config-managed
      Note

      The dashboard definition is based on Grafana 6.x dashboards. Not all Grafana 6.x dashboard features are supported in the OpenShift web console.

Verification

  1. In the Administrator view of the OpenShift web console, go to Observe Dashboards.
  2. Go to Dashboard Che Server JVM and verify that the dashboard panels contain data.

    Figure 8.3. Quick Facts

    The *JVM quick facts* panel

    Figure 8.4. JVM Memory

    The *JVM Memory* panel

    Figure 8.5. JVM Misc

    The *JVM Misc* panel

    Figure 8.6. JVM Memory Pools (heap)

    The *JVM Memory Pools (heap)* panel

    Figure 8.7. JVM Memory Pools (Non-Heap)

    The *JVM Memory Pools (non-heap)* panel

    Figure 8.8. Garbage Collection

    The *JVM garbage collection* panel

    Figure 8.9. Class loading

    The *JVM class loading* panel

    Figure 8.10. Buffer Pools

    The *JVM buffer pools* panel
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top