Skip to content

Commit e397417

Browse files
committed
Add tracing package with sharable code that configures tracing provider
The tracing package contains sharable common code that configure tracing provider. The package then can be vendored into other projects/components that need to set up OpenTelemetry tracing. Signed-off-by: Vu Dinh <vudinh@outlook.com>
1 parent bfe6f7d commit e397417

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

pkg/tracing/otlp_sdk.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package tracing
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"go.opentelemetry.io/contrib/exporters/autoexport"
8+
"go.opentelemetry.io/otel"
9+
"go.opentelemetry.io/otel/attribute"
10+
"go.opentelemetry.io/otel/propagation"
11+
"go.opentelemetry.io/otel/sdk/resource"
12+
tracesdk "go.opentelemetry.io/otel/sdk/trace"
13+
14+
"github.com/go-logr/logr"
15+
errors "github.com/zgalor/weberr"
16+
)
17+
18+
// ConfigureOpenTelemetryTracer configures the global OpenTelemetry trace
19+
// provider and propagator for baggages and trace context.
20+
//
21+
// The function uses the following environment variables for the tracer
22+
// configuration:
23+
// - `OTEL_TRACES_EXPORTER`, either `otlp` to send traces to an OTLP endpoint or `console`.
24+
// - `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL`, either `grpc` or `http`.
25+
// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`, endpoint where to send the OTLP
26+
// traces (e.g. `https://localhost:4318/v1/traces`).
27+
//
28+
// See
29+
// https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
30+
// for the list of all supported variables.
31+
//
32+
// An error is returned if an environment value is set to an unhandled value.
33+
//
34+
// If no environment variable are set, a no-op tracer is setup.
35+
func ConfigureOpenTelemetryTracer(ctx context.Context, logger logr.Logger, resourceAttrs ...attribute.KeyValue) (func(context.Context) error, error) {
36+
logger.Info("initializing OpenTelemetry tracer...")
37+
38+
exp, err := autoexport.NewSpanExporter(ctx, autoexport.WithFallbackSpanExporter(newNoopFactory))
39+
if err != nil {
40+
return nil, errors.Errorf("failed to create OTEL exporter: %s", err)
41+
}
42+
43+
var isNoop bool
44+
if _, isNoop = exp.(*noopSpanExporter); !isNoop || autoexport.IsNoneSpanExporter(exp) {
45+
isNoop = true
46+
}
47+
logger.Info("initializing OpenTelemetry tracer:", "isNoop", isNoop)
48+
49+
opts := []resource.Option{resource.WithHost()}
50+
if len(resourceAttrs) > 0 {
51+
opts = append(opts, resource.WithAttributes(resourceAttrs...))
52+
}
53+
resources, err := resource.New(ctx, opts...)
54+
if err != nil {
55+
return nil, errors.Errorf("failed to initialize trace resources: %s", err)
56+
}
57+
58+
tp := tracesdk.NewTracerProvider(
59+
tracesdk.WithBatcher(exp),
60+
tracesdk.WithResource(resources),
61+
)
62+
otel.SetTracerProvider(tp)
63+
64+
shutdown := func(ctx context.Context) error {
65+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
66+
defer cancel()
67+
return tp.Shutdown(ctx)
68+
}
69+
70+
propagator := propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})
71+
otel.SetTextMapPropagator(propagator)
72+
73+
otel.SetErrorHandler(otelErrorHandlerFunc(func(err error) {
74+
logger.Error(err, "OpenTelemetry.ErrorHandler: %v", err.Error())
75+
}))
76+
77+
return shutdown, nil
78+
}
79+
80+
type otelErrorHandlerFunc func(error)
81+
82+
// Handle implements otel.ErrorHandler
83+
func (f otelErrorHandlerFunc) Handle(err error) {
84+
f(err)
85+
}
86+
87+
func newNoopFactory(_ context.Context) (tracesdk.SpanExporter, error) {
88+
return &noopSpanExporter{}, nil
89+
}
90+
91+
var _ tracesdk.SpanExporter = noopSpanExporter{}
92+
93+
// noopSpanExporter is an implementation of trace.SpanExporter that performs no operations.
94+
type noopSpanExporter struct{}
95+
96+
// ExportSpans is part of trace.SpanExporter interface.
97+
func (e noopSpanExporter) ExportSpans(ctx context.Context, spans []tracesdk.ReadOnlySpan) error {
98+
return nil
99+
}
100+
101+
// Shutdown is part of trace.SpanExporter interface.
102+
func (e noopSpanExporter) Shutdown(ctx context.Context) error {
103+
return nil
104+
}

0 commit comments

Comments
 (0)