Skip to content

ADR-023: Observability & Wide-Events Logging

FieldValue
TypeSkill Resource
Source~/.copilot/skills/adr/references/adr-023-observability-and-wide-events-logging.md
DescriptionNot specified

Source Content

ADR-023: Observability & Wide-Events Logging

Decision

All services emit wide, structured JSON events — one log line per meaningful operation, drawn from a standardized field registry. The msg field is always static and grep-stable; dynamic values go in top-level fields or data, never interpolated into msg.

Key rules

  • Emit one log entry per meaningful operation, and attach all context to that single wide event.
  • Keep msg static and grep-stable: "request completed", never "request completed for user 123".
  • Make event dot-namespaced and machine-readable: "http.request_completed", "billing.payment_failed".
  • Always include the Tier 1 fields: timestamp, level, msg, event, service, version, env.
  • Never log sensitive data. The canonical never-log list (PII, secrets, payloads over 2 KB) lives in ADR-025.
  • Put stack traces in data.stack, never as a top-level field.
  • Use the standard implementations: pino (TypeScript), zerolog (Go), structlog (Python).

Code patterns

log.info({ event: 'billing.subscription_created', data: { plan: 'pro' } }, 'subscription created')
log.error({ event: 'billing.payment_failed', error: err.message, data: { stack: err.stack } }, 'payment failed')

Why

Wide events keep one operation on one line, so context is queryable without correlating across entries. A static msg stays greppable while dynamic detail lives in structured fields. The never-log list is centralized in ADR-025 (rather than duplicated here) so it stays single-source-of-truth across services.

Applies when

You are adding logging to a new service, setting up pino, zerolog, or structlog, or reviewing a log statement for correctness.

  • ADR-025 — secrets management; canonical never-log list.
  • ADR-024 — engineering standards; logging checklist.
  • ADR-027 — default tech stack; observability defaults.