Tracer
Tracer的邏輯很簡單,Tracer接口就一個Start方法,用來生成新的span。
與之相對于的tracer結(jié)構(gòu)體,可以說是非常簡單
type tracer struct {
provider *TracerProvider // 上層的provider
instrumentationLibrary instrumentation.Library // 沒啥用,可以忽略
}
然后是實現(xiàn)Tracer接口的Start方法
func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanStartOption) (context.Context, trace.Span) {
config := trace.NewSpanStartConfig(options...) // 配置
// 記錄從當(dāng)前span創(chuàng)建的子span的個數(shù)(如果是recordingSpan)
if p := trace.SpanFromContext(ctx); p != nil {
if sdkSpan, ok := p.(*recordingSpan); ok {
sdkSpan.addChild()
}
}
s := tr.newSpan(ctx, name, &config) // 從當(dāng)前攜帶span信息的ctx創(chuàng)建新的子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
}