123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package otel
- import (
- "encoding/binary"
- "errors"
- "fmt"
- "os"
- "strconv"
- "strings"
- sdktrace "go.opentelemetry.io/otel/sdk/trace"
- "go.opentelemetry.io/otel/trace"
- )
- const (
- tracesSamplerKey = "OTEL_TRACES_SAMPLER"
- tracesSamplerArgKey = "OTEL_TRACES_SAMPLER_ARG"
- samplerTraceIDRatio = "traceidratio"
- )
- var (
- errNegativeTraceIDRatio = errors.New("invalid trace ID ratio: less than 0.0")
- errGreaterThanOneTraceIDRatio = errors.New("invalid trace ID ratio: greater than 1.0")
- )
- type samplerArgParseError struct {
- parseErr error
- }
- func (e samplerArgParseError) Error() string {
- return fmt.Sprintf("parsing sampler argument: %s", e.parseErr.Error())
- }
- func (e samplerArgParseError) Unwrap() error {
- return e.parseErr
- }
- type traceIDRatioSampler struct {
- traceIDUpperBound uint64
- description string
- }
- func (ts traceIDRatioSampler) ShouldSample(p sdktrace.SamplingParameters) sdktrace.SamplingResult {
- psc := trace.SpanContextFromContext(p.ParentContext)
- x := binary.BigEndian.Uint64(p.TraceID[len(p.TraceID)-8:]) >> 1
- if x < ts.traceIDUpperBound {
- return sdktrace.SamplingResult{
- Decision: sdktrace.RecordAndSample,
- Tracestate: psc.TraceState(),
- }
- }
- return sdktrace.SamplingResult{
- Decision: sdktrace.Drop,
- Tracestate: psc.TraceState(),
- }
- }
- func (ts traceIDRatioSampler) Description() string {
- return ts.description
- }
- func traceIDRatioBased(fraction float64) sdktrace.Sampler {
- if fraction >= 1 {
- return sdktrace.AlwaysSample()
- }
- if fraction <= 0 {
- fraction = 0
- }
- return &traceIDRatioSampler{
- traceIDUpperBound: uint64(fraction * (1 << 63)),
- description: fmt.Sprintf("traceIDRatioBased{%g}", fraction),
- }
- }
- func parseTraceIDRatio(arg string) (sdktrace.Sampler, error) {
- v, err := strconv.ParseFloat(arg, 64)
- if err != nil {
- return traceIDRatioBased(1.0), samplerArgParseError{err}
- }
- if v < 0.0 {
- return traceIDRatioBased(0.0), errNegativeTraceIDRatio
- }
- if v > 1.0 {
- return traceIDRatioBased(1.0), errGreaterThanOneTraceIDRatio
- }
- return traceIDRatioBased(v), nil
- }
- func addTraceIDRatioSampler(opts []sdktrace.TracerProviderOption) ([]sdktrace.TracerProviderOption, error) {
- samplerName, ok := os.LookupEnv(tracesSamplerKey)
- if !ok {
- return opts, nil
- }
- if strings.ToLower(strings.TrimSpace(samplerName)) != samplerTraceIDRatio {
- return opts, nil
- }
- samplerArg, hasSamplerArg := os.LookupEnv(tracesSamplerArgKey)
- samplerArg = strings.TrimSpace(samplerArg)
- var (
- sampler sdktrace.Sampler
- err error
- )
- if !hasSamplerArg {
- sampler = traceIDRatioBased(1.0)
- } else {
- sampler, err = parseTraceIDRatio(samplerArg)
- }
- return append(opts, sdktrace.WithSampler(sampler)), err
- }
|