package main import ( "context" "errors" "time" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/log/global" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/trace" ) // setupOTelSDK bootstraps the OpenTelemetry pipeline. // If it does not return an error, make sure to call shutdown for proper cleanup. func setupOTelSDK(ctx context.Context) (func(context.Context) error, error) { var shutdownFuncs []func(context.Context) error var err error shutdown := func(ctx context.Context) error { var err error for _, fn := range shutdownFuncs { err = errors.Join(err, fn(ctx)) } shutdownFuncs = nil return err } handleErr := func(inErr error) { err = errors.Join(inErr, shutdown(ctx)) } prop := newPropagator() otel.SetTextMapPropagator(prop) tracerProvider, err := newTracerProvider() if err != nil { handleErr(err) return shutdown, err } shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) otel.SetTracerProvider(tracerProvider) meterProvider, err := newMeterProvider() if err != nil { handleErr(err) return shutdown, err } shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) otel.SetMeterProvider(meterProvider) loggerProvider, err := newLoggerProvider() if err != nil { handleErr(err) return shutdown, err } shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) global.SetLoggerProvider(loggerProvider) return shutdown, err } func newPropagator() propagation.TextMapPropagator { return propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ) } func newTracerProvider() (*trace.TracerProvider, error) { traceExporter, err := otlptracegrpc.New(context.Background()) if err != nil { return nil, err } tracerProvider := trace.NewTracerProvider( trace.WithBatcher(traceExporter, trace.WithBatchTimeout(time.Second)), ) return tracerProvider, nil } func newMeterProvider() (*metric.MeterProvider, error) { exporter, err := otlpmetricgrpc.New(context.Background()) if err != nil { return nil, err } provider := metric.NewMeterProvider(metric.WithReader(metric.NewPeriodicReader(exporter))) return provider, nil } func newLoggerProvider() (*log.LoggerProvider, error) { logExporter, err := otlploggrpc.New(context.Background()) if err != nil { return nil, err } loggerProvider := log.NewLoggerProvider( log.WithProcessor(log.NewBatchProcessor(logExporter)), ) return loggerProvider, nil }