package common import ( "context" "log" "time" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/log/global" "go.opentelemetry.io/otel/propagation" sdklog "go.opentelemetry.io/otel/sdk/log" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" ) // InitOTel initializes OpenTelemetry tracing, metrics, and logging providers. // It returns a shutdown function that should be called on application exit. func InitOTel(ctx context.Context, otelEndpoint string) (shutdown func(context.Context) error) { res, err := resource.New(ctx, resource.WithAttributes( semconv.ServiceNameKey.String("file-system"), semconv.ServiceVersionKey.String("1.0.0"), ), ) if err != nil { log.Printf("OTel resource creation failed: %v", err) return func(ctx context.Context) error { return nil } } // Tracer provider traceExp, err := otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint(otelEndpoint), otlptracegrpc.WithInsecure(), ) if err != nil { log.Printf("OTel trace exporter creation failed: %v", err) } else { tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(traceExp), sdktrace.WithResource(res), ) otel.SetTracerProvider(tp) } // Meter provider metricExp, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithEndpoint(otelEndpoint), otlpmetricgrpc.WithInsecure(), ) if err != nil { log.Printf("OTel metric exporter creation failed: %v", err) } else { mp := sdkmetric.NewMeterProvider( sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExp, sdkmetric.WithInterval(30*time.Second))), sdkmetric.WithResource(res), ) otel.SetMeterProvider(mp) } // Logger provider logExp, err := otlploggrpc.New(ctx, otlploggrpc.WithEndpoint(otelEndpoint), otlploggrpc.WithInsecure(), ) if err != nil { log.Printf("OTel log exporter creation failed: %v", err) } else { lp := sdklog.NewLoggerProvider( sdklog.WithProcessor(sdklog.NewBatchProcessor(logExp)), sdklog.WithResource(res), ) global.SetLoggerProvider(lp) } otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, )) return func(ctx context.Context) error { var errs []error if tp, ok := otel.GetTracerProvider().(*sdktrace.TracerProvider); ok { errs = append(errs, tp.Shutdown(ctx)) } if mp, ok := otel.GetMeterProvider().(*sdkmetric.MeterProvider); ok { errs = append(errs, mp.Shutdown(ctx)) } if lp, ok := global.GetLoggerProvider().(*sdklog.LoggerProvider); ok { errs = append(errs, lp.Shutdown(ctx)) } for _, e := range errs { if e != nil { return e } } return nil } }