package main import ( "context" "errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) func setupOpenTelemetry(ctx context.Context, serviceName, serviceVersion string) (func(context.Context) error, error) { var shutdownFuncs []func(context.Context) error shutdown := func(ctx context.Context) error { var err error for _, fn := range shutdownFuncs { err = errors.Join(err, fn(ctx)) } shutdownFuncs = nil return err } res, err := resource.Merge( resource.Default(), resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName(serviceName), semconv.ServiceVersion(serviceVersion), ), ) if err != nil { return nil, errors.Join(err, shutdown(ctx)) } prop := propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ) otel.SetTextMapPropagator(prop) tracerProvider, err := newTraceProvider(ctx, res) if err != nil { return nil, errors.Join(err, shutdown(ctx)) } shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) otel.SetTracerProvider(tracerProvider) meterProvider, err := newMeterProvider(ctx, res) if err != nil { return nil, errors.Join(err, shutdown(ctx)) } shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) otel.SetMeterProvider(meterProvider) return shutdown, nil } func newTraceProvider(ctx context.Context, res *resource.Resource) (*trace.TracerProvider, error) { traceExporter, err := otlptracegrpc.New(ctx) if err != nil { return nil, err } traceProvider := trace.NewTracerProvider( trace.WithBatcher(traceExporter), trace.WithResource(res), ) return traceProvider, nil } func newMeterProvider(ctx context.Context, res *resource.Resource) (*metric.MeterProvider, error) { metricExporter, err := otlpmetricgrpc.New(ctx) if err != nil { return nil, err } meterProvider := metric.NewMeterProvider( metric.WithResource(res), metric.WithReader(metric.NewPeriodicReader(metricExporter)), ) return meterProvider, nil }