Part of the Observability — OpenTelemetry Tracing v1 initiative (master tracking: #108). Effort: XS (~0.5 engineer-day). Risk: low (no behavior change). Depends on: nothing.
Goal
forge-core can import otel and exposes a tracer seam that defaults to no-op. Zero behavior change — purely additive infrastructure that subsequent phases hang implementations off.
Files
| File |
Change |
forge-core/go.mod |
Add otel deps (below) |
forge-core/runtime/tracing.go |
New. Tracer seam: package-level provider holder defaulting to otel noop, SetTracerProvider, Tracer(), span helpers |
forge-core/runtime/tracing_test.go |
New. Verify default is noop; Tracer().Start returns a non-recording span |
Dependencies to add (forge-core/go.mod)
go.opentelemetry.io/otel
go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/sdk
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
W3C tracecontext + baggage propagators are in core otel (go.opentelemetry.io/otel/propagation) — no contrib module needed.
tracing.go shape
- The seam is otel's
trace.TracerProvider interface. Default = go.opentelemetry.io/otel/trace/noop.NewTracerProvider().
var tracerProvider trace.TracerProvider = noop.NewTracerProvider() guarded by sync.RWMutex.
SetTracerProvider(tp trace.TracerProvider) — installs the real provider (called from cli wiring). Also call otel.SetTracerProvider(tp) and otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) so propagation works globally.
Tracer() trace.Tracer → tracerProvider.Tracer("github.com/initializ/forge").
- Instrumentation scope name constant:
const InstrumentationName = "github.com/initializ/forge".
Do not hand-roll a span type — use otel's trace.Span. The noop provider already satisfies "no-op when disabled."
Verify
go work sync
go build ./...
go test ./forge-core/runtime/ -run Tracing -v
# Confirm: with no provider set, Tracer().Start(ctx,"x") yields span.SpanContext().IsValid()==false
Anti-patterns to avoid
- Defining a custom
Span interface (use otel's trace.Span).
- Importing otel from cli call sites that should use the runtime seam.
- Setting a real exporter here — that's Phase 1's job.
Architectural decision
forge-core owns the otel dependency behind a no-op TracerProvider seam. Real OTLP provider lives in a new forge-core/observability subpackage (Phase 1) and is injected from forge-cli (Phase 2) — same pattern as audit: defined in core, wired in cli.
Goal
forge-corecan import otel and exposes a tracer seam that defaults to no-op. Zero behavior change — purely additive infrastructure that subsequent phases hang implementations off.Files
forge-core/go.modforge-core/runtime/tracing.goSetTracerProvider,Tracer(), span helpersforge-core/runtime/tracing_test.goTracer().Startreturns a non-recording spanDependencies to add (
forge-core/go.mod)W3C
tracecontext+baggagepropagators are in core otel (go.opentelemetry.io/otel/propagation) — no contrib module needed.tracing.goshapetrace.TracerProviderinterface. Default =go.opentelemetry.io/otel/trace/noop.NewTracerProvider().var tracerProvider trace.TracerProvider = noop.NewTracerProvider()guarded bysync.RWMutex.SetTracerProvider(tp trace.TracerProvider)— installs the real provider (called from cli wiring). Also callotel.SetTracerProvider(tp)andotel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))so propagation works globally.Tracer() trace.Tracer→tracerProvider.Tracer("github.com/initializ/forge").const InstrumentationName = "github.com/initializ/forge".Do not hand-roll a span type — use otel's
trace.Span. The noop provider already satisfies "no-op when disabled."Verify
Anti-patterns to avoid
Spaninterface (use otel'strace.Span).Architectural decision
forge-core owns the otel dependency behind a no-op
TracerProviderseam. Real OTLP provider lives in a newforge-core/observabilitysubpackage (Phase 1) and is injected fromforge-cli(Phase 2) — same pattern as audit: defined in core, wired in cli.