Emit telemetry
pipeline.Main installs OpenTelemetry and Temporal instrumentation. User code
adds domain information through pkg/obs; it does not configure exporters.
Logs
obs.Info(ctx, "package installed", obs.Str("name", pkg), obs.Int("attempt", n))
obs.Warn(ctx, "retrying", obs.Err(err))
Available levels are Debug, Info, Warn, and Error. Attributes use
Str, Int, and Err. The worker automatically adds run, pipeline, activity,
and entity correlation.
obs.RunTail(ctx, cmd, bytes) streams stdout/stderr while retaining a bounded
tail for the returned error. Prefer it around external commands so the failure
reason reaches the record's logs.
Metrics and spans
obs.Count(ctx, "packages.installed", 1, obs.Str("manager", "dnf"))
obs.Gauge(ctx, "queue.depth", depth)
obs.Measure(ctx, "download.seconds", elapsed)
ctx, span := obs.Span(ctx, "download", obs.Str("source", source))
defer span.End()
Count is an integer counter increment, Gauge records a value, and
Measure records a floating-point measurement. Names should describe stable
product signals rather than Go functions.
Durable events
err := obs.EventFor(ctx, "docker/db", "schema-migrated", payload)
An event is a durable domain milestone in the record's workflow history, not a
log line. Use it sparingly: each event consumes history. In a resource activity,
obs.Event uses the entity already attached to the context; use EventFor
when acting on another record explicitly.
Read all dimensions through graphenectl observe or Studio. Backend wiring belongs to server configuration.