如何将OpenTracing上下文传递到Go命令行工具并初始化对应上下文?
基于已有trace_id、span_id初始化OpenTracing上下文的实现思路
以下是三种常用的可行实现方案,你可以根据你的技术栈场景选择:
直接构造对应链路实现的SpanContext实例
OpenTracing的SpanContext本身是通用接口,不同的链路追踪实现(Jaeger、Zipkin等)都有对应的结构体实现,你可以直接把已有的trace_id、span_id转换成对应类型后初始化实例即可,下面是Jaeger的示例代码:import ( "context" "github.com/opentracing/opentracing-go" "github.com/uber/jaeger-client-go" ) // 转换字符串形式的trace_id、span_id为Jaeger内部类型 traceID, err := jaeger.TraceIDFromString("你拿到的trace_id字符串") if err != nil { // 处理trace_id格式错误逻辑 } spanID, err := jaeger.SpanIDFromString("你拿到的span_id字符串") if err != nil { // 处理span_id格式错误逻辑 } // 构造SpanContext实例 spanCtx := jaeger.NewSpanContext( traceID, spanID, 0, // 父spanID,无父span时传0即可 true, // 采样标记,按实际业务需求赋值 nil, // 需要传递的baggage键值对,无额外内容传nil )通过模拟Extract流程获取通用SpanContext
如果你不想和具体的链路实现强绑定,可以复用OpenTracing标准的Extract能力,把trace_id、span_id按照对应实现的序列化规则放到自定义Carrier中,再调用Extract方法拿到通用SpanContext,这种方式和你之前用到的从HTTP Header提取上下文的逻辑完全一致,只是替换了Carrier类型:import ( "context" "fmt" "github.com/opentracing/opentracing-go" ) // 按照你使用的链路实现要求的格式组装Carrier,以下是Jaeger的TextMap格式示例 carrier := opentracing.TextMapCarrier{ "uber-trace-id": fmt.Sprintf("%s:%s:0:1", traceIDStr, spanIDStr), } spanCtx, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, carrier) if err != nil { // 处理提取失败逻辑 }把SpanContext嵌入Go标准Context实现传递
拿到SpanContext之后,你可以基于它生成新的子Span,再嵌入Go标准context中在CLI应用的函数间传递:// 基于父SpanContext启动新的子Span span := opentracing.StartSpan("你的CLI操作名称", opentracing.ChildOf(spanCtx)) defer span.Finish() // 嵌入context后即可在应用内传递链路信息 ctx := opentracing.ContextWithSpan(context.Background(), span)
注意:不同链路实现的trace_id/span_id格式、Carrier对应的键名、序列化规则都有差异,需要根据你实际使用的组件调整对应逻辑,有额外baggage需要传递时对应补充到SpanContext或者Carrier中即可。
内容的提问来源于stack exchange,提问作者f0rt
相关产品推荐
相关产品推荐

