node-comfortv2.0.0

nc.logger

A console logger that works with zero setup: levels, colors, a small markup for styling, groups, timers and tables. In production, switch to one JSON object per line with LOG_FORMAT=json, and write to rotating files if you need to.

Markup: <% red bold Error:%> disk is full. Any style name works, plus #ff8800, bg#1e1e2e, rgb(255, 128, 0) and bgRgb(...).

Levels, from chatty to severe: trace, debug, info, warn, error, fatal. The default is info, or debug when DEBUG is set; LOG_LEVEL overrides it. Warnings and errors go to stderr.

const { logger } = require("@ix-xs/node-comfort");
import { log } from "@ix-xs/node-comfort/logger";

These functions are also available at the top level: nc.log() is nc.logger.log().

nc.info("Server listening on port 3000");
nc.warn("Cache is almost full");
nc.error(new Error("Payment failed", { cause: err }));
nc.log("<% cyan bold Tip:%> press <% bgWhite black  q  %> to quit");
GuideExplanations and examples for nc.logger.
Read the guide →

Functions

nc.logger.log()

log(...args: unknown[]): typeof nc.logger

Prints a message without a badge. Strings support markup, objects are pretty-printed, and several arguments are joined with spaces.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

Example

nc.log("<% green ✔ Saved %> in <% bold 12ms %>");
nc.log("user:", { id: 1, roles: ["admin"] });

nc.logger.trace()

trace(...args: unknown[]): typeof nc.logger

Very detailed diagnostics, shown only at the trace level.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

nc.logger.debug()

debug(...args: unknown[]): typeof nc.logger

Diagnostics for developers, shown at the debug level (the default when DEBUG is set).

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

Example

nc.debug("cache miss", { key });

nc.logger.info()

info(...args: unknown[]): typeof nc.logger

An informational message.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

Example

nc.info("Server listening on http://localhost:3000");

nc.logger.success()

success(...args: unknown[]): typeof nc.logger

A success message.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

Example

nc.success("Database connected");

nc.logger.warn()

warn(...args: unknown[]): typeof nc.logger

A warning, written to stderr.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

nc.logger.error()

error(...args: unknown[]): typeof nc.logger

An error, written to stderr. Error objects show their stack trace and their chain of causes.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

Example

nc.error(new Error("Cannot save order", { cause: dbError }));

nc.logger.fatal()

fatal(...args: unknown[]): typeof nc.logger

A fatal error, written to stderr. It doesn't stop the process; call process.exit(1) yourself if you mean to.

Parameters

NameType
...args...unknown

Returns typeof import("./Logger")

nc.logger.group()

group(label?: string): typeof nc.logger

Prints a label and indents what follows, until groupEnd(). Groups nest.

Parameters

NameType
labeloptionalstring

Returns typeof import("./Logger")

Example

nc.group("Startup").info("Loading config");
nc.group("Database").success("Connected").groupEnd();
nc.groupEnd();

nc.logger.groupEnd()

groupEnd(): typeof nc.logger

Closes the current group.

Returns typeof import("./Logger")

nc.logger.timeStart()

timeStart(label?: string): typeof nc.logger

Starts a named timer. timeEnd() prints the elapsed time.

Parameters

NameTypeDescription
labeloptionalstringDefault: "default"

Returns typeof import("./Logger")

Example

nc.timeStart("import");
await importProducts();
nc.timeEnd("import"); // "import: 1.24s"

nc.logger.timeEnd()

timeEnd(label?: string): typeof nc.logger

Prints the time since timeStart() with the same label.

Parameters

NameTypeDescription
labeloptionalstringDefault: "default"

Returns typeof import("./Logger")

nc.logger.table()

table(rows: Record<string, unknown>[] | unknown[][], options?: TableOptions): typeof nc.logger

Prints rows as a table.

Parameters

NameType
rowsArray<Record<string, unknown>> | unknown[][]
optionsoptionalTableOptions

Returns typeof import("./Logger")

Example

nc.table([{ name: "Ada", role: "admin" }, { name: "Bob", role: "user" }]);

nc.logger.box()

box(text: string, options?: BoxOptions): typeof nc.logger

Prints text in a box. Nice for startup banners.

Parameters

NameType
textstring
optionsoptionalBoxOptions

Returns typeof import("./Logger")

Example

nc.box("Server ready\nhttp://localhost:3000", { title: "my-app", borderColor: "green" });

nc.logger.divider()

divider(title?: string): typeof nc.logger

Prints a horizontal line, with an optional title in it.

Parameters

NameType
titleoptionalstring

Returns typeof import("./Logger")

nc.logger.setLevel()

setLevel(level: LogLevel): typeof nc.logger

Sets the minimum level.

Parameters

NameType
levelLogLevel

Returns typeof import("./Logger")

Throws RangeError For an unknown level.

Example

nc.setLevel("warn");   // warnings and errors only
nc.setLevel("silent"); // nothing

nc.logger.getLevel()

getLevel(): LogLevel

The current minimum level.

Returns LogLevel

nc.logger.isLevelEnabled()

isLevelEnabled(level: LogLevel): boolean

Would this level be printed? Use it to skip building expensive debug output.

Parameters

NameType
levelLogLevel

