Functions + OpenTelemetry
Critical rules
- Observability is an observer: wrap with
trace(); business functions stay telemetry-blind and return Results. - Structured JSON logs only (Pino) — never string interpolation. Redact sensitive fields in logs and span attributes.
- Use OpenTelemetry semantic attribute names (
user.id, notuserId). - Map Result ok/err to span status. Correlate logs with
traceId/spanId. Prefer one canonical wide event per request. - Tests must not change when tracing is off (
trace()is a no-op). - Before wrapping or configuring, read references/patterns.md and references/setup.md.
Workflow
- Init autotel + Pino with redaction and optional attribute filter — see references/setup.md.
- Wrap
fn(args, deps)withtrace((ctx) => async (args, deps) => ...). - Set semantic attributes; map Result to span status; never put retry/branch decisions in the core function for telemetry.
- Ensure logs include trace/span IDs; enable canonical wide events for request roots when useful.
- Use
track()for point-in-time business events; keep existing unit tests unchanged.
Resources
- references/patterns.md — structured logs, trace wrap, semantics, redaction, wide events. Read when instrumenting.
- references/setup.md — init, backends, track vs trace, test no-op. Read when bootstrapping.
Validation
- Structured fields, not string interpolation
- Tracing in wrapper only; function stays blind
- OTel semantic attribute names
- PII redacted in logs and spans
- Result maps to span status; logs carry trace/span IDs
- Existing tests pass unchanged
Constraints
- Not a substitute for proper Result errors. Avoid hot loops where span overhead dominates.
- Related:
result-types,fn-args-deps,api-design,resilience.