如何在Trace请求头中添加Trace ID等B3传播字段?
问题分析与解决
你的代码里有几个关键问题导致B3请求头没有生成:
1. 手动注入时目标对象错误
你调用propagation.inject时传的是空对象{},这意味着Trace信息被注入到了一个无意义的空对象里,根本不会关联到实际请求的头信息中。你需要把实际的请求头对象传进去。
2. Span未绑定到当前上下文
你创建的span没有激活并关联到当前上下文,context.active()获取的是默认上下文,不包含你生成的Trace信息,所以注入操作等于无效。
3. 工具类导入错误与缺失HTTP instrumentation
WebTracerProvide拼写错误,应该是WebTracerProviderOTLPTraceExporter的导入路径错误,Web环境下应该从@opentelemetry/exporter-trace-otlp-http导入,而非@opentelemetry/instrumentation- 没有注册HTTP请求的instrumentation(比如fetch/XHR),导致无法自动给请求注入Trace头,手动注入也没关联到请求
修正后的代码示例
步骤1:安装必要依赖
确保你安装了所需包:
npm install @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/propagator-b3 @opentelemetry/exporter-trace-otlp-http @opentelemetry/instrumentation-fetch @opentelemetry/instrumentation-xml-http-request @opentelemetry/resources
步骤2:修正代码
import { Span, trace, propagation, context, defaultTextMapSetter } from '@opentelemetry/api'; import { B3Propagator, B3InjectEncoding } from '@opentelemetry/propagator-b3'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'; import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request'; import { Resource } from '@opentelemetry/resources'; import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { WebTracerProvider } from '@opentelemetry/sdk-trace-web'; const collectorOptions = { url: 'https://<mylocalhost>/v1/traces', headers: { 'Content-Type': 'application/json' }, concurrencyLimit: 10 }; function init(): void { // 注册HTTP请求 instrumentation,自动处理请求头注入 registerInstrumentations({ instrumentations: [ new FetchInstrumentation(), new XMLHttpRequestInstrumentation() ] }); const resource = Resource.default().merge(new Resource({ // 可以添加服务标识等资源信息,可选 'service.name': 'your-web-app' })); const provider = new WebTracerProvider({ resource }); const exporter = new OTLPTraceExporter(collectorOptions); const processor = new BatchSpanProcessor(exporter); provider.addSpanProcessor(processor); // 注册B3 propagator,指定多header格式 provider.register({ propagator: new B3Propagator({ injectEncoding: B3InjectEncoding.MULTI_HEADER }) }); } init(); // 手动处理请求的示例(如果不用自动instrumentation的话) export async function tracing(): Promise<void> { const tracer = trace.getTracer('tracer'); // 使用startActiveSpan自动将span绑定到当前上下文 await tracer.startActiveSpan('manual-request-span', async (span) => { span.setAttribute('clientId', '123'); // 创建请求头对象,用于注入Trace信息 const requestHeaders = new Headers(); // 将当前上下文的Trace信息注入到请求头 propagation.inject(context.active(), requestHeaders, defaultTextMapSetter); // 发起请求,使用注入后的头 await fetch('your-api-url', { method: 'GET', headers: requestHeaders }); span.end(); }); }
关键修正点说明
- 注册HTTP Instrumentation:
FetchInstrumentation和XMLHttpRequestInstrumentation会自动拦截浏览器的fetch/XHR请求,将B3 Trace头注入到请求中,无需手动调用propagation.inject - Span上下文绑定:用
tracer.startActiveSpan替代startSpan,自动将span设置为当前上下文的活跃span,确保context.active()能获取到包含Trace信息的上下文 - 手动注入的正确方式:如果需要手动处理请求,要将Trace信息注入到实际的请求头对象(如
Headers实例),再将该头对象传入请求 - 修正导入错误:修正拼写错误的类名和错误的包导入路径
内容的提问来源于stack exchange,提问作者BlueSea
相关产品推荐
相关产品推荐

