By default, the OpenTelemetry agent includes trace IDs only in HTTP request headers. Returning trace IDs in HTTP response headers lets API consumers and frontend systems correlate specific HTTP responses with their backend distributed traces -- making it straightforward to debug user-reported issues and trace requests end to end.
This topic covers Java and Node.js implementations:
| Language | Approach | Effort | When to use |
|---|---|---|---|
| Java | Pre-built extension JAR | Low | Default choice. Works out of the box with no custom code. |
| Java | Custom agent extension | Medium | The pre-built extension does not meet your requirements. |
| Node.js | responseHook in HttpInstrumentation | Low | Standard approach for Node.js applications. |
Java
Both methods below use the OpenTelemetry Java agent extension mechanism to inject TraceId and SpanId headers into HTTP responses.
Method 1: Use the pre-built extension
Managed Service for OpenTelemetry provides a pre-built extension JAR that adds TraceId and SpanId headers to every HTTP response automatically. No custom code is required.
Download the extension JAR: ot-java-agent-extension-1.28.0.jar.
Add
-Dotel.javaagent.extensionsto the startup command, pointing to the downloaded JAR: Replace the following placeholders with actual values:Placeholder Description <token>Authentication token for the OTLP exporter <endpoint>OTLP endpoint URL of your Managed Service for OpenTelemetry instance 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: Build a custom extension
If the pre-built extension does not meet your requirements, build a custom OpenTelemetry Java agent extension and package it as a JAR file.
Prerequisites
Before you begin, make sure that you have:
The OpenTelemetry Java agent configured
The OpenTelemetry Java agent version 1.24.0 or later
Procedure
Create a project and add dependencies. Add the following to the
pom.xmlfile:ImportantThe
opentelemetry-javaagentdependency version must match the version of the OpenTelemetry Java agent that your application uses.<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>Create the
AgentHttpResponseCustomizerclass. This class implementsHttpServerResponseCustomizerto inject the trace ID and span ID into HTTP responses: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 trace ID and span ID to the HTTP response header. // Change the header names to match your requirements. responseMutator.appendHeader(response, "TraceId", traceId); responseMutator.appendHeader(response, "SpanId", spanId); } }Build the extension JAR. The JAR file is generated in the
targetdirectory.mvn clean packageStart the application with the extension. Add
-Dotel.javaagent.extensionsto the startup command, pointing to the built JAR: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
For Node.js applications, add a responseHook to HttpInstrumentation to inject trace IDs into HTTP response headers.
Procedure
(Optional) If the Node.js application is not yet integrated with OpenTelemetry, download the Node.js demo project and follow it to set up the integration first.
Modify the
HttpInstrumentationinitialization to include aresponseHook. This hook adds the trace ID and span ID to every HTTP response:// Replace the default HttpInstrumentation initialization: // // registerInstrumentations({ // tracerProvider: provider, // instrumentations: [new HttpInstrumentation(), ExpressInstrumentation], // }); // Create HttpInstrumentation with a custom responseHook: const httpInstrumentation = new HttpInstrumentation({ responseHook: (span, response) => { // Get the trace ID and span ID from the span context const traceId = span.spanContext().traceId; const spanId = span.spanContext().spanId; // Add trace ID and span ID to the HTTP response header response.setHeader('TraceId', traceId); response.setHeader('SpanId', spanId); return response; }, }); registerInstrumentations({ tracerProvider: provider, instrumentations: [httpInstrumentation, ExpressInstrumentation], });