tracing

package
v1.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package tracing records what a request does as a tree of timed spans, and exports them to OpenTelemetry collectors and the services that take OTLP, such as Grafana Tempo, Honeycomb, Jaeger or Datadog:

tracer := tracing.New(tracing.Options{Exporters: []tracing.Exporter{otlp.New(otlp.Options{})}})
tracing.SetDefault(tracer)
server, err := ternApp(kit.WithTracer(tracer))

kit starts a span for each request, and one for each load, action, endpoint and server render in it. Add your own with Start:

ctx, span := tracing.Start(ctx, "charge card", slog.String("order", id))
defer span.End()

Spans join the logs: a record logged inside a span carries its trace_id and span_id. Trace context follows work out of the process through Transport for HTTP requests and through the jobs queue, and comes in with a W3C traceparent header from a trusted proxy or service. Under tern dev, the log view shows each request's spans as a waterfall.

It is a small, dependency-free implementation of OpenTelemetry's tracing model, not its SDK: spans, events, status, parent-based sampling and W3C trace context.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContextWith

func ContextWith(ctx context.Context, span *Span) context.Context

ContextWith returns ctx carrying span, and its IDs for the logs.

func Inject

func Inject(r *http.Request)

Inject sets the traceparent header for the span in r's context, so the service r goes to continues the trace.

func OpenDB

func OpenDB(driverName, dsn string) (*sql.DB, error)

OpenDB opens a database like sql.Open, with each query a client span inside the trace of the context it runs with:

db, err := tracing.OpenDB("sqlite", "app.db")

Queries without a span in their context, such as at startup, record nothing.

func Permanent

func Permanent(err error) error

Permanent marks an export error as one retrying won't fix.

func SetDefault

func SetDefault(t *Tracer)

SetDefault makes t the tracer of spans started without a parent, such as those of jobs and of code that doesn't run in a request.

func Transport

func Transport(base http.RoundTripper) http.RoundTripper

Transport wraps base (http.DefaultTransport if nil) so each request is a client span, and carries the trace to the server it goes to:

client := &http.Client{Transport: tracing.Transport(nil)}

func WrapConnector

func WrapConnector(c driver.Connector, system string) driver.Connector

WrapConnector makes each query through c a span, for sql.OpenDB. system is the database, as OpenTelemetry names it: "postgresql", "sqlite", "mysql".

Types

type Batch

type Batch = batch.Options

Batch says how spans are batched and retried, as logging's sinks are.

type DevSpan

type DevSpan struct {
	TraceID   string         `json:"trace"`
	SpanID    string         `json:"span"`
	Parent    string         `json:"parent,omitempty"`
	Name      string         `json:"name"`
	Kind      string         `json:"kind"`
	Start     time.Time      `json:"start"`
	Micros    int64          `json:"us"`
	Error     string         `json:"error,omitempty"`
	RequestID string         `json:"request_id,omitempty"`
	Attrs     map[string]any `json:"attrs,omitempty"`
}

DevSpan is a span as tern dev's log view reads it.

type Event

type Event struct {
	Name  string
	Time  time.Time
	Attrs []slog.Attr
}

Event is something that happened at a point in a span, such as an exception.

type Exporter

type Exporter interface {
	Export(ctx context.Context, spans []SpanData) error
}

An Exporter sends finished spans somewhere, in batches, from one goroutine. Return Permanent for errors that retrying won't fix.

type ExporterFunc

type ExporterFunc func(ctx context.Context, spans []SpanData) error

ExporterFunc makes a function an Exporter.

func (ExporterFunc) Export

func (f ExporterFunc) Export(ctx context.Context, spans []SpanData) error

Export implements Exporter.

type Kind

type Kind int

Kind is what a span does, as OpenTelemetry has it.

const (
	Internal Kind = 1 // work inside the process: the default
	Server   Kind = 2 // handling a request
	Client   Kind = 3 // making a request: HTTP, SQL
	Producer Kind = 4 // queueing work: a job
	Consumer Kind = 5 // doing queued work
)

The kinds, numbered as in OTLP.

func (Kind) String

func (k Kind) String() string

type Options

type Options struct {
	// Exporters get every recorded span.
	Exporters []Exporter
	// Sample is the fraction of new traces recorded, from 0 to 1. Traces
	// that come in from elsewhere keep their own decision. The default is
	// TERN_TRACE_SAMPLE's, or 1: everything.
	Sample float64
	// Batch says how spans are batched for exporters.
	Batch Batch
}

Options configures a tracer.

type Span

type Span struct {
	// contains filtered or unexported fields
}

Span is an operation being timed. A Span that isn't recorded (no tracer, or not sampled) still carries its IDs, so logs and outgoing requests keep the trace; its other methods do nothing. All methods are safe on a nil *Span.

func FromContext

func FromContext(ctx context.Context) *Span

FromContext returns the span ctx carries, or nil.

func Start

func Start(ctx context.Context, name string, opts ...StartOption) (context.Context, *Span)

Start starts a span as a child of the span in ctx (or a remote parent), and returns ctx carrying it. The span is recorded by its parent's tracer, or the default one. End it when the work is done. With no tracer and no trace to continue, it returns ctx and a nil span, whose methods do nothing.

