// Package telemetry owns the backend's OpenTelemetry wiring. The provider // bootstrap (exporter selection, propagators, shutdown, Go runtime metrics) is // shared across the Scrabble services in scrabble/pkg/telemetry; this package is a // thin backend-flavoured facade over it (the "scrabble-backend" default service // name) plus the backend-specific gin request-timing middleware (middleware.go), // which uses the registered global tracer so requests are timed and logged even // when the exporter is "none". package telemetry import ( "context" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" pkgtel "scrabble/pkg/telemetry" ) // Exporter selectors, re-exported from scrabble/pkg/telemetry so the backend's // config and tests need not import the shared package directly. const ( ExporterNone = pkgtel.ExporterNone ExporterStdout = pkgtel.ExporterStdout ExporterOTLP = pkgtel.ExporterOTLP ) // DefaultServiceName labels traces and metrics when BACKEND_SERVICE_NAME is unset. const DefaultServiceName = "scrabble-backend" // Config selects the telemetry providers' service name and exporters. It aliases // the shared configuration type. type Config = pkgtel.Config // Runtime owns the shared OpenTelemetry providers. It aliases the shared runtime // type, so callers keep using telemetry.Runtime. type Runtime = pkgtel.Runtime // DefaultConfig returns the backend's telemetry configuration: the // "scrabble-backend" service name and both exporters off (so no collector is // required locally or in CI). func DefaultConfig() Config { return pkgtel.DefaultConfig(DefaultServiceName) } // New constructs the telemetry runtime, registers the global providers and the // W3C propagators, and returns the Runtime. Callers must invoke Runtime.Shutdown // during process exit. func New(ctx context.Context, cfg Config) (*Runtime, error) { return pkgtel.New(ctx, cfg) } // TraceFieldsFromContext returns zap fields identifying the active span, or nil // when ctx carries no valid span context. Collocated here so callers (the // request-timing middleware and the access log) do not import the OpenTelemetry // API directly. func TraceFieldsFromContext(ctx context.Context) []zap.Field { if ctx == nil { return nil } sc := trace.SpanContextFromContext(ctx) if !sc.IsValid() { return nil } return []zap.Field{ zap.String("otel_trace_id", sc.TraceID().String()), zap.String("otel_span_id", sc.SpanID().String()), } }