Signale
Highly configurable logging library
Install / Use
/learn @klaudiosinani/SignaleREADME
Description
Hackable and configurable to the core, signale can be used for logging purposes, status reporting, as well as for handling the output rendering process of other node modules and applications.
Read this document in: Albanian - Shqip, 简体中文 - Simplified Chinese, German - Deutsch.
You can now support the development process through GitHub Sponsors.
Visit the contributing guidelines to learn more on how to translate this document into more languages.
Highlights
- 19 out-of-the-box loggers
- Hackable to the core
- Clean and beautiful output
- Integrated timers
- Custom pluggable loggers
- TypeScript support
- Interactive and regular modes
- Secrets & sensitive information filtering
- Filename, date and timestamp support
- Scoped loggers and timers
- Scaled logging levels mechanism
- String interpolation support
- Multiple configurable writable streams
- Simple and minimal syntax
- Globally configurable through
package.json - Overridable configuration per file and logger
Contents
- Description
- Highlights
- Install
- Usage
- Configuration
- API
- Development
- Related
- Who's Using It?
- Team
- Sponsors
- License
Install
Yarn
yarn add signale
NPM
npm install signale
Usage
Default Loggers
Import signale and start using any of the default loggers.
<details> <summary>View all of the available loggers.</summary> <br/>awaitcompleteerrordebugfatalfavinfonotepausependingstarstartsuccesswaitwarnwatchlog
const signale = require('signale');
signale.success('Operation successful');
signale.debug('Hello', 'from', 'L59');
signale.pending('Write release notes for %s', '1.2.0');
signale.fatal(new Error('Unable to acquire lock'));
signale.watch('Recursively watching build directory...');
signale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});
<div align="center">
<img alt="Default Loggers" src="media/default-loggers.png" width="65%">
</div>
Custom Loggers
To create a custom logger define an options object yielding a types field with the logger data and pass it as argument to a new signale instance.
const {Signale} = require('signale');
const options = {
disabled: false,
interactive: false,
logLevel: 'info',
scope: 'custom',
secrets: [],
stream: process.stdout,
types: {
remind: {
badge: '**',
color: 'yellow',
label: 'reminder',
logLevel: 'info'
},
santa: {
badge: '🎅',
color: 'red',
label: 'santa',
logLevel: 'info'
}
}
};
const custom = new Signale(options);
custom.remind('Improve documentation.');
custom.santa('Hoho! You have an unused variable on L45.');
<div align="center">
<img alt="Custom Loggers" src="media/custom-loggers.png" width="70%">
</div>
Here is an example where we override the default error and success loggers.
const {Signale} = require('signale');
const options = {
types: {
error: {
badge: '!!',
label: 'fatal error'
},
success: {
badge: '++',
label: 'huge success'
}
}
};
const signale = new Signale();
signale.error('Default Error Log');
signale.success('Default Success Log');
const custom = new Signale(options);
custom.error('Custom Error Log');
custom.success('Custom Success Log');
<div align="center">
<img alt="Default Loggers" src="media/override-defaults.png" width="65%">
</div>
The options object can hold any of the following attributes: disabled, interactive, logLevel, secrets, stream, scope and types.
disabled
- Type:
Boolean - Default:
false
Disables the logging functionality of all loggers belonging to the created instance.
interactive
- Type:
Boolean - Default:
false
Switches all loggers belonging to the created instance into the interactive mode.
logLevel
- Type:
String - Default:
'info'
Sets the general logging level of the created instance. Can be one of the following:
'info'- Displays all messages from all loggers.'timer'- Displays messages only from thetime,timeEnd,debug,warn,error&fatalloggers.'debug'- Displays messages only from thedebug,warn,error&fatalloggers.'warn'- Displays messages only from thewarn,error&fatalloggers.'error'- Displays messages only from theerror&fatalloggers.
secrets
- Type:
(String|Number)[] - Default:
[]
An array holding secrets/sensitive-information to be removed from the body and metadata of to-be-logged messages and replaced with the default '[secure]' string.
stream
- Type:
stream.Writable|stream.Writable[] - Default:
process.stdout
Destination to which the data is written, can be a single valid Writable stream or an array holding multiple valid Writable streams.
scope
- Type:
String|String[]
Name of the scope the logger is reporting from.
types
- Type:
Object
Holds the configuration of the custom and default loggers.
Additionally, the configuration object of each custom/default logger type, defined in the types option, can hold any of the following attributes: badge, label, color, logLevel & stream.
badge
- Type:
String
The icon corresponding to the logger.
label
- Type:
String
The label used to identify the type of the logger.
color
- Type:
String
The color of the label, can be any of the foreground colors supported by chalk.
logLevel
- Type:
String - Default:
'info'
The log level corresponding to the logger. Messages originating from the logger are displayed only if the log level is greater or equal to the above described general logging level logLevel of the Signale instance.
stream
- Type:
stream.Writable|stream.Writable[] - Default:
process.stdout
Destination to which the data is written, can be a single valid Writable stream or an array holding multiple valid Writable streams.
Scoped Loggers
To create a scoped logger from scratch, define the scope field inside the options object and pass it as argument to a new signale instance.
const {Signale} = require('signale');
const options = {
scope: 'global scope'
};
const global = new Signale(options);
global.success('Successful Operation');
<div align="center">
<img alt="Scope Vanilla" src="media/scope-vanilla.png" width="65%">
</div>
To create a scoped logger based on an already existing one, use the scope() function, which will return a new signale instance, inheriting all custom loggers, timers, secrets, streams, configuration, log level, interactive mode & disabled statuses from the initial one.
const signale = require('signale');
const global = signale.scope('global scope');
global.success('Hello from the global scope');
function foo() {
const outer = global.scope('outer', 'scope');
outer.success('Hello from the outer scope');
setTimeout(() => {
const inner = outer.scope('inner', 'scope');
inner.success('Hello from the inner scope');
}, 500);
}
foo();
<div align="center">
<img alt="Scope Existing" src="media/scope-existing.png" width="65%">
</div>
Interactive Loggers
To initialize an interactive logger, create a new signale instance with the interactive attribute set to true. While into the interactive mode, previously logged messages originating from an interactive logger, will be overridden only by new ones originating from the same or a different interactive logger. Note that regular messages originating from regular loggers are not overridden by the interactive ones.
const {Signale} = require('signale');
const interactive = new Signale({interactive: true, scope: 'interactive'});
interactive.await('[%d/4] - Process A', 1);
setTimeout(() => {
interactive.success('[%d/4] - Process A', 2);
setTimeout(() => {
interactive.await('[%d/4] - Process B', 3);
setTimeout(() => {
interactive.error('[%d/4] - Process B', 4);
setTimeout(() => {}, 1000);
}, 1000);
}, 1000);
}, 1000);
<div align="center">
<img alt="Interactive Mode" src="media/interactive-mode.gif" width="65%">
</div>
Writable Streams
By default, all signale instances log their messages to the process.stdout stream. This can be modified, to match your own preference, through the stream property, where you can define a single or multiple valid Writable streams,
