@jazim/logger
v1.0.0
Published
Structured Pino logger with AsyncLocalStorage request context for Node.js
Downloads
117
Maintainers
Readme
@jazim/logger
Structured logging via Pino with AsyncLocalStorage request context. Dual ESM / CommonJS. Output is JSON on stdout by default, or human-readable when pretty mode is enabled.
Install
pnpm add @jazim/loggerUsage
import { createLogger, withContext, getContext } from "@jazim/logger";
const log = createLogger({ service: "my-api" });
log.info("user profile updated", { userId });
log.warn("resource not found", { resourceId });
log.error("database query failed", { err });Levels: trace, debug, info, warn, error, fatal.
Options
createLogger({
service: "my-api", // required — included on every log line
level: "debug", // optional — defaults to LOG_LEVEL or "info"
redactPaths: ["headers.authorization"], // optional — extra redact paths
pretty: true, // optional — force pretty output; defaults to LOG_PRETTY === "1"
});Request context
Wrap work in withContext so logs automatically include fields like reqId:
await withContext({ reqId: crypto.randomUUID() }, async () => {
log.info("handling request"); // includes reqId
});Nested contexts inherit parent fields; inner keys override outer on conflict:
await withContext({ reqId: "abc" }, async () => {
await withContext({ feature: "auth" }, async () => {
log.info("login ok"); // includes reqId + feature
});
});Per-call fields merge with context; per-call wins on conflict.
Feature-scoped loggers
Attach stable fields once with child:
const authLog = log.child({ feature: "auth" });
authLog.info("login ok", { userId }); // includes feature: "auth"
authLog.warn("bad password", { userId });
// child can nest
const stepLog = authLog.child({ step: "token" });
stepLog.info("issued"); // feature + stepChild bindings merge with ALS context and per-call data: { ...context, ...bindings, ...data }.
Error logging
Pass the Error as err so Pino serializes the stack:
log.error("failed to create user", {
err: err instanceof Error ? err : new Error(String(err)),
userId,
});Pretty output (local dev)
Enable human-readable logs locally:
LOG_PRETTY=1 node app.jsOr pass pretty: true to createLogger. Production / Lambda should leave pretty off (default) for JSON lines.
Environment variables
| Variable | Default | Effect |
|----------|---------|--------|
| LOG_LEVEL | info | Minimum level (trace, debug, info, warn, error, fatal) |
| LOG_REDACT_PATHS | — | Comma-separated extra field paths to redact |
| LOG_PRETTY | — | Set to 1 for colorized pretty output |
Built-in redaction paths: password, token, *.secret.
Example output
JSON (default):
{
"level": 30,
"levelName": "info",
"time": "2026-09-02T08:55:00.123Z",
"service": "my-api",
"reqId": "550e8400-e29b-41d4-a716-446655440000",
"feature": "auth",
"msg": "handling request"
}Pretty (LOG_PRETTY=1):
[08:55:00.123] INFO (my-api): handling request
reqId: "550e8400-e29b-41d4-a716-446655440000"
feature: "auth"