Observability

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.