Reference

Observability

addons/observability enables generated GOWDK Trace wiring for debug builds. It registers FeatureObservability; runtime/trace remains the dependency-free root runtime, and optional OTLP export lives in the nested runtime/trace/otel module.

addons/observability enables generated GOWDK Trace wiring for debug builds. It registers FeatureObservability; runtime/trace remains the dependency-free root runtime, and optional OTLP export lives in the nested runtime/trace/otel module.

Enable it:

gowdk add observability
gowdk build --debug --app /tmp/gowdk-app pages/home.page.gwdk

Generated development builds mount the local trace viewer at:

/_gowdk/traces

The viewer is off unless the addon is enabled and Build.DebugAssets() is true (Build.Mode != gowdk.Production). Outside dev, generated apps mount the viewer behind runtime/app.LocalTraceAccess, which only allows direct localhost or loopback requests and rejects forwarded reverse-proxy requests unless the app supplies an explicit TraceAccess function.

Current generated instrumentation:

  • Backend request route spans extract incoming traceparent.
  • Generated SSR route and load {} spans record route IDs, render lane, source refs, response status, and load errors without storing raw request bodies or headers.
  • Generated action, API, fragment, command, and query routes record handler spans with .gwdk source refs when debug metadata is enabled.
  • Guards and contract command/query/job/event/worker operations record child spans when a tracer is present in context.
  • runtime/contracts.EventEnvelope and file outbox records carry an optional traceparent; old records without it remain readable.
  • Generated browser runtime spans partial submits and SPA navigation, injects traceparent, and posts frontend spans to the local collector.
  • JS islands, WASM island loaders, and page-level client Go WASM loaders reuse window.__gowdkTrace.

The generated local collector keeps a bounded in-memory ring of 1024 completed spans. Generated code records stable route/endpoint IDs and source metadata, and uses runtime redaction helpers for query strings, error messages, and app-owned trace events.

For app-owned Go handlers, record a user event on the active span:

app.Trace(ctx, "loaded patient", map[string]any{"patientID": id})

Export to OTLP from an app that opts into the nested module:

sink, err := otel.NewSink(ctx, otel.WithEndpoint("localhost:4318"), otel.WithInsecure())
if err != nil {
	return err
}
defer sink.Shutdown(ctx)

tracer := trace.NewTracer(trace.WithSink(sink))

Do not treat the local collector or viewer as a production observability backend. Production deployments should set sampling deliberately, keep viewer access gated or disabled, and send spans to app-owned telemetry infrastructure.