Skip to content
Warlock.js v4

Installation

@warlock.js/logger is structured logging for Node. Instead of scattering console.log everywhere, you emit entries tagged with a module, an action, and a message, and the logger fans each one out to every destination you’ve registered — the terminal in dev, a rotating file in prod, Slack for errors. You get level filtering, secret redaction, and a clean shutdown that doesn’t drop the last few lines — without rewriting a single call site when you add a new destination.

Here’s the whole thing in one screen. Copy it into a file, run it, and you’re logging:

src/logger-demo.ts
import { log, ConsoleLog } from "@warlock.js/logger";
// 1. Register where logs should go (just the terminal for now).
log.addChannel(new ConsoleLog());
// 2. Log with a module, an action, a message, and optional structured context.
await log.info("users", "register", "New account created", { userId: 42 });
await log.warn("auth", "login", "Password attempt failed", { attempts: 3 });
await log.success("billing", "charge", "Payment captured", { amount: 4999 });
// 3. Pass an Error straight through — file channels keep the full stack.
try {
throw new Error("Stripe declined the card");
} catch (error) {
await log.error("billing", "charge", error);
}
ℹ (2024-03-15T10:22:01.482Z) [users] [register] New account created
⚠ (2024-03-15T10:22:01.486Z) [auth] [login] Password attempt failed
✓ (2024-03-15T10:22:01.488Z) [billing] [charge] Payment captured
✗ (2024-03-15T10:22:01.491Z) [billing] [charge] Stripe declined the card

That’s the core value: one consistent call shape, colored and searchable, ready to route anywhere. The rest of these docs build on exactly this.


@warlock.js/logger is a standalone package — no framework required. Install it in any Node project and configure it in plain TypeScript or JavaScript.

Terminal window
npm install @warlock.js/logger

Inside a Warlock app, the logger ships transitively through @warlock.js/core — you can import log directly without adding the dependency yourself.

The logger starts with no channels attached. Nothing is printed or written until you add at least one:

src/index.ts
import { log, ConsoleLog } from "@warlock.js/logger";
log.addChannel(new ConsoleLog());
await log.info("users", "register", "New user created successfully");

Three lines of setup, then you’re logging. Adding channels is covered in full on the Configuration page.

The package exports one default instance and one class:

ExportWhat it isWhen to use
logThe Logger singleton — pre-instantiated with zero channelsAlmost always. Day-to-day logging and configuration go through it.
LoggerThe classWhen you need an isolated logger (libraries, sandboxes, parallel test suites).
import { log, Logger, ConsoleLog, FileLog } from "@warlock.js/logger";
// Singleton — most code uses this
log.addChannel(new ConsoleLog());
// Custom isolated instance
const auditLog = new Logger();
auditLog.addChannel(new FileLog({ name: "audit" }));

log is a Logger instance, not a function — every method is reachable through it (info, debug, warn, error, success, addChannel, configure, setMinLevel, setRedact, assert, timer, channel, flushSync, enableAutoFlush, disableAutoFlush).

Continue to Configuration to wire up channels, set a minimum level, and configure the logger for each environment.