Returns boolean

Example

if (nc.isLevelEnabled("debug")) nc.debug(buildHugeReport());

nc.logger.configure()

configure(options: LoggerOptions): typeof nc.logger

Changes several settings at once.

Parameters

NameType
optionsLoggerOptions

Returns typeof import("./Logger")

Example

nc.configure({ level: "debug", file: "logs/app.log" });
nc.configure({ format: "json", fields: { service: "api" } });

nc.logger.setTimestamp()

setTimestamp(value: string | boolean): typeof nc.logger

Shows or hides timestamps, or sets their pattern.

Parameters

NameType
valueboolean | string

Returns typeof import("./Logger")

Example

nc.setTimestamp(false);
nc.setTimestamp("YYYY-MM-DD HH:mm:ss.SSS");

nc.logger.setDelimiter()

setDelimiter(options?: { open?: string; close?: string; } | undefined): typeof nc.logger

Changes the markup delimiters, for when <% clashes with a template engine.

Parameters

NameType
optionsoptional{ open?: string, close?: string }

Returns typeof import("./Logger")

Example

nc.setDelimiter({ open: "{{", close: "}}" });
nc.log("{{red Hello}} world");

nc.logger.createLogger()

createLogger(options?: LoggerOptions): Logger

Creates a logger with its own settings.

Parameters

NameType
optionsoptionalLoggerOptions

Returns Logger

Example

const log = nc.createLogger({ scope: "api", timestamp: "HH:mm:ss.SSS" });
log.info("GET /users 200"); // [14:30:05.120] [api] ℹ INFO GET /users 200
log.child("db").debug("query took 12ms");

const prod = nc.createLogger({ format: "json", fields: { service: "billing" } });
prod.error("charge failed", { orderId: 42 }, error);

Types

Import any of them in TypeScript with import type { LogFileOptions } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").LogFileOptions.

LogFileOptions

Writing logs to a file.

PropertyTypeDescription
pathstringThe file to append to. Folders are created, colors removed.
maxSizeoptionalstring | numberRotate past this size, like "10MB".
maxFilesoptionalnumberHow many rotated files to keep. Defaults to 5.

Logger

A logger from createLogger(). Every method returns the logger, so calls chain.

PropertyTypeDescription
log(...args: unknown[]) => LoggerA plain message, no badge. Supports markup.
trace(...args: unknown[]) => LoggerVery detailed diagnostics, hidden unless the level is trace.
debug(...args: unknown[]) => LoggerDiagnostics, hidden unless the level is debug or lower.
info(...args: unknown[]) => LoggerAn ℹ INFO message.
success(...args: unknown[]) => LoggerA ✔ OK message.
warn(...args: unknown[]) => LoggerA ⚠ WARN message, on stderr.
error(...args: unknown[]) => LoggerAn ✖ ERROR message, on stderr. Errors show their stack and cause.
fatal(...args: unknown[]) => LoggerAn ✖ FATAL message, on stderr.
group(label?: string) => LoggerPrints a label and indents what follows. Groups nest.
groupEnd() => LoggerCloses the current group.
timeStart(label?: string) => LoggerStarts a named timer.
timeEnd(label?: string) => LoggerPrints how long since timeStart(label).
table(rows: Record<string, unknown>[] | unknown[][], options?: TableOptions) => LoggerPrints rows as a table.
box(text: string, options?: BoxOptions) => LoggerPrints text in a box.
divider(title?: string) => LoggerPrints a horizontal line.
child(scope: string, options?: LoggerOptions) => LoggerA logger with the same settings and a nested scope. Its fields are added to the parent's.
setLevel(level: LogLevel) => LoggerChanges the minimum level.
getLevel() => LogLevelThe current minimum level.
isLevelEnabled(level: LogLevel) => booleanWould this level be printed? Skip expensive debug output when it wouldn't.
configure(options: LoggerOptions) => LoggerChanges several settings at once.

LoggerOptions

Options for createLogger() and configure().

PropertyTypeDescription
leveloptionalLogLevelHide messages below this level. Defaults to LOG_LEVEL, else "info".
scopeoptionalstringShown before each message, like [db]. Child loggers extend it (db:pool).
timestampoptionalstring | booleantrue shows [HH:mm:ss], false hides it, a string is a time.format pattern. Defaults to true.
formatoptional"pretty" | "json""json" writes one object per line, for log collectors. Defaults to LOG_FORMAT, else "pretty".
delimiteroptional{ open?: string; close?: string; }Markup delimiters. Defaults to <% and %>.
colorsoptionalbooleanForce colors on or off. By default, it depends on the terminal.
stdoutoptionalLogStreamWhere trace to info go. Defaults to process.stdout.
stderroptionalLogStreamWhere warn, error and fatal go. Defaults to process.stderr.
fileoptionalstring | LogFileOptionsAlso write every message to a file.
fieldsoptionalRecord<string, unknown>Added to every JSON record, like a service name.

LogLevel

Log levels, from the most verbose to the most severe. silent hides everything.

type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal" | "silent"

LogStream

Where logs go: process.stdout, a file stream, or anything with a write(text) method.

PropertyTypeDescription
write(text: string) => unknown
node-comfort v2.0.0View the source