otel 源码阅读(三)
2022-03-08 本文已影响0人
迪克dike
Tracer
Tracer的逻辑很简单,Tracer接口就一个Start方法,用来生成新的span。
与之相对于的tracer结构体,可以说是非常简单
type tracer struct {
provider *TracerProvider // 上层的provider
instrumentationLibrary instrumentation.Library // 没啥用,可以忽略
}
然后是实现Tracer接口的Start方法
func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanStartOption) (context.Context, trace.Span) {
config := trace.NewSpanStartConfig(options...) // 配置
// 记录从当前span创建的子span的个数(如果是recordingSpan)
if p := trace.SpanFromContext(ctx); p != nil {
if sdkSpan, ok := p.(*recordingSpan); ok {
sdkSpan.addChild()
}
}
s := tr.newSpan(ctx, name, &config) // 从当前携带span信息的ctx创建新的子span
if rw, ok := s.(ReadWriteSpan); ok && s.IsRecording() {
sps, _ := tr.provider.spanProcessors.Load().(spanProcessorStates)
for _, sp := range sps {
sp.sp.OnStart(ctx, rw)
}
}
if rtt, ok := s.(runtimeTracer); ok {
ctx = rtt.runtimeTrace(ctx)
}
return trace.ContextWithSpan(ctx, s), s
}