func (*Span) AddEvent

func (s *Span) AddEvent(name string, attrs ...slog.Attr)

AddEvent records something that happened now.

func (*Span) Context

func (s *Span) Context() SpanContext

Context returns the span's IDs.

func (*Span) End

func (s *Span) End()

End finishes the span and hands it to the exporters. Calls after the first do nothing.

func (*Span) IsRecording

func (s *Span) IsRecording() bool

IsRecording reports whether the span will be exported.

func (*Span) RecordError

func (s *Span) RecordError(err error)

RecordError records err as an exception event and marks the span failed. A nil err does nothing.

func (*Span) SetAttrs

func (s *Span) SetAttrs(attrs ...slog.Attr)

SetAttrs adds attributes, replacing ones with the same key.

func (*Span) SetName

func (s *Span) SetName(name string)

SetName renames the span, as kit does once it knows the request's route.

func (*Span) SetStatus

func (s *Span) SetStatus(code StatusCode, message string)

SetStatus sets the span's outcome. An Error is kept over a later OK.

type SpanContext

type SpanContext struct {
	TraceID TraceID
	SpanID  SpanID
	Sampled bool
}

SpanContext is what travels between processes: the trace, the span, and whether the trace is recorded.

func ParseTraceparent

func ParseTraceparent(s string) (SpanContext, bool)

ParseTraceparent reads a W3C traceparent header.

func (SpanContext) IsValid

func (sc SpanContext) IsValid() bool

IsValid reports whether both IDs are set.

func (SpanContext) Traceparent

func (sc SpanContext) Traceparent() string

Traceparent is the W3C traceparent header for sc.

type SpanData

type SpanData struct {
	Context SpanContext
	Parent  SpanID // zero for a root span
	Name    string
	Kind    Kind
	Start   time.Time
	End     time.Time
	Attrs   []slog.Attr
	Events  []Event
	Status  Status
}

SpanData is a finished span, as exporters get it.

func (SpanData) Duration

func (d SpanData) Duration() time.Duration

Duration is how long the span took.

type SpanID

type SpanID [8]byte

SpanID identifies a span within a trace.

func (SpanID) IsValid

func (s SpanID) IsValid() bool

IsValid reports whether the ID is set.

func (SpanID) String

func (s SpanID) String() string

type StartOption

type StartOption func(*startConfig)

StartOption configures a span started with Start.

func AsRoot

func AsRoot() StartOption

AsRoot starts a new trace, ignoring any span in the context.

func WithAttrs

func WithAttrs(attrs ...slog.Attr) StartOption

WithAttrs sets attributes at the start.

func WithKind

func WithKind(k Kind) StartOption

WithKind sets the span's kind. The default is Internal.

func WithRemoteParent

func WithRemoteParent(sc SpanContext) StartOption

WithRemoteParent makes the span a child of a span in another process, from a traceparent header or a queued job.

func WithTracer

func WithTracer(t *Tracer) StartOption

WithTracer records the span with t rather than the parent's tracer or the default.

type Stats

type Stats struct {
	Dropped uint64 // an exporter's queue was full
	Failed  uint64 // an exporter didn't take them after retrying
}

Stats counts spans a tracer didn't export.

type Status

type Status struct {
	Code    StatusCode
	Message string
}

Status is a span's outcome and, for errors, its message.

type StatusCode

type StatusCode int

StatusCode is a span's outcome.

const (
	Unset StatusCode = 0
	OK    StatusCode = 1
	Error StatusCode = 2
)

The codes, numbered as in OTLP.

type TraceID

type TraceID [16]byte

TraceID identifies a trace, as W3C trace context has it.

func (TraceID) IsValid

func (t TraceID) IsValid() bool

IsValid reports whether the ID is set.

func (TraceID) String

func (t TraceID) String() string

type Tracer

type Tracer struct {
	// contains filtered or unexported fields
}

Tracer records spans and hands them to exporters. Make one with New.

func Default

func Default() *Tracer

Default returns the default tracer, or nil.

func DevOnly

func DevOnly() *Tracer

DevOnly returns a tracer that records every span for tern dev's log view alone, or nil outside tern dev. kit uses it when the app has no tracer of its own.

func New

func New(o Options) *Tracer

New returns a tracer. Under tern dev, it also sends spans to the dev server's log view.

func (*Tracer) Close

func (t *Tracer) Close(ctx context.Context) error

Close flushes the exporters and stops them.

func (*Tracer) Flush

func (t *Tracer) Flush(ctx context.Context) error

Flush waits until the spans ended so far are exported, or ctx ends.

func (*Tracer) Stats

func (t *Tracer) Stats() Stats

Stats returns t's counts.

Directories

Path Synopsis
Package otlp exports spans to an OpenTelemetry collector, or any service that takes OTLP over HTTP (Grafana Tempo, Honeycomb, Jaeger, SigNoz, Datadog, New Relic…), as OTLP/HTTP JSON:
Package otlp exports spans to an OpenTelemetry collector, or any service that takes OTLP over HTTP (Grafana Tempo, Honeycomb, Jaeger, SigNoz, Datadog, New Relic…), as OTLP/HTTP JSON:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL