package observability import ( "context" "fmt" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) type TraceProvider struct{ provider *sdktrace.TracerProvider } func SetupTracing(ctx context.Context, serviceName, environment, endpoint string) (*TraceProvider, error) { res, err := resource.New(ctx, resource.WithAttributes( attribute.String("service.name", serviceName), attribute.String("deployment.environment.name", environment), )) if err != nil { return nil, fmt.Errorf("create telemetry resource: %w", err) } options := []sdktrace.TracerProviderOption{sdktrace.WithResource(res)} if endpoint != "" { exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint(endpoint), otlptracegrpc.WithInsecure(), ) if err != nil { return nil, fmt.Errorf("create OTLP trace exporter: %w", err) } options = append(options, sdktrace.WithBatcher(exporter)) } provider := sdktrace.NewTracerProvider(options...) otel.SetTracerProvider(provider) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, )) return &TraceProvider{provider: provider}, nil } func (p *TraceProvider) Shutdown(ctx context.Context) error { if p == nil || p.provider == nil { return nil } return p.provider.Shutdown(ctx) }