Configuration
The log singleton starts with zero channels. Configuration is how you attach channels, set a severity floor, wire shutdown flushing, and set a redaction floor — all at the logger level. Per-channel options (level filters, timestamp format, custom filters) are covered on the Channels Overview.
Adding channels
Section titled “Adding channels”Three methods attach channels to any Logger instance. Pick based on how much control you need.
addChannel(channel) — append one
Section titled “addChannel(channel) — append one”Adds a single channel without touching the ones already registered. Safe to call multiple times.
import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
log.addChannel(new ConsoleLog());log.addChannel(new FileLog({ storagePath: "./logs" }));setChannels(channels[]) — replace all
Section titled “setChannels(channels[]) — replace all”Replaces every existing channel with the supplied array. Use it for a clean slate — for example, swapping channels per environment.
import { log, FileLog } from "@warlock.js/logger";
log.setChannels([ new FileLog({ storagePath: "./logs", chunk: "daily" }),]);configure({ channels, autoFlushOn, minLevel, redact }) — object-style setup
Section titled “configure({ channels, autoFlushOn, minLevel, redact }) — object-style setup”Accepts an options object. Every field is optional — pass only what you want to change.
| Field | Effect |
|---|---|
channels | Replaces the channel list (same as setChannels). |
autoFlushOn | Installs process-level auto-flush handlers — see Shutdown & flushing. |
minLevel | Sets the logger-wide severity floor. Entries below this rank are dropped before fan-out. |
redact | Sets the logger-wide redaction floor — see Redaction. |
import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
log.configure({ channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })], autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"], minLevel: "info", redact: { paths: ["context.password", "context.*.token"], },});Environment-based setup
Section titled “Environment-based setup”Build the channel list once at startup, keyed on process.env.NODE_ENV, then apply it with a single setChannels. Put it in a dedicated file and import it early in your entry point.
import { log, ConsoleLog, FileLog, type LogChannel } from "@warlock.js/logger";
const channels: LogChannel[] = [];
if (process.env.NODE_ENV === "production") { channels.push( new FileLog({ storagePath: process.cwd() + "/storage/logs", chunk: "daily", rotate: true, maxFileSize: 10 * 1024 * 1024, // 10 MB }), );} else if (process.env.NODE_ENV !== "test") { // development and everything else — test stays silent (empty array) channels.push(new ConsoleLog());}
log.setChannels(channels);import "./logger"; // configures the singleton as a side effect
import { log } from "@warlock.js/logger";
log.info("app", "boot", "App started");log is a singleton — import "./logger" runs the configuration once as a side effect, and every other file imports log straight from @warlock.js/logger. No need to re-export it.
Logger-wide minimum level
Section titled “Logger-wide minimum level”The cheapest way to silence low-severity noise is the logger-wide minLevel. Entries below the rank are dropped before fan-out — no channel sees them, no filter runs, no allocation happens.
import { log } from "@warlock.js/logger";
// at startuplog.configure({ minLevel: "info" });
// or at runtimelog.setMinLevel("warn");
// clear itlog.setMinLevel(undefined);Severity ranking: debug < info ≈ success < warn < error. Setting minLevel: "warn" drops debug, info, and success. The success level shares info severity — it’s treated as informational, not as a warning.
Retrieving a channel by name
Section titled “Retrieving a channel by name”log.channel(name) returns a previously registered channel instance, or undefined when no channel with that name is found.
| Channel | name |
|---|---|
ConsoleLog | "console" |
FileLog | "file" |
JSONFileLog | "fileJson" |
import { log } from "@warlock.js/logger";
const consoleChannel = log.channel("console"); // ConsoleLog | undefinedconst fileChannel = log.channel("file"); // FileLog | undefinedInside a Warlock app
Section titled “Inside a Warlock app”On @warlock.js/core you don’t call log.setChannels directly. You export a LogConfigurations object from src/config/log.ts and the framework wires it into the singleton on boot, keyed on the current environment:
import { type LogConfigurations } from "@warlock.js/core";import { ConsoleLog, JSONFileLog } from "@warlock.js/logger";
const consoleLog = new ConsoleLog();
const logConfigurations: LogConfigurations = { enabled: true, development: { channels: [consoleLog], }, test: { channels: [consoleLog], }, production: { channels: [ consoleLog, new JSONFileLog({ storagePath: process.cwd() + "/storage/logs", chunk: "daily" }), ], },};
export default logConfigurations;The standalone API above is what you reach for outside Warlock, or for runtime overrides on top of the configuration file.
Continue to Your first log for the call-site API — levels, structured context, errors, and the timer/assert helpers.
Working a specific task? See Silence noisy logs per environment for minLevel / levels / filter in combination.