Skip to main content

Logs are data

advanced16 min readLesson 173 of 180

Event fields, level contracts, swallowed exceptions, and context propagation across executors.

A log line is a database row you're writing to stdout: timestamp, level, event name, and key-value fields. Grep for userId=42 works when fields are first-class; parsing English prose at 3 a.m. does not.

record LogEvent(Instant ts, String level, String event, Map<String, String> fields)

Levels are a contract: ERROR = a human should act (paging threshold); WARN = degraded but self-healing (retries, fallbacks); INFO = state transitions (started, finished); DEBUG = the details you wish you'd logged, enabled per-request. The cardinal sin: catch (Exception e) {} — an exception that vanishes cannot be diagnosed; log it with its stack, at the level that matches whether a human must act.

Context: the fields every event in one request shares — requestId, userId — belong in a thread-local (log frameworks call it MDC) that the framework stamps onto every line. Propagation across async boundaries is the advanced wrinkle: the context must be captured at task submission and re-applied in the task, because thread-locals do not cross executor hops.