@abhinav-dev/ctx-logger
v0.2.0
Published
Explicit, vendor-neutral structured logger for Node.js/TypeScript (pino engine).
Readme
Structured Logger (Node.js / TypeScript)
A simple, explicit, and vendor-neutral logging wrapper for Node.js services.
Designed to survive:
- CloudWatch → Splunk → Datadog migrations
- different execution models (API, cron, queue, batch, CLI)
- long-lived enterprise codebases
No magic. No hidden context. No runtime dependencies on async hooks.
Why this library exists
In many services:
- logging libraries get swapped over time (pino → something else)
- log destinations change (CloudWatch → Splunk → Datadog)
- log formats drift and dashboards break
This library solves that by enforcing:
- a stable log schema
- explicit context passing
- structured JSON logs
- engine abstraction (pino today, others later)
Core principles
- JSON logs only
- Explicit context (no AsyncLocalStorage)
- Stable, machine-friendly event names
- Human-friendly messages
- Redaction by default
- Compatible with CommonJS and older Node runtimes
Installation
npm install @abhinav-dev/ctx-loggerQuick Start
- Create the logger (once)
import { createLogger } from "@abhinav-dev/ctx-logger";
const logger = createLogger();- Create a context (per request / job / trigger)
const ctx: LoggerContext = {
service: "orders-api",
env: "prod",
version: "1.2.3",
correlation_id: "c-9f3e8d2",
};- Log events
logger.info(ctx, "service_started");
logger.info(ctx, "order_created", {
order_id: "o-123",
amount: 499,
});
logger.error(ctx, "db_query_failed", {
table: "orders",
reason: "timeout",
});
Derived context (optional)
To add stable sub-scope fields without mutating the original context:
const orderCtx = logger.with(ctx, { order_id: "o-123" });
logger.info(orderCtx, "order_loaded");
Log Output
Example:
{
"level": 30,
"time": "2026-01-16T06:38:58.483Z",
"service": "demo",
"env": "dev",
"version": "0.1.0",
"correlation_id": "c-1",
"level_name": "info",
"event": "hello",
"message": "hello",
"details": {
"name": "a",
"password": "[REDACTED]"
}
}
Redaction
Sensitive keys are redacted automatically inside details.
Default redacted keys (case-insensitive):
- authorization
- cookie, set-cookie
- password
- token
- secret
- api_key
- client_secret
Example:
logger.info(ctx, "login_attempt", {
username: "myusername",
password: "secret123",
});
Output:
"details": {
"username": "myusername",
"password": "[REDACTED]"
}
