...
1
16
17 package tracing
18
19 import (
20 "context"
21 "net/http"
22
23 "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
24 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
25 "go.opentelemetry.io/otel/propagation"
26 "go.opentelemetry.io/otel/sdk/resource"
27 sdktrace "go.opentelemetry.io/otel/sdk/trace"
28 semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
29 oteltrace "go.opentelemetry.io/otel/trace"
30
31 "k8s.io/client-go/transport"
32 "k8s.io/component-base/tracing/api/v1"
33 )
34
35
36 type TracerProvider interface {
37 oteltrace.TracerProvider
38 Shutdown(context.Context) error
39 }
40
41 type noopTracerProvider struct {
42 oteltrace.TracerProvider
43 }
44
45 func (n *noopTracerProvider) Shutdown(context.Context) error {
46 return nil
47 }
48
49 func NewNoopTracerProvider() TracerProvider {
50 return &noopTracerProvider{TracerProvider: oteltrace.NewNoopTracerProvider()}
51 }
52
53
54 func NewProvider(ctx context.Context,
55 tracingConfig *v1.TracingConfiguration,
56 addedOpts []otlptracegrpc.Option,
57 resourceOpts []resource.Option,
58 ) (TracerProvider, error) {
59 if tracingConfig == nil {
60 return NewNoopTracerProvider(), nil
61 }
62 opts := append([]otlptracegrpc.Option{}, addedOpts...)
63 if tracingConfig.Endpoint != nil {
64 opts = append(opts, otlptracegrpc.WithEndpoint(*tracingConfig.Endpoint))
65 }
66 opts = append(opts, otlptracegrpc.WithInsecure())
67 exporter, err := otlptracegrpc.New(ctx, opts...)
68 if err != nil {
69 return nil, err
70 }
71 res, err := resource.New(ctx, resourceOpts...)
72 if err != nil {
73 return nil, err
74 }
75
76
77
78 sampler := sdktrace.NeverSample()
79
80 if tracingConfig.SamplingRatePerMillion != nil && *tracingConfig.SamplingRatePerMillion > 0 {
81 sampler = sdktrace.TraceIDRatioBased(float64(*tracingConfig.SamplingRatePerMillion) / float64(1000000))
82 }
83
84 bsp := sdktrace.NewBatchSpanProcessor(exporter)
85 tp := sdktrace.NewTracerProvider(
86 sdktrace.WithSampler(sdktrace.ParentBased(sampler)),
87 sdktrace.WithSpanProcessor(bsp),
88 sdktrace.WithResource(res),
89 )
90 return tp, nil
91 }
92
93
94 func WithTracing(handler http.Handler, tp oteltrace.TracerProvider, spanName string) http.Handler {
95 opts := []otelhttp.Option{
96 otelhttp.WithPropagators(Propagators()),
97 otelhttp.WithTracerProvider(tp),
98 }
99 wrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
100
101
102 if r.URL != nil {
103 oteltrace.SpanFromContext(r.Context()).SetAttributes(semconv.HTTPTarget(r.URL.RequestURI()))
104 }
105 handler.ServeHTTP(w, r)
106 })
107
108
109 return otelhttp.NewHandler(wrappedHandler, spanName, opts...)
110 }
111
112
113
114
115
116
117
118 func WrapperFor(tp oteltrace.TracerProvider) transport.WrapperFunc {
119 return func(rt http.RoundTripper) http.RoundTripper {
120 opts := []otelhttp.Option{
121 otelhttp.WithPropagators(Propagators()),
122 otelhttp.WithTracerProvider(tp),
123 }
124
125
126 return otelhttp.NewTransport(rt, opts...)
127 }
128 }
129
130
131 func Propagators() propagation.TextMapPropagator {
132 return propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
133 }
134
View as plain text