Logging
Lightweight level based logging system.
Installation
- Yarn
- pnpm
- npm
yarn add @boost/log
pnpm add @boost/log
npm install @boost/log
Environment variables
BOOSTJS_LOG_DEFAULT_LEVEL
(LogLevel
) - The default log level to use when calling the logger function stand alone (the usage examples below). Defaults to the lowest level,log
.BOOSTJS_LOG_MAX_LEVEL
(LogLevel
) - The maximum level, based on priority, to write to a stream. All levels higher than the maximum will be ignored. Defaults to allowing all levels.
Logging
Logging is based around the concept of a "logger", which provides a set of functions of severity
levels to log with. Logs are written to one or many provided transports -- or console
if not
defined. To begin, instantiate a logger with createLogger
, which
returns a function that can be used for standard level logging.
import { createLogger } from '@boost/log';
const log = createLogger({ name: 'boost' });
log('Something has happened…');
Each logging function requires a message string as the 1st argument, and an optional rest of
arguments to interpolate into the message using
util.format()
.
log('Name: %s %s', user.first_name, user.last_name);
log('Object: %O', data);
If you would prefer to interact with a class instance, you may use the
Logger
class. The major difference between the class and the function, is
that the class only has 1 logging method, Logger#log()
.
import { Logger } from '@boost/log';
const logger = new Logger({ name: 'boost' });
logger.log({
level: 'info',
message: 'Something else has happened…',
});
Options
When creating a logger, a LoggerOptions
object can be passed.
The options cannot be customized after the fact.
import chalk from 'chalk';
import { createLogger, StreamTransport } from '@boost/log';
const log = createLogger({
name: 'boost',
labels: {
error: chalk.bgRed.black.bold(' FAIL '),
},
transports: [new StreamTransport({ levels: ['error'], stream: process.stderr })],
});
Log levels
There are 5 distinct logging levels outside the standard level, each represented as a unique
function on the logger instance. The levels in order of priority are trace
, debug
, info
,
warn
, and error
. Each function requires a message as the 1st argument, and an optional rest of
arguments to interpolate into the message.
log.trace('Code path hit?');
log.debug('What is going on here?');
log.info('Systems are stable');
log.warn('Something is definitely going on…');
log.error('Systems are down! %s', error.message);
Silencing output
By default, all logged messages are immediately written to the configured transports. To silence
output and disable writes, call the logger.disable()
function, and to re-enable, call logger.enable()
.
log.disable();
// Will not write!
log.debug('Something is broken!');
Messages that are logged while silenced are lost and are not buffered.
Formats
All logs are represented as an object, known as a LogItem
. These
items contain metadata about the environment, the logger, and the current log message.
Before an item is written to a transport, it must be formatted from an object into a string. This
can be done on a per transport basis using the
format
option, like so.
import { ConsoleTransport, formats } from '@boost/log';
const transport = new ConsoleTransport({
format: (item) => `${item.level} ${item.message}`,
// Or a pre-built format
format: formats.json,
});
Boost provides formats by default, all of which are pre-configured into each built-in transport. Feel free to use the built-in formats, or customize your own!
Metadata
Sometimes additional metadata may be required that is not found within the pre-defined log item fields. Metadata can be defined on the logger using an object, which is then passed to all log items.
const log = createLogger({
name: 'boost',
metadata: {
locale: 'en',
region: 'eu',
},
});
It can also be defined per log by passing an object as the 1st argument. Metadata defined at this level will override the logger metadata.
log({ locale: 'de' }, "What's going on?");
Fields
name
,host
, andpid
are reserved names and cannot be used.
Transport types
There are multiple types of transports that can be used within a logger, all of which support a
TransportOptions
object. Some transports support additional
options, so please refer to their types.
ConsoleTransport
The ConsoleTransport
logs messages to the native console
and
its corresponding level. This is the default transport when no transports are defined.
import { ConsoleTransport } from '@boost/log';
const transport = new ConsoleTransport();
StreamTransport
The StreamTransport
logs messages to any writeable stream or an
object that defines a write()
method. Additional
StreamTransportOptions
options may be provided.
import { StreamTransport } from '@boost/log';
const transport = new StreamTransport({
levels: ['error', 'warn'],
stream: process.stderr,
});
FileTransport
The FileTransport
appends and logs messages to a file at the
defined path. Will automatically rotate files when a max file size is met. Additional
FileTransportOptions
options may be provided.
import { FileTransport } from '@boost/log';
const transport = new FileTransport({
levels: ['error'],
path: '/var/log/error.log',
});
RotatingFileTransport
The RotatingFileTransport
is like
FileTransport
, but also rotates files based on timestamps and a
chosen periodic interval. Additional
RotatingFileTransportOptions
options may be
provided.
import { RotatingFileTransport } from '@boost/log';
const transport = new RotatingFileTransport({
levels: ['error'],
path: '/var/log/error.log',
rotation: 'daily',
});
Test utilities
A handful of Vitest utilities are available in the @boost/log/test
module.
View the API for a full list.