error tracking

why

errors are only useful if they can be counted and compared over time. grouping by a stable code plus boundary keeps today's error and next month's recurrence of the same error in one bucket — seeing it once is signal, a thousand times is an incident. a reworded message or moved boundary otherwise shatters history, and incident response degrades into grepping disconnected log lines.

rule

every typed diagnostic error that reaches a person or a log is grouped by its stable code, counted, and attached to the correlation id and boundary that produced it. an error is a first-class durable fact. without stable grouping you cannot tell new from recurring; with it, one code + boundary query reveals the pattern and recurrence.

what is tracked

diagnostic errors define the typed shape. tracking adds the accounting layer:

layerowns
diagnostic errorstable code, boundary, cause, remediation — the contract.
loggingevery raised diagnostic is logged as a structured error event with correlation id.
trackinggrouping by code + boundary, counts over time, first/last seen, sample payload.
alertingthreshold rules over tracked groups, per metrics and alerts.

grouping and noise

group by the stable diagnostic code and boundary — never by message string. provider errors map to the local diagnostic that wrapped them; the original cause is preserved as a field, not as the grouping key. wording changes must not fragment history.

do not

  • track raw exceptions with no stable code — they group into noise.
  • swallow a diagnostic without logging it because "it's expected" — expected failures are logged at warn with the same structure, or explicitly modeled as a semantic state, not silently dropped.
  • alert on every occurrence — alert on rate or persistence, per metrics and alerts.
  • let the tracking call itself throw and break the request path; tracking is best-effort after the diagnostic is composed.

verification

pick three distinct diagnostic codes. for each, confirm: logs contain its structured event with correlation id; the tracking store groups them under one key unchanged by wording; the rate over a probe window matches the count of logged events. raise one deliberate diagnostic in a non-production environment and confirm it appears end-to-end.

good and bad

bad

log: "error creating user: timeout connecting to auth provider"
log: "auth provider connection timed out (attempt 2)"
log: "auth service unavailable"
log: "createUser failed, provider down"

dozens of phrasings, so you cannot query "auth provider timeout"; you do not know if it recurs (ten times today?) or is a one-off; at incident time you grep and guess they share a root cause. history shatters on every rewording, so a regression looks brand-new and recurrence counts — signal vs incident — can never be computed. responders burn the recovery window reconstructing what the system already knew.

good

// logged with stable fields
{
code: "auth.provider.timeout",
boundary: "authentication adapter",
correlationId: "c_9f2a",
cause: "connection timeout (5s)",
timestamp: "2025-08-26T14:23:18Z"
}

one stable code groups every auth timeout regardless of logger or wording. the tracking system counts them under that single key; one query on code + boundary reveals 47 occurrences in the last hour, all from provider adapter, 40 in the last 5 minutes (clear incident). the correlation id finds the exact operation that hit it.

search pages

go to any page