Logging
Structured logging that works everywhere the code runs.
import { log } from '@kreogen/observability/log';
log.info('Subscription created', { userId, plan });
log.warn('Retrying webhook', { attempt });
log.error('Payment failed', { customerId, reason });Four levels — debug, info, warn, error — each taking a message and an
optional object of structured fields.
Output
In development, output is human-readable. In production it is one JSON object per line:
{"level":"info","time":"2026-01-01T12:00:00.000Z","message":"Subscription created","userId":"usr_123","plan":"pro"}That shape is deliberate. Containers hand stdout straight to whatever collector the platform runs — Loki, Vector, CloudWatch — so JSON on stdout is already the transport. A logging library with its own transport would add a hop that nothing reads.
Why there is no logging dependency
The logger is dependency-free because parseError uses it, and parseError
runs in server components, route handlers and the browser alike. Anything this
module imports is traced into client bundles, so a Node-only logging library
would either bloat them or fail outright.
If a project needs richer server-side logging, add it in server-only code rather than here.
What to log
Log decisions and outcomes, not control flow. A useful line answers "what happened, to whom, and why" without needing the surrounding code.
Never log secrets, tokens, passwords or full request bodies. Structured fields make redaction the default: log an identifier rather than an object.