You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为OpenTelemetry Java Agent配置X-CorrelationToken头同步至New Relic APM

问题:通过OpenTelemetry Java Agent将X-CorrelationToken同步至New Relic APM

背景

前端会给所有后端API请求发送X-CorrelationToken请求头,该Token会写入每条日志,方便出错时通过ELK检索日志。需要将这个请求头的值作为属性同步到New Relic APM,实现日志与服务链路的关联。

此前实现方式(New Relic Java Agent)

通过newrelic.yml配置即可实现需求:

transaction_events:
   custom_request_headers:
     - header_name: "X-CorrelationToken"

当前问题(OpenTelemetry Java Agent)

使用官方OpenTelemetry Java Agent时,尝试了以下配置参数,但均无效——服务的New Relic链路或Span中未出现X-CorrelationToken属性:

otel.instrumentation.http.client.capture-request-headers=X-CorrelationToken
otel.instrumentation.http.capture-headers.client.request=X-CorrelationToken
otel.instrumentation.common.experimental.capture-http-headers.client.request=X-CorrelationToken
otel.instrumentation.common.experimental.capture-http-headers.server.request=X-CorrelationToken
otel.instrumentation.http.capture-headers.server.request=X-CorrelationToken

期望实现的效果与New Relic Java Agent一致,即X-CorrelationToken属性显示在类似下图的位置:
New Relic中X-CorrelationToken属性展示

解决方案

1. 正确配置OpenTelemetry HTTP头捕获参数

OpenTelemetry Java Agent的HTTP头捕获参数需区分服务端和客户端场景,且不同版本参数可能存在差异:

  • 若为服务端接收前端请求,使用服务端头捕获参数:
    otel.instrumentation.http.server.capture-headers=X-CorrelationToken
    
  • 若为后端作为客户端调用其他服务,使用客户端头捕获参数:
    otel.instrumentation.http.client.capture-headers=X-CorrelationToken
    

注:确保使用较新的稳定版OpenTelemetry Agent,旧版本可能不支持上述参数,建议升级至最新版。

2. 自定义Span Processor手动添加属性

若配置参数无效,可通过自定义Span Processor提取请求头并添加到Span属性:

  1. 创建自定义Span Processor类:
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SpanProcessor;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class CorrelationTokenSpanProcessor implements SpanProcessor {
    @Override
    public void onStart(Context parentContext, ReadWriteSpan span) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String correlationToken = request.getHeader("X-CorrelationToken");
            if (correlationToken != null && !correlationToken.isEmpty()) {
                span.setAttribute("X-CorrelationToken", correlationToken);
            }
        }
    }

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

    @Override
    public void onEnd(ReadableSpan span) {}

    @Override
    public boolean isEndRequired() {
        return false;
    }
}
  1. 将自定义Span Processor注册到OpenTelemetry SDK:
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;

public class OpenTelemetryConfig {
    public static OpenTelemetrySdk createOpenTelemetry() {
        OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter.builder()
                .setEndpoint("https://otlp.nr-data.net:4317")
                .addHeader("api-key", "YOUR_NEW_RELIC_LICENSE_KEY")
                .build();

        SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
                .addSpanProcessor(SimpleSpanProcessor.create(exporter))
                .addSpanProcessor(new CorrelationTokenSpanProcessor())
                .build();

        return OpenTelemetrySdk.builder()
                .setTracerProvider(tracerProvider)
                .buildAndRegisterGlobal();
    }
}

注:Spring Boot项目可通过@Configuration类注册该配置,确保自定义处理器被加载。

3. 配置日志与链路关联

为让日志中的X-CorrelationToken与New Relic Span关联,需配置日志框架(如Logback、Log4j2)的OpenTelemetry Appender,将Span属性同步到日志:
以Logback为例,添加OpenTelemetry Appender:

<appender name="OTEL" class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %X{X-CorrelationToken} - %msg %ex%n</pattern>
    </encoder>
</appender>

同时通过请求拦截器将Token写入MDC:

import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class CorrelationTokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String correlationToken = request.getHeader("X-CorrelationToken");
        if (correlationToken != null) {
            MDC.put("X-CorrelationToken", correlationToken);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        MDC.remove("X-CorrelationToken");
    }
}

内容的提问来源于stack exchange,提问作者John Little

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 10:35:01