@portable/log
Functions
Log.format
Returns a record's arguments as one line of text, replacing format specifiers as Node's
util.format does, except that objects are written with JSON.stringify instead of
util.inspect. %s, %d, %i, %f, %j, %o and %O in the first argument are replaced
with the next arguments, %c and its argument are dropped, and the remaining arguments are
appended after spaces. Errors are written as their stack. A format string with no arguments
after it is returned unchanged.
function format(record: Record): string;Log.subscribe((record) => lines.push(Log.format(record)));Log.create
Returns a logger for namespace. debug and info calls are off until a pattern enables the
namespace, and warn and error calls are on until a pattern turns it off.
function create(namespace: string): Logger;const log = Log.create('app:db');
log.debug('connected to %s', url);
log.warn('slow query', { ms: 812 });Log.disable
Turns off every namespace at every level, warnings and errors included, and returns the
patterns that were in effect, so enable can restore them.
function disable(): string;const previous = Log.disable();
Log.enable(previous);Log.enable
Sets which namespaces log, with debug's pattern syntax plus an optional minimum level:
app:*,-app:noisy,lib:*=warn. Pass undefined to keep the current patterns and change only
options. Throws a RangeError for an unknown level.
function enable(
patterns: string | undefined,
options: enable.Options = {},
): void;| Option | Type | Default | Description |
|---|---|---|---|
persist | boolean | false | Also writes the patterns to localStorage.debug, so they apply after a reload. |
console | boolean | true | Writes enabled calls to console. Set to false to log only through subscribe. |
time | boolean | false | Prefixes console output with an ISO 8601 timestamp. |
context | ContextStorage | Storage for withContext, such as new AsyncLocalStorage() from node:async_hooks. |
Log.enable('app:*', { time: true });Log.subscribe
Calls subscriber with every enabled log call, after the console output.
function subscribe(
subscriber: (record: Record) => void,
options: subscribe.Options = {},
): void;| Option | Type | Default | Description |
|---|---|---|---|
signal | AbortSignal | Removes the subscriber when the signal aborts. |
Log.subscribe((record) => lines.push(Log.format(record)), { signal });Log.withContext
Runs fn with properties added to every record logged during the call, including records from
loggers created elsewhere. Needs a context storage passed to enable. Without one it just
calls fn.
function withContext<result>(
properties: Properties,
fn: () => result,
): result;Log.withContext({ requestId }, () => handle(request));Log.write
Writes a record to console as the default output does: the namespace in a color picked from
its name, then the arguments, then the properties. debug records go to console.log, because
Chrome hides console.debug unless its Verbose level is on.
function write(record: Record): void;Log.enable(undefined, { console: false });
Log.subscribe((record) =>
Log.console({ ...record, properties: redact(record.properties) }),
);Types
Log.ContextStorage
Storage for withContext. Node's AsyncLocalStorage has this shape, and so does
AsyncLocalStorage in Bun, Deno and Cloudflare Workers with nodejs_compat.
type ContextStorage = {
run: <result>(store: Properties, fn: () => result) => result;
getStore: () => Properties | undefined;
};Log.Level
A log level, from most to least verbose.
type Level = | | | ;Log.Logger
A logger made by create. Its methods don't use this, so they can be passed around alone.
type Logger = {
debug: (...args: readonly unknown[]) => void;
info: (...args: readonly unknown[]) => void;
warn: (...args: readonly unknown[]) => void;
error: (...args: readonly unknown[]) => void;
extend: (suffix: string) => Logger;
with: (properties: Properties) => Logger;
isEnabled: (level?: Level) => boolean;
readonly namespace: string;
};Log.Properties
Properties attached to a record by with and withContext.
type Properties = Readonly<{
[key: string]: unknown;
}>;Log.Record
One enabled log call, as subscribe receives it.
type Record = {
time: Date;
level: Level;
namespace: string;
args: readonly unknown[];
properties: Properties;
};