telemetry

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package telemetry records what 012 spends its time on, as structured events written with log/slog. It is off unless a destination is given: a JSON log file (012 --log path, or O12_LOG), one line per event that DuckDB or an OpenTelemetry Collector's filelog receiver can read, and/or an OTLP/HTTP endpoint (012 --otlp URL, or OTEL_EXPORTER_OTLP_ENDPOINT) that gets the events as logs, spans as traces and frame summaries as metrics. Stdout belongs to the terminal UI. See docs/contributing/observability.md.

Events carry sizes, counts and durations only: never cell contents, file contents or secrets.

The API is small on purpose, so call sites stay few and backends can change behind it without touching them.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Close

func Close() error

Close stops recording, sends what OTLP has queued (waiting at most about one request timeout) and closes the log file.

func Debug

func Debug(name string, d time.Duration, attrs ...slog.Attr)

Debug logs a finished operation at Debug level, for events too frequent to keep by default (and to send as spans).

func Enabled

func Enabled() bool

Enabled reports whether events are being recorded.

func Event

func Event(name string, d time.Duration, attrs ...slog.Attr)

Event logs a finished operation that took d, as a root span.

func Frame

func Frame(render, key time.Duration)

Frame records a frame that took render to draw. key is how long ago the key press it answers happened, or 0 when it answers none.

func Logger

func Logger() *slog.Logger

Logger is the event logger; it discards everything while off.

func Set

func Set(name string, v int64)

Set records a gauge, such as the number of cells or JEV questions waiting, reported with the next frame summary.

func Setup

func Setup(c Config) (func() error, error)

Setup starts recording as c says. The returned function flushes and closes the log and sends what OTLP has queued; call it on exit.

func WithParent

func WithParent(ctx context.Context, p Parent) context.Context

WithParent returns ctx carrying p, for ParentFrom.

Types

type Config

type Config struct {
	// LogPath is the JSON log file, appended to. Empty (and no OTLP)
	// turns telemetry off.
	LogPath string
	// Level is the least severe level logged; Info by default. Debug adds
	// an event for every frame and every command.
	Level slog.Level
	// Version is 012's version or commit, added to the start event and
	// sent as the OTLP service.version.
	Version string
	// OTLP sends events to an OpenTelemetry endpoint too, or instead.
	OTLP OTLPConfig
}

Config says where events go.

func ConfigFromEnv

func ConfigFromEnv() Config

ConfigFromEnv reads O12_LOG, O12_LOG_LEVEL (debug, info, warn) and the standard OTEL_* variables described at OTLPConfig.

type OTLPConfig

type OTLPConfig struct {
	// Endpoint is the base URL, like http://localhost:4318, to which
	// /v1/logs, /v1/traces and /v1/metrics are appended
	// (OTEL_EXPORTER_OTLP_ENDPOINT, or 012 --otlp).
	Endpoint string
	// LogsEndpoint, TracesEndpoint and MetricsEndpoint are full URLs for
	// one signal each, used as they are
	// (OTEL_EXPORTER_OTLP_{LOGS,TRACES,METRICS}_ENDPOINT).
	LogsEndpoint, TracesEndpoint, MetricsEndpoint string
	// NoLogs, NoTraces and NoMetrics leave a signal out
	// (OTEL_{LOGS,TRACES,METRICS}_EXPORTER=none).
	NoLogs, NoTraces, NoMetrics bool
	// Headers go with every request, e.g. for authentication
	// (OTEL_EXPORTER_OTLP_HEADERS). They are never logged.
	Headers map[string]string
	// Resource adds resource attributes (OTEL_RESOURCE_ATTRIBUTES);
	// service.name stays 012.
	Resource map[string]string
	// Timeout bounds each request (OTEL_EXPORTER_OTLP_TIMEOUT, in
	// milliseconds); 3 s when zero.
	Timeout time.Duration
	// NoCompression sends plain JSON instead of gzip
	// (OTEL_EXPORTER_OTLP_COMPRESSION=none).
	NoCompression bool
	// Disabled turns OTLP off whatever else is set (OTEL_SDK_DISABLED).
	Disabled bool
}

OTLPConfig says where OTLP goes. ConfigFromEnv reads it from the standard OTEL_* variables. Nothing is sent unless an endpoint is set.

type Parent

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

Parent identifies a span that others can nest under, from any goroutine. The zero Parent is none: spans under it are roots, each in a trace of its own.

func ParentFrom

func ParentFrom(ctx context.Context) Parent

ParentFrom is the Parent ctx carries, zero if none.

func (Parent) Event

func (p Parent) Event(name string, d time.Duration, attrs ...slog.Attr)

Event logs a finished operation that took d, as a span under p.

func (Parent) Start

func (p Parent) Start(name string, attrs ...slog.Attr) Span

Start begins a span under p, like the package's Start.

type Span

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

Span times one operation. The zero Span, returned while off, does nothing. With OTLP on it is sent as a span, and the log record of the same event carries its trace, span and parent ids.

func Start

func Start(name string, attrs ...slog.Attr) Span

Start begins timing an operation named like "recalc" or "import", with up to four attributes known at the start, as a root span.

func (Span) End

func (s Span) End(attrs ...slog.Attr)

End logs the operation with its duration in milliseconds and any attributes learned along the way, such as rows read. A span started through a Trace is no longer open in it.

func (Span) Fail

func (s Span) Fail(err error, attrs ...slog.Attr)

Fail ends the span with an error, logged at Warn with its message.

func (Span) Parent

func (s Span) Parent() Parent

Parent is the handle for nesting spans under s; zero for the zero Span.

type Trace

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

Trace is the spans open in one thread of work, innermost last: one UI program's, or one import's. Spans started through it nest under the innermost open span, and stay open in it until they end. It belongs to one goroutine at a time, like the Model or workbook that keeps it. A nil *Trace works too, with nothing open.

func NewTrace

func NewTrace(base Parent) *Trace

NewTrace returns a Trace with base open, if it isn't zero, beneath everything started through it.

func (*Trace) Begin

func (t *Trace) Begin(name string)

Begin starts a span like Start and keeps it for End, for code that has nowhere to keep a Span, such as the engine's hooks (see cmd/012). On a nil Trace it does nothing.

func (*Trace) End

func (t *Trace) End(attrs ...slog.Attr) bool

End ends the span last begun by Begin, reporting whether there was one.

func (*Trace) Enter

func (t *Trace) Enter(p Parent) int

Enter makes p the innermost open span, until Leave with the depth it returns: for a span that lives across several updates (a macro run, a session) to hold what each of them starts.

func (*Trace) Event

func (t *Trace) Event(name string, d time.Duration, attrs ...slog.Attr)

Event logs a finished operation that took d, under the innermost open span.

func (*Trace) Leave

func (t *Trace) Leave(depth int)

Leave closes what was opened since the Enter that returned depth.

func (*Trace) Parent

func (t *Trace) Parent() Parent

Parent is the innermost span open, zero if none is: the handle to give work done on another goroutine.

func (*Trace) Start

func (t *Trace) Start(name string, attrs ...slog.Attr) Span

Start begins a span under the innermost open one; it is the innermost itself until it ends.

Jump to

Keyboard shortcuts

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