指定策略

NewTracerProvider时,可传入WithSampler选项

tracerProvider := tracesdk.NewTracerProvider(
    tracesdk.WithSampler(..),
    // ...
)

如果不传,则默认是tracesdk.ParentBased(tracesdk.AlwaysSample())

/// go.opentelemetry.io/otel/sdk@v1.11.2/trace/provider.go
func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
    o := tracerProviderConfig{
        // ...
    }
    // ...
    o = ensureValidTracerProviderConfig(o)
    tp := &TracerProvider{
        namedTracer: make(map[instrumentation.Scope]*tracer),
        sampler:     o.sampler,
        // ...
    }
    // ...
    return tp
}

func ensureValidTracerProviderConfig(cfg tracerProviderConfig) tracerProviderConfig {
    if cfg.sampler == nil {
        cfg.sampler = ParentBased(AlwaysSample())
    }
    // ...
    return cfg
}

调用策略

创建span时,传递trace_id、name、attributes给sampler,让其计算span是否采样

func (tr *tracer) newSpan(ctx context.Context, name string, config *trace.SpanConfig) trace.Span {
    // ...
    samplingResult := tr.provider.sampler.ShouldSample(SamplingParameters{
        ParentContext: ctx,
        TraceID:       tid,
        Name:          name,
        Kind:          config.SpanKind(),
        Attributes:    config.Attributes(),
        Links:         config.Links(),
    })
    // ...
    return tr.newRecordingSpan(parentSpanContext, spanContext, name, samplingResult, config)
}

策略:ParentBased

// go.opentelemetry.io/otel/sdk@v1.11.2/trace/sampling.go
type parentBased struct {
    root   Sampler
    config samplerConfig
}

func ParentBased(root Sampler, samplers ...ParentBasedSamplerOption) Sampler {
    return parentBased{
        root:   root,
        config: configureSamplersForParentBased(samplers),
    }
}

func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) samplerConfig {
    c := samplerConfig{
        remoteParentSampled:    AlwaysSample(),
        remoteParentNotSampled: NeverSample(),
        localParentSampled:     AlwaysSample(),
        localParentNotSampled:  NeverSample(),
    }

    for _, so := range samplers {
        c = so.apply(c)
    }

    return c
}