opentelemetry-go的采样策略
指定策略
在
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
}