All Products
Search
Document Center

Managed Service for OpenTelemetry:Return a trace ID in an HTTP response header for Java and Node.js applications

Last Updated:Nov 21, 2023

This topic describes how to return a trace ID in an HTTP response header for Java and Node.js applications.

Java applications

By default, a trace ID is specified only in an HTTP request header. If you want the trace ID to be returned in an HTTP response header, you can follow the instructions described in this topic to add an extension of the OpenTelemetry Java agent, which provides additional features based on the OpenTelemetry Java agent.

You can use one of the following methods:

  • Method 1: Use the out-of-the-box service. You can use the extension of the OpenTelemetry Java agent packaged by Managed Service for OpenTelemetry. This way, a trace ID can be returned in an HTTP response header with ease.

  • Method 2: Create an extension of the OpenTelemetry Java agent. If the extension of the OpenTelemetry Java agent provided by Managed Service for OpenTelemetry cannot meet your business requirements, you can use this method to create an extension of the OpenTelemetry Java agent and package the extension as a JAR file.

Method 1: Use the out-of-the-box service

Download URL of the extension: ot-java-agent-extension-1.28.0.jar.

Managed Service for OpenTelemetry provides the basic extension of the OpenTelemetry Java agent. To ensure that a trace ID and a span ID are returned in the HTTP response header, you need to only modify the startup parameters to add the full path of the JAR file.

How to modify the startup parameters

Run the following command to add the otel.javaagent.extensions parameter to the original startup parameters: -Dotel.javaagent.extensions=/path/to/opentelemetry-java-agent-extension.jar

Example of the complete startup commands:

java -javaagent:path/to/opentelemetry-javaagent.jar \
 -Dotel.javaagent.extensions=path/to/opentelemetry-java-agent-extension.jar \
 -Dotel.exporter.otlp.headers=Authentication=<token> \
 -Dotel.exporter.otlp.endpoint=<endpoint> \
 -Dotel.metrics.exporter=none \
 -jar your-app.jar

Method 2: Create an extension of the OpenTelemetry Java agent

Prerequisites

  • The OpenTelemetry Java agent is configured.

  • The version of the OpenTelemetry Java agent is 1.24.0 or later.

  1. Write an extension of the OpenTelemetry Java agent.

    1. Create a new project.

    2. Add the following dependencies to the pom.xml file.

      The version of the Opentelemetry-javaagent dependency must be the same as the version of the OpenTelemetry Java agent.

       <dependencies>
       <dependency>
       <groupId>com.google.auto.service</groupId>
       <artifactId>auto-service</artifactId>
       <version>1.1.1</version>
       </dependency>
      
       <dependency>
       <groupId>io.opentelemetry.javaagent</groupId>
       <artifactId>opentelemetry-javaagent</artifactId>
       <version>1.28.0</version>
       <scope>compile</scope>
       </dependency>
       </dependencies>

    3. Create an AgentHttpResponseCustomizer class to implement HttpServerResponseCustomizer.

      package org.example;
      
      import com.google.auto.service.AutoService;
      import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.trace.Span;
      import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.trace.SpanContext;
      import io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context;
      import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizer;
      import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
      
      @AutoService(HttpServerResponseCustomizer.class)
      public class AgentHttpResponseCustomizer implements HttpServerResponseCustomizer {
       @Override
       public <RESPONSE> void customize(Context context, RESPONSE response, HttpServerResponseMutator<RESPONSE> responseMutator) {
       SpanContext spanContext = Span.fromContext(context).getSpanContext();
       String traceId = spanContext.getTraceId();
       String spanId = spanContext.getSpanId();
      
       // Add the trace ID and the span ID to the HTTP response header. You can change the field name of the header based on your requirements.
       responseMutator.appendHeader(response, "TraceId", traceId);
       responseMutator.appendHeader(response, "SpanId", spanId);
       }
      }
  2. Build an extension of the OpenTelemetry Java agent.

    Package the project into a JAR file and store the JAR file in the target directory.

    mvn clean package
  3. Load an extension of the OpenTelemetry Java agent when you start an application.

    Run the following command to add the otel.javaagent.extensions parameter to the original startup parameters: -Dotel.javaagent.extensions=/path/to/opentelemetry-java-agent-extension.jar.

    Example of the complete startup commands:

    java -javaagent:path/to/opentelemetry-javaagent.jar \
     -Dotel.javaagent.extensions=path/to/opentelemetry-java-agent-extension.jar \
     -Dotel.exporter.otlp.headers=Authentication=<token> \
     -Dotel.exporter.otlp.endpoint=<endpoint> \
     -Dotel.metrics.exporter=none 
     -jar yourapp.jar

Node.js applications

  1. (Optional) Run the demo project to integrate your Node.js application with OpenTelemetry. Download URL: node.js-demo.

    If your Node.js application was integrated with OpenTelemetry, you do not need to download the demo project. You can follow the instructions in the next step to modify the code of the Node.js application.

  2. Modify the code to create the Http instrumentation.

    When you create the Http instrumentation, you can specify HttpInstrumentationConfig parameters, such as the responseHook parameter. The responseHook parameter helps modify the response generation procedure. You can use the parameter to add custom content to the response header before the response is returned. For example, you can add a trace ID to the response header.

    ...
    
    // The content to be replaced.
    // registerInstrumentations({
    // tracerProvider: provider,
    // instrumentations: [new HttpInstrumentation(), ExpressInstrumentation],
    // });
    
    
    
    
    const httpInstrumentation = new HttpInstrumentation({
     // Add a custom response hook.
     responseHook: (span, response) => {
    
     // Obtain the trace ID and the span ID from the context.
     const traceId = span.spanContext().traceId;
     const spanId = span.spanContext().spanId;
    
     // Add the trace ID and the span ID to the HTTP response header.
     response.setHeader('TraceId', traceId);
     response.setHeader('SpanId', spanId);
     // Return the response object.
     return response;
     },
    });
    
    
    registerInstrumentations({
     tracerProvider: provider,
     instrumentations: [httpInstrumentation, ExpressInstrumentation],
    });
    
    ...