Documentation
¶
Overview ¶
Package trace provides a dependency-free tracing core for GOWDK Runtime and plain Go applications.
Index ¶
- Constants
- Variables
- func ContextWithTraceContext(ctx context.Context, traceContext TraceContext) context.Context
- func ContextWithTracer(ctx context.Context, tracer *Tracer) context.Context
- func EntropyFailureCount() uint64
- func Extract(ctx context.Context, carrier Carrier) context.Context
- func Inject(ctx context.Context, carrier Carrier)
- func MatchLane(lane Lane) func(SamplingContext) bool
- func MatchSpanName(name string) func(SamplingContext) bool
- func MatchSpanNamePrefix(prefix string) func(SamplingContext) bool
- func MatchSurface(surface Surface) func(SamplingContext) bool
- func NormalizeSourceFile(file string, policy SourcePolicy) string
- func SetEntropyFailureHandler(handler func(error))
- func SetSourcePolicy(policy SourcePolicy)
- func SlogArgs(ctx context.Context) []any
- func SlogAttrs(ctx context.Context) []slog.Attr
- func Traceparent(traceContext TraceContext) string
- type Attribute
- type Carrier
- type Collector
- func (collector *Collector) Dropped() uint64
- func (collector *Collector) Handler() http.Handler
- func (collector *Collector) HealthSnapshot() CollectorHealthSnapshot
- func (collector *Collector) RecordSpan(ctx context.Context, span Snapshot) error
- func (collector *Collector) Rejected() uint64
- func (collector *Collector) Spans() []Snapshot
- func (collector *Collector) ViewerHandler() http.Handler
- type CollectorHealthSnapshot
- type CollectorOption
- type ConsoleSink
- type CountedSampler
- type CryptoIDGenerator
- type Event
- type Exporter
- type IDGenerator
- type JSONLSink
- type Lane
- type OTLPSpan
- type RingSink
- type Sampler
- type SamplerRule
- type SamplingContext
- type Sink
- type Snapshot
- type SourcePathMode
- type SourcePolicy
- type SourceRef
- type Span
- func (span *Span) End()
- func (span *Span) EndTime(t time.Time)
- func (span *Span) Event(level string, message string, attrs map[string]any)
- func (span *Span) Set(key string, value any)
- func (span *Span) SetStatus(code StatusCode, message string)
- func (span *Span) Snapshot() Snapshot
- func (span *Span) TraceContext() TraceContext
- type SpanID
- type StartOption
- type Status
- type StatusCode
- type Surface
- type TraceContext
- type TraceID
- type Tracer
- type TracerHealthSnapshot
- type TracerOption
Constants ¶
const ( AttrGOWDKSurface = "gowdk.surface" AttrGOWDKLane = "gowdk.lane" AttrGOWDKSourceFile = "gowdk.source.file" AttrGOWDKSourceLine = "gowdk.source.line" AttrGOWDKSourceCol = "gowdk.source.column" AttrHTTPRoute = "http.route" AttrHTTPRequestMethod = "http.request.method" AttrHTTPResponseStatusCode = "http.response.status_code" AttrURLPath = "url.path" AttrServerAddress = "server.address" )
const ( SlogTraceIDKey = "trace_id" SlogSpanIDKey = "span_id" )
const ( // MaxTraceparentHeaderBytes is the maximum traceparent header size accepted // by Extract and ParseTraceparent. MaxTraceparentHeaderBytes = 256 // MaxTracestateHeaderBytes is the W3C tracestate list-member byte budget. MaxTracestateHeaderBytes = 512 )
Variables ¶
var SinkLogger func(message string) = func(message string) { log.Print(message) }
SinkLogger receives completed-span export failures. Set it to nil to silence sink failure logging. It defaults to the standard log package.
Functions ¶
func ContextWithTraceContext ¶
func ContextWithTraceContext(ctx context.Context, traceContext TraceContext) context.Context
ContextWithTraceContext returns a context carrying trace identity.
func ContextWithTracer ¶
ContextWithTracer returns a context carrying tracer for child spans started by helper packages such as runtime/app and runtime/contracts.
func EntropyFailureCount ¶ added in v0.8.0
func EntropyFailureCount() uint64
EntropyFailureCount reports how many crypto/rand failures the default ID generator has observed since process start. It is zero on healthy systems. A non-zero value means trace/span identity could not be generated from the system CSPRNG and the affected spans were dropped rather than assigned a predictable identifier.
func MatchLane ¶ added in v0.8.0
func MatchLane(lane Lane) func(SamplingContext) bool
MatchLane matches spans on the given GOWDK lane.
func MatchSpanName ¶ added in v0.8.0
func MatchSpanName(name string) func(SamplingContext) bool
MatchSpanName matches spans whose name equals name.
func MatchSpanNamePrefix ¶ added in v0.8.0
func MatchSpanNamePrefix(prefix string) func(SamplingContext) bool
MatchSpanNamePrefix matches spans whose name starts with prefix.
func MatchSurface ¶ added in v0.8.0
func MatchSurface(surface Surface) func(SamplingContext) bool
MatchSurface matches spans on the given GOWDK surface.
func NormalizeSourceFile ¶ added in v0.8.0
func NormalizeSourceFile(file string, policy SourcePolicy) string
NormalizeSourceFile applies policy to a single SourceRef.File value.
In the default relative mode it never returns an absolute path: Windows drive letters and UNC prefixes are stripped, the path is made relative to policy.ProjectRoot when it lies beneath it, leading separators are removed, and leading parent-directory ("..") segments are collapsed so the logical path cannot escape the project root. In absolute mode the path is returned cleaned but otherwise unchanged.
func SetEntropyFailureHandler ¶ added in v0.8.0
func SetEntropyFailureHandler(handler func(error))
SetEntropyFailureHandler installs a callback invoked for each crypto/rand failure observed by the default ID generator. Pass nil to clear it.
The handler must not start spans or otherwise re-enter the tracer: doing so during an entropy failure can recurse. Use it to increment an external metric or emit a single rate-limited alert.
func SetSourcePolicy ¶ added in v0.8.0
func SetSourcePolicy(policy SourcePolicy)
SetSourcePolicy installs the process-wide source-path normalization policy. It is applied to every span snapshot before it is exposed through the trace viewer, JSON/SSE, console, or OTLP surfaces. The zero SourcePolicy (relative mode, no project root) is the default and never exposes absolute paths.
func SlogArgs ¶ added in v0.8.0
SlogArgs returns trace/span attributes as alternating key/value args for slog.Logger methods.
func SlogAttrs ¶ added in v0.8.0
SlogAttrs returns stable slog attributes for the active trace context. It returns nil when ctx has no valid trace identity.
func Traceparent ¶
func Traceparent(traceContext TraceContext) string
Traceparent encodes traceContext as a W3C traceparent header.
Types ¶
type Attribute ¶
Attribute is an OpenTelemetry-compatible key/value attribute. Supported values are string, bool, integer, float64, and homogeneous slices of those scalar forms. Trace boundaries copy supported values and drop unsupported pointer/map/object values so snapshots remain serialization-safe.
type Carrier ¶
Carrier is the minimal interface implemented by http.Header and compatible request metadata maps.
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector combines an in-memory ring sink with a small HTTP JSON/SSE handler for local inspection.
func NewCollector ¶
func NewCollector(limit int, options ...CollectorOption) *Collector
NewCollector creates a collector backed by a RingSink.
func (*Collector) Handler ¶
Handler serves recent spans as JSON. Requests to /events or requests with an Accept header containing text/event-stream receive an SSE stream of existing and future spans. POST requests accept one Snapshot or a JSON array of Snapshots so generated browser runtimes can join frontend spans to backend traces without another collector dependency.
func (*Collector) HealthSnapshot ¶ added in v0.8.0
func (collector *Collector) HealthSnapshot() CollectorHealthSnapshot
HealthSnapshot returns local collector storage, rejection, and stream queue health.
func (*Collector) RecordSpan ¶
RecordSpan implements Sink.
func (*Collector) Rejected ¶ added in v0.8.0
Rejected returns the number of rejected ingest or stream requests.
func (*Collector) ViewerHandler ¶
ViewerHandler serves a self-contained local trace viewer plus JSON and SSE endpoints. Generated apps mount it behind an access gate when enabling it outside dev; raw callers should do the same for internet-facing handlers.
type CollectorHealthSnapshot ¶ added in v0.8.0
type CollectorHealthSnapshot struct {
Spans int `json:"spans"`
Dropped uint64 `json:"dropped"`
Rejected uint64 `json:"rejected"`
Subscribers int `json:"subscribers"`
SubscriberQueueDepth int `json:"subscriberQueueDepth"`
SubscriberQueueCapacity int `json:"subscriberQueueCapacity"`
SSELimit int `json:"sseLimit"`
IngestRateLimit int `json:"ingestRateLimit"`
IngestRateWindowDuration string `json:"ingestRateWindowDuration"`
}
CollectorHealthSnapshot is a point-in-time view of local collector state.
type CollectorOption ¶ added in v0.8.0
type CollectorOption func(*Collector)
CollectorOption configures a Collector.
func WithCollectorIngestRate ¶ added in v0.8.0
func WithCollectorIngestRate(limit int, window time.Duration) CollectorOption
WithCollectorIngestRate sets a fixed-window POST ingest rate per remote address. A non-positive limit or window disables rate limiting.
func WithCollectorSSELimit ¶ added in v0.8.0
func WithCollectorSSELimit(limit int) CollectorOption
WithCollectorSSELimit sets the maximum number of concurrent SSE subscribers. A non-positive limit disables the cap.
type ConsoleSink ¶
type ConsoleSink struct {
// contains filtered or unexported fields
}
ConsoleSink writes one readable line per completed span.
ConsoleSink is intended for development and local diagnostics. Span names, status messages, source paths, and event messages can derive from request, route, or browser-supplied values, so every field is escaped (see escapeControl) before it is written: control characters cannot forge an additional log line or emit raw terminal control sequences. Use JSONLSink for production logging where downstream tooling parses structured records.
func NewConsoleSink ¶
func NewConsoleSink(writer io.Writer) *ConsoleSink
NewConsoleSink creates a console sink.
func (*ConsoleSink) RecordSpan ¶
func (sink *ConsoleSink) RecordSpan(ctx context.Context, span Snapshot) error
RecordSpan implements Sink.
type CountedSampler ¶
type CountedSampler struct {
N uint64
// contains filtered or unexported fields
}
CountedSampler is a deterministic test helper that samples every n-th span.
func (*CountedSampler) Sample ¶
func (sampler *CountedSampler) Sample(SamplingContext) bool
Sample implements Sampler.
type CryptoIDGenerator ¶ added in v0.8.0
type CryptoIDGenerator struct{}
CryptoIDGenerator is the default IDGenerator. It reads identifiers from crypto/rand and never falls back to predictable values such as timestamps or sequence counters. On the (extraordinary) event of a crypto/rand failure it records the failure via EntropyFailureCount and the entropy failure handler, then returns an invalid ID so the caller can observe the loss instead of emitting a guessable identifier.
func (CryptoIDGenerator) NewSpanID ¶ added in v0.8.0
func (CryptoIDGenerator) NewSpanID() SpanID
NewSpanID implements IDGenerator.
func (CryptoIDGenerator) NewTraceID ¶ added in v0.8.0
func (CryptoIDGenerator) NewTraceID() TraceID
NewTraceID implements IDGenerator.
type Event ¶
type Event struct {
Time time.Time `json:"time"`
Level string `json:"level,omitempty"`
Message string `json:"message"`
Attributes []Attribute `json:"attributes,omitempty"`
}
Event records a timestamped span event.
type IDGenerator ¶ added in v0.8.0
type IDGenerator interface {
// NewTraceID returns a valid W3C trace ID, or "" if one cannot be produced.
NewTraceID() TraceID
// NewSpanID returns a valid W3C span ID, or "" if one cannot be produced.
NewSpanID() SpanID
}
IDGenerator produces trace and span identifiers for new spans.
The default generator (CryptoIDGenerator) draws identifiers from crypto/rand. Provide a custom generator with WithIDGenerator to make IDs deterministic in tests, or to source identity from another subsystem. A generator may report transient failure by returning an empty (invalid) ID; the tracer treats that as "cannot start a span" rather than substituting a predictable identifier.
type JSONLSink ¶
type JSONLSink struct {
// contains filtered or unexported fields
}
JSONLSink writes one JSON object per completed span.
func NewJSONLSink ¶
NewJSONLSink creates a JSON Lines sink.
type OTLPSpan ¶
type OTLPSpan struct {
TraceID TraceID `json:"traceId"`
SpanID SpanID `json:"spanId"`
ParentSpanID SpanID `json:"parentSpanId,omitempty"`
Name string `json:"name"`
StartTimeUnixNano int64 `json:"startTimeUnixNano"`
EndTimeUnixNano int64 `json:"endTimeUnixNano"`
Attributes []Attribute `json:"attributes,omitempty"`
Events []Event `json:"events,omitempty"`
Status Status `json:"status,omitempty"`
}
OTLPSpan is intentionally shaped like the OTLP span model while remaining a dependency-free value type.
func OTLPSpanFromSnapshot ¶
OTLPSpanFromSnapshot converts a completed span to the OTLP-like model.
type RingSink ¶
type RingSink struct {
// contains filtered or unexported fields
}
RingSink stores the most recent completed spans in memory. On overflow it drops the oldest span and increments Dropped.
func NewRingSink ¶
NewRingSink creates a bounded in-memory sink.
func (*RingSink) RecordSpan ¶
RecordSpan implements Sink. It never blocks on external I/O.
type Sampler ¶
type Sampler interface {
Sample(SamplingContext) bool
}
Sampler decides whether a span should be recorded.
func ParentBasedSampler ¶ added in v0.8.0
ParentBasedSampler returns a sampler that keeps a trace whole: when a span has a propagated parent, it honors the parent's sampling decision; for a root span (no parent) it delegates to root. This is the production-safe default for distributed tracing — a downstream service does not re-roll the dice and split one logical trace into sampled and unsampled fragments. Pair it with RatioSampler as the root to sample a deterministic fraction of whole traces:
trace.ParentBasedSampler(trace.RatioSampler(0.1))
func RatioSampler ¶
RatioSampler returns a deterministic trace-id based sampler. Ratios <= 0 are always off; ratios >= 1 are always on.
func RuleSampler ¶ added in v0.8.0
func RuleSampler(base Sampler, rules ...SamplerRule) Sampler
RuleSampler applies the first matching rule's decision and falls back to base when no rule matches. It is the GOWDK-owned override hook for app and generated route/endpoint policy: silence health checks and noisy endpoints (Keep:false), force high-value endpoints on (Keep:true), and sample everything else with base.
trace.RuleSampler(
trace.ParentBasedSampler(trace.RatioSampler(0.1)),
trace.DropSpansNamed("GET /_gowdk/health"),
trace.KeepSpansNamed("POST /checkout"),
)
type SamplerRule ¶ added in v0.8.0
type SamplerRule struct {
Match func(SamplingContext) bool
// Keep is the decision applied when Match returns true.
Keep bool
}
SamplerRule overrides the sampling decision for spans whose SamplingContext matches. The first matching rule in a RuleSampler wins.
func DropSpansNamed ¶ added in v0.8.0
func DropSpansNamed(name string) SamplerRule
DropSpansNamed builds a rule that always drops spans with the exact name, for health checks and other always-off endpoints.
func KeepSpansNamed ¶ added in v0.8.0
func KeepSpansNamed(name string) SamplerRule
KeepSpansNamed builds a rule that always keeps spans with the exact name, for high-value endpoints that must be traced regardless of the base ratio.
type SamplingContext ¶
type SamplingContext struct {
TraceID TraceID
ParentSpanID SpanID
HasParent bool
ParentSampled bool
Name string
Surface Surface
Lane Lane
Attributes []Attribute
}
SamplingContext is passed to samplers before a span is allocated. HasParent and ParentSampled describe the propagated parent decision so a parent-based sampler can keep a trace whole: every span in a sampled trace is kept, and every span in an unsampled trace is dropped.
type Sink ¶
Sink receives completed span snapshots.
func ExporterSink ¶
ExporterSink adapts an Exporter into a Sink.
type Snapshot ¶
type Snapshot struct {
TraceID TraceID `json:"traceId"`
SpanID SpanID `json:"spanId"`
ParentSpanID SpanID `json:"parentSpanId,omitempty"`
Name string `json:"name"`
Surface Surface `json:"surface,omitempty"`
Lane Lane `json:"lane,omitempty"`
Source SourceRef `json:"source,omitempty"`
Attributes []Attribute `json:"attributes,omitempty"`
Events []Event `json:"events,omitempty"`
Status Status `json:"status,omitempty"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
DurationNS int64 `json:"durationNs"`
}
Snapshot is the immutable JSON/export shape of a completed span.
type SourcePathMode ¶ added in v0.8.0
type SourcePathMode int
SourcePathMode controls how SourceRef.File paths are exposed outside the process (trace viewer, JSON/SSE, console, and OTLP export).
const ( // SourcePathRelative reduces absolute filesystem paths to project-relative // logical paths so local filesystem structure is not revealed to trace // consumers. It is the default and the only production-safe mode. SourcePathRelative SourcePathMode = iota // SourcePathAbsolute exposes source paths verbatim, including absolute local // filesystem paths. It is a debugging aid for local development and must not // be enabled when traces leave the machine. SourcePathAbsolute )
type SourcePolicy ¶ added in v0.8.0
type SourcePolicy struct {
// Mode selects relative (default) or absolute path exposure.
Mode SourcePathMode
// ProjectRoot, when set, is the directory that absolute source paths under
// it are made relative to in SourcePathRelative mode.
ProjectRoot string
}
SourcePolicy controls source-path normalization applied to a span snapshot's SourceRef.File before the snapshot is exposed outside the process.
func CurrentSourcePolicy ¶ added in v0.8.0
func CurrentSourcePolicy() SourcePolicy
CurrentSourcePolicy returns the active source-path normalization policy.
type SourceRef ¶
type SourceRef struct {
File string `json:"file,omitempty"`
Line int `json:"line,omitempty"`
Column int `json:"column,omitempty"`
OwnerKind string `json:"ownerKind,omitempty"`
OwnerID string `json:"ownerId,omitempty"`
}
SourceRef points a span back to GOWDK source or generated runtime metadata.
type Span ¶
type Span struct {
// contains filtered or unexported fields
}
Span records one sampled unit of work. Methods are nil-safe so callers can defer span.End() even when sampling is disabled.
func (*Span) End ¶
func (span *Span) End()
End completes the span and sends an immutable snapshot to the configured sink. Calling End more than once is safe.
func (*Span) SetStatus ¶
func (span *Span) SetStatus(code StatusCode, message string)
SetStatus records the final span status.
func (*Span) TraceContext ¶
func (span *Span) TraceContext() TraceContext
TraceContext returns the span's W3C trace identity.
type SpanID ¶
type SpanID string
SpanID is a W3C Trace Context parent-id/span-id: 8 bytes encoded as 16 lowercase hexadecimal characters.
type StartOption ¶
type StartOption func(*startConfig)
StartOption configures one span.
func WithAttributes ¶
func WithAttributes(attrs map[string]any) StartOption
WithAttributes records initial span attributes.
func WithSource ¶
func WithSource(source SourceRef) StartOption
WithSource records a source reference.
func WithStartTime ¶
func WithStartTime(start time.Time) StartOption
WithStartTime sets a deterministic start time.
func WithSurface ¶
func WithSurface(surface Surface) StartOption
WithSurface records a span surface.
func WithTracer ¶
func WithTracer(tracer *Tracer) StartOption
WithTracer starts a span with tracer instead of the default tracer.
type Status ¶
type Status struct {
Code StatusCode `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}
Status records the final span status.
type StatusCode ¶
type StatusCode string
StatusCode follows the OpenTelemetry span status shape without importing the OpenTelemetry SDK.
const ( StatusUnset StatusCode = "unset" StatusOK StatusCode = "ok" StatusError StatusCode = "error" )
type TraceContext ¶
type TraceContext struct {
TraceID TraceID
SpanID SpanID
Sampled bool
Remote bool
TraceState string
}
TraceContext is the trace identity stored in context.Context and encoded in W3C traceparent/tracestate headers.
func ParseTraceContext ¶ added in v0.8.0
func ParseTraceContext(traceparent string, tracestate string) (TraceContext, error)
ParseTraceContext parses W3C traceparent and tracestate headers. Invalid traceparent input rejects the context. Invalid tracestate input is dropped so a usable trace identity is still preserved without propagating ambiguous vendor state.
func ParseTraceparent ¶
func ParseTraceparent(value string) (TraceContext, error)
ParseTraceparent parses a W3C traceparent header.
func TraceContextFromContext ¶
func TraceContextFromContext(ctx context.Context) (TraceContext, bool)
TraceContextFromContext returns trace identity from ctx when present.
type TraceID ¶
type TraceID string
TraceID is a W3C Trace Context trace-id: 16 bytes encoded as 32 lowercase hexadecimal characters.
func NewTraceID ¶
func NewTraceID() TraceID
NewTraceID returns a valid W3C trace ID from the default ID generator (CryptoIDGenerator). It returns "" only when the system CSPRNG cannot provide entropy; see EntropyFailureCount. It never falls back to a predictable value.
type Tracer ¶
type Tracer struct {
// contains filtered or unexported fields
}
Tracer owns sampling, identity generation, and completed-span delivery.
func TracerFromContext ¶
TracerFromContext returns the tracer stored in ctx, or the tracer that owns the active sampled span.
func (*Tracer) HealthSnapshot ¶ added in v0.8.0
func (tracer *Tracer) HealthSnapshot() TracerHealthSnapshot
HealthSnapshot returns local sampling and sink export health.
type TracerHealthSnapshot ¶ added in v0.8.0
type TracerHealthSnapshot struct {
Sampler string `json:"sampler"`
SamplingRatio string `json:"samplingRatio,omitempty"`
SampledSpans uint64 `json:"sampledSpans"`
ExportedSpans uint64 `json:"exportedSpans"`
ExportFailures uint64 `json:"exportFailures"`
LastExportLatencyNS int64 `json:"lastExportLatencyNs"`
MaxExportLatencyNS int64 `json:"maxExportLatencyNs"`
}
TracerHealthSnapshot is a dependency-free point-in-time view of local tracer sampling and sink export health.
type TracerOption ¶
type TracerOption func(*Tracer)
TracerOption configures a Tracer.
func WithIDGenerator ¶ added in v0.8.0
func WithIDGenerator(generator IDGenerator) TracerOption
WithIDGenerator sets the trace/span ID generator. Nil keeps the default CryptoIDGenerator. Tests use this to inject deterministic identifiers without relying on entropy failure.
func WithSampler ¶
func WithSampler(sampler Sampler) TracerOption
WithSampler sets the sampler. Nil means AlwaysOn.