Your first log
Once a channel is attached, you log through the log singleton. Every entry follows the same shape: module, action, message, and an optional context object.
The module · action · message pattern
Section titled “The module · action · message pattern”Every log call takes three positional arguments — module, action, message — plus an optional fourth context object for structured data.
log.info("users", "register", "New user created", { userId: 42 });// ^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^// module action message context (optional)The first three let you filter and search logs by feature area instead of wading through flat text; the fourth carries the structured metadata. Real-world examples across domains:
// Authlog.info("auth", "login", "User signed in");log.warn("auth", "tokenExpired", "JWT expired for session");
// Payments — message in the 3rd arg, structured data in the 4th (context)log.info("payments", "chargeInitiated", "Charge initiated", { amount: 4999, currency: "USD" });log.error("payments", "chargeFailed", new Error("Stripe declined card"));
// Emaillog.success("email", "welcomeSent", "Welcome email delivered");log.warn("email", "bounced", "Delivery failed — invalid address");
// Orderslog.debug("orders", "priceCalculation", "Calculated cart total", { subtotal: 120, discount: 10 });log.success("orders", "fulfillment", "Order shipped via FedEx");The six log levels
Section titled “The six log levels”| Level | Method | When to use | Console style |
|---|---|---|---|
debug | log.debug() | Dev diagnostics, variable dumps, flow tracing | magenta |
info | log.info() | Normal operational events (user registered, job queued) | blue |
warn | log.warn() | Unexpected but recoverable conditions (retry, fallback) | yellow |
error | log.error() | Handled failures that need attention; app continues | red |
success | log.success() | Explicit happy-path confirmation (payment completed) | green |
fatal | log.fatal() | Unrecoverable failures; the app is going down (boot fail, uncaughtException) | bright red on red background |
log.debug("cache", "miss", "Key not found, fetching from DB");log.info("jobs", "queued", "SendInvoice job added to queue");log.warn("api", "rateLimitApproaching", "80% of quota used");log.error("db", "connectionFailed", new Error("ECONNREFUSED 5432"));log.success("payments", "captured", "Payment of $49.99 captured");log.fatal("config", "missingSecret", new Error("STRIPE_KEY is required to boot"));Structured logging — the context object
Section titled “Structured logging — the context object”To attach arbitrary metadata, pass a fourth context argument, or pass a full LoggingData object to log.log(...).
// Fourth argument — contextlog.info("orders", "checkout", "Order placed", { orderId: "ord_9f2a", userId: 101, amount: 4999,});
// Object form — log.log(...)import { log, type LoggingData } from "@warlock.js/logger";
const entry: LoggingData = { type: "error", module: "orders", action: "checkout", message: "Card declined", context: { orderId: "ord_9f2a", userId: 101, amount: 4999, retryCount: 2, },};
log.log(entry);File and JSON channels persist context alongside the entry. The console channel renders it on a second line only when its showContext option is enabled — see Console Channel.
Logging errors
Section titled “Logging errors”Pass an Error instance directly as the message argument. File and JSON channels capture the stack trace automatically.
try { await processPayment(orderId);} catch (err) { log.error("payments", "processPayment", err);}Helpers — timer and assert
Section titled “Helpers — timer and assert”Two shortcuts every Logger exposes.
timer(module, action) — measure a duration
Section titled “timer(module, action) — measure a duration”Returns an end-function that emits an info entry with a durationMs field in context when called.
const end = log.timer("db", "users.findById");const user = await usersRepo.findById(id);end({ id, found: !!user });// → info "db" "users.findById" "completed in 42ms" { durationMs: 42, id, found: true }Pass an object to the end-function to merge extra fields into the context.
assert(condition, module, action, message, context?) — log on a failed invariant
Section titled “assert(condition, module, action, message, context?) — log on a failed invariant”Logs an error entry only when condition is falsy. A no-op otherwise — the entry is never built and channels aren’t invoked, so it’s free on the happy path. Like console.assert, but it routes through the logger pipeline so persistent channels capture the failure.
log.assert(user !== null, "auth", "session", "user vanished mid-flight", { sessionId });You’ve covered the call-site API. Next, learn how channels decide what to emit and where — start with the Channels Overview.
Or jump straight to a task-shaped guide: