package observability import ( "context" "log/slog" "strings" "go.opentelemetry.io/otel" "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" semconv "go.opentelemetry.io/otel/semconv/v1.37.0" "go.opentelemetry.io/otel/trace" ) func NewTracerProvider(ctx context.Context, logger *slog.Logger, serviceName, environment, otlpEndpoint string) (*sdktrace.TracerProvider, error) { res, err := resource.New( ctx, resource.WithAttributes( semconv.ServiceName(serviceName), semconv.DeploymentEnvironmentName(environment), ), ) if err != nil { return nil, err } providerOptions := []sdktrace.TracerProviderOption{sdktrace.WithResource(res)} endpoint := strings.TrimSpace(otlpEndpoint) if endpoint != "" { exporter, err := otlptracegrpc.New( ctx, otlptracegrpc.WithEndpoint(endpoint), otlptracegrpc.WithInsecure(), ) if err != nil { return nil, err } providerOptions = append(providerOptions, sdktrace.WithBatcher(exporter)) logger.Info("otlp tracing exporter enabled", slog.String("endpoint", endpoint)) } else { logger.Info("otlp endpoint not set, traces will not be exported") } tp := sdktrace.NewTracerProvider(providerOptions...) otel.SetTracerProvider(tp) otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ), ) return tp, nil } func NewTracer(tp *sdktrace.TracerProvider, serviceName string) trace.Tracer { return tp.Tracer(serviceName) }