Problem
GOWDK needs a tracing core that can be used by plain Go applications and later by generated runtime paths without taking a dependency on OpenTelemetry, Sentry, or a hosted observability backend.
Goals
- Provide a dependency-free
runtime/tracepackage. - Use W3C Trace Context IDs and
traceparentpropagation. - Support backend, frontend, and worker surfaces plus GOWDK lanes such as route, guard, handler, SSR, action, API, fragment, contract, job, island, navigation, and user spans.
- Provide context helpers:
Start,SpanFrom, span events, attributes, and status. - Provide pluggable sinks: console, JSON Lines, in-memory ring, multi-sink, and exporter adapter.
- Provide sampling: always on, always off, ratio, and test-counted sampling.
- Provide a self-contained collector handler that serves recent spans as JSON and streams spans over SSE.
- Keep the root module dependency graph unchanged.
Non-Goals
- Add OpenTelemetry SDK or OTLP dependencies to the root module.
- Persist traces durably.
- Define
.gwdktracing syntax.
Users
- Go developers who want lightweight local trace output in plain Go programs.
- Future generated GOWDK app wiring that needs a stable runtime trace API.
- Tooling that wants recent in-process traces without a collector service.
Requirements
Functional
runtime/traceexposes W3C-compatibleTraceIDandSpanIDvalues.trace.Start(ctx, name, opts...)starts a sampled span and returns a context carrying that span.trace.SpanFrom(ctx)returns the active sampled span.- Span methods are nil-safe:
End,Event,Set, andSetStatuscan be called even when sampling returnednil. trace.Injectandtrace.Extractround-triptraceparentthrough carriers such ashttp.Header.trace.RingSinkkeeps the newest spans, drops oldest on overflow, and exposes a drop count.trace.Collectorimplements a sink and serves recent spans as JSON or SSE.- The exporter adapter produces an OTLP-like span shape without importing OpenTelemetry packages.
Non-Functional
- Runtime package imports must stay standard-library only.
AlwaysOffwith no start options must allocate zero objects on the hot path.- Sinks must be safe for concurrent use.
- The ring sink must not block on external I/O.
Acceptance Criteria
go test ./runtime/tracego test ./runtime/trace -run '^$' -bench BenchmarkStartAlwaysOff -benchmemgo test ./...- No root
go.moddependency changes.
Current Limits
- Generated instrumentation is debug-gated through
addons/observability; production sampling, access policy, and durable storage remain app-owned. - Collector data is in-memory only and process-local.
- The SSE stream is a local inspection aid, not a durable delivery channel.
- Concrete OTLP transport lives in the nested optional
runtime/trace/otelmodule.