winston

0
год назад
год назад
README.md

winston

A logger for just about everything.

Version npm npm Downloads build status coverage status

NPM

winston@3

See the Upgrade Guide for more information. Bug reports and PRs welcome!

Looking for
winston@2.x
documentation?

Please note that the documentation below is for

winston@3
. Read the
winston@2.x
documentation
.

Motivation

winston
is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each
winston
logger can have multiple transports (see: Transports) configured at different levels (see: Logging levels). For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.

winston
aims to decouple parts of the logging process to make it more flexible and extensible. Attention is given to supporting flexibility in log formatting (see: Formats) & levels (see: Using custom logging levels), and ensuring those APIs decoupled from the implementation of transport logging (i.e. how the logs are stored / indexed, see: Adding Custom Transports) to the API that they exposed to the programmer.

Quick Start

TL;DR? Check out the quick start example in

./examples/
. There are a number of other examples in
./examples/*.js
. Don't see an example you think should be there? Submit a pull request to add it!

Usage

The recommended way to use

winston
is to create your own logger. The simplest way to do this is using
winston.createLogger
:

You may also log directly via the default logger exposed by

require('winston')
, but this merely intended to be a convenient shared logger to use throughout your application if you so choose. Note that the default logger doesn't have any transports by default. You need add transports by yourself, and leaving the default logger without any transports may produce a high memory usage issue.

Table of contents

Logging

Logging levels in

winston
conform to the severity ordering specified by RFC5424: severity of all levels is assumed to be numerically ascending from most important to least important.

Creating your own Logger

You get started by creating a logger using

winston.createLogger
:

A logger accepts the following parameters:

NameDefaultDescription
level
'info'
Log only if
info.level
is less than or equal to this level
levels
winston.config.npm.levels
Levels (and colors) representing log priorities
format
winston.format.json
Formatting for
info
messages (see: Formats)
transports
[]
(No transports)
Set of logging targets for
info
messages
exitOnError
true
If false, handled exceptions will not cause
process.exit
silent
false
If true, all logs are suppressed

The levels provided to

createLogger
will be defined as convenience methods on the
logger
returned.

You can add or remove transports from the

logger
once it has been provided to you from
winston.createLogger
:

You can also wholesale reconfigure a

winston.Logger
instance using the
configure
method:

Creating child loggers

You can create child loggers from existing loggers to pass metadata overrides:

.child
is likely to be bugged if you're also extending the
Logger
class, due to some implementation details that make
this
keyword to point to unexpected things. Use with caution.

Streams,
objectMode
, and
info
objects

In

winston
, both
Logger
and
Transport
instances are treated as
objectMode
streams that accept an
info
object.

The

info
parameter provided to a given format represents a single log message. The object itself is mutable. Every
info
must have at least the
level
and
message
properties:

Properties besides level and message are considered as "

meta
". i.e.:

Several of the formats in

logform
itself add additional properties:

PropertyFormat added byDescription
splat
splat()
String interpolation splat for
%d %s
-style messages.
timestamp
timestamp()
timestamp the message was received.
label
label()
Custom label associated with each message.
ms
ms()
Number of milliseconds since the previous log message.

As a consumer you may add whatever properties you wish – internal state is maintained by

Symbol
properties:

  • Symbol.for('level')
    (READ-ONLY): equal to
    level
    property. Is treated as immutable by all code.
  • Symbol.for('message'):
    complete string message set by "finalizing formats":
    • json
    • logstash
    • printf
    • prettyPrint
    • simple
  • Symbol.for('splat')
    : additional string interpolation arguments. Used exclusively by
    splat()
    format.

These Symbols are stored in another package:

triple-beam
so that all consumers of
logform
can have the same Symbol reference. i.e.:

NOTE: any

{ message }
property in a
meta
object provided will automatically be concatenated to any
msg
already provided: For example the below will concatenate 'world' onto 'hello':

Formats

Formats in

winston
can be accessed from
winston.format
. They are implemented in
logform
, a separate module from
winston
. This allows flexibility when writing your own transports in case you wish to include a default format with your transport.

In modern versions of

node
template strings are very performant and are the recommended way for doing most end-user formatting. If you want to bespoke format your logs,
winston.format.printf
is for you:

To see what built-in formats are available and learn more about creating your own custom logging formats, see

.

Combining formats

Any number of formats may be combined into a single format using

format.combine
. Since
format.combine
takes no
opts
, as a convenience it returns pre-created instance of the combined format.

String interpolation

The

log
method provides the string interpolation using util.format. It must be enabled using
format.splat()
.

Below is an example that defines a format with string interpolation of messages using

format.splat
and then serializes the entire
info
message using
format.simple
.

Filtering
info
Objects

If you wish to filter out a given

info
Object completely when logging then simply return a falsey value.

Use of

format.combine
will respect any falsey values return and stop evaluation of later formats in the series. For example:

Creating custom formats

Formats are prototypal objects (i.e. class instances) that define a single method:

transform(info, opts)
and return the mutated
info
:

  • info
    : an object representing the log message.
  • opts
    : setting specific to the current instance of the format.

They are expected to return one of two things:

  • An
    info
    Object
    representing the modified
    info
    argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider
    info
    mutable, but [immutablejs] is being considered for future releases.
  • A falsey value indicating that the
    info
    argument should be ignored by the caller. (See: Filtering
    info
    Objects
    ) below.

winston.format
is designed to be as simple as possible. To define a new format, simply pass it a
transform(info, opts)
function to get a new
Format
.

The named

Format
returned can be used to create as many copies of the given
Format
as desired:

Logging Levels

Logging levels in

winston
conform to the severity ordering specified by RFC5424: severity of all levels is assumed to be numerically ascending from most important to least important.

Each

level
is given a specific integer priority. The higher the priority the more important the message is considered to be, and the lower the corresponding integer priority. For example, as specified exactly in RFC5424 the
syslog
levels are prioritized from 0 to 7 (highest to lowest).

Similarly,

npm
logging levels are prioritized from 0 to 6 (highest to lowest):

If you do not explicitly define the levels that

winston
should use, the
npm
levels above will be used.

Using Logging Levels

Setting the level for your logging message can be accomplished in one of two ways. You can pass a string representing the logging level to the log() method or use the level specified methods defined on every winston Logger.

winston
allows you to define a
level
property on each transport which specifies the maximum level of messages that a transport should log. For example, using the
syslog
levels you could log only
error
messages to the console and everything
info
and below to a file (which includes
error
messages):

You may also dynamically change the log level of a transport:

winston
supports customizable logging levels, defaulting to npm style logging levels. Levels must be specified at the time of creating your logger.

Using Custom Logging Levels

In addition to the predefined

npm
,
syslog
, and
cli
levels available in
winston
, you can also choose to define your own:

Although there is slight repetition in this data structure, it enables simple encapsulation if you do not want to have colors. If you do wish to have colors, in addition to passing the levels to the Logger itself, you must make winston aware of them:

This enables loggers using the

colorize
formatter to appropriately color and style the output of custom levels.

Additionally, you can also change background color and font style. For example,

Possible options are below.

  • Font styles:

    bold
    ,
    dim
    ,
    italic
    ,
    underline
    ,
    inverse
    ,
    hidden
    ,
    strikethrough
    .

  • Font foreground colors:

    black
    ,
    red
    ,
    green
    ,
    yellow
    ,
    blue
    ,
    magenta
    ,
    cyan
    ,
    white
    ,
    gray
    ,
    grey
    .

  • Background colors:

    blackBG
    ,
    redBG
    ,
    greenBG
    ,
    yellowBG
    ,
    blueBG
    magentaBG
    ,
    cyanBG
    ,
    whiteBG

Colorizing Standard logging levels

To colorize the standard logging level add

where

winston.format.simple()
is whatever other formatter you want to use. The
colorize
formatter must come before any formatters adding text you wish to color.

Colorizing full log line when json formatting logs

To colorize the full log line with the json formatter you can apply the following

Transports

There are several core transports included in

winston
, which leverage the built-in networking and file I/O offered by Node.js core. In addition, there are additional transports written by members of the community.

Multiple transports of the same type

It is possible to use multiple transports of the same type e.g.

winston.transports.File
when you construct the transport.

If you later want to remove one of these transports you can do so by using the transport itself. e.g.:

Adding Custom Transports

Adding a custom transport is easy. All you need to do is accept any options you need, implement a log() method, and consume it with

winston
.

Common Transport options

As every transport inherits from winston-transport, it's possible to set a custom format and a custom log level on each transport separately:

Exceptions

Handling Uncaught Exceptions with winston

With

winston
, it is possible to catch and log
uncaughtException
events from your process. With your own logger instance you can enable this behavior when it's created or later on in your applications lifecycle:

If you want to use this feature with the default logger, simply call

.exceptions.handle()
with a transport instance.

To Exit or Not to Exit

By default, winston will exit after logging an uncaughtException. If this is not the behavior you want, set

exitOnError = false

When working with custom logger instances, you can pass in separate transports to the

exceptionHandlers
property or set
handleExceptions
on any transport.

Example 1
Example 2

The

exitOnError
option can also be a function to prevent exit on only certain types of errors:

Rejections

Handling Uncaught Promise Rejections with winston

With

winston
, it is possible to catch and log
unhandledRejection
events from your process. With your own logger instance you can enable this behavior when it's created or later on in your applications lifecycle:

If you want to use this feature with the default logger, simply call

.rejections.handle()
with a transport instance.

Profiling

In addition to logging messages and metadata,

winston
also has a simple profiling mechanism implemented for any logger:

Also you can start a timer and keep a reference that you can call

.done()
on:

All profile messages are set to 'info' level by default, and both message and metadata are optional. For individual profile messages, you can override the default log level by supplying a metadata object with a

level
property:

Querying Logs

winston
supports querying of logs with Loggly-like options. See Loggly Search API. Specifically:
File
,
Couchdb
,
Redis
,
Loggly
,
Nssocket
, and
Http
.

Streaming Logs

Streaming allows you to stream your logs back from your chosen transport.

Further Reading

Using the Default Logger

The default logger is accessible through the

winston
module directly. Any method that you could call on an instance of a logger is available on the default logger:

By default, no transports are set on the default logger. You must add or remove transports via the

add()
and
remove()
methods:

Or do it with one call to configure():

For more documentation about working with each individual transport supported by

winston
see the
winston
Transports
document.

Awaiting logs to be written in
winston

Often it is useful to wait for your logs to be written before exiting the process. Each instance of

winston.Logger
is also a [Node.js stream]. A
finish
event will be raised when all logs have flushed to all transports after the stream has been ended.

It is also worth mentioning that the logger also emits an 'error' event if an error occurs within the logger itself which you should handle or suppress if you don't want unhandled exceptions:

Working with multiple Loggers in winston

Often in larger, more complex, applications it is necessary to have multiple logger instances with different settings. Each logger is responsible for a different feature area (or category). This is exposed in

winston
in two ways: through
winston.loggers
and instances of
winston.Container
. In fact,
winston.loggers
is just a predefined instance of
winston.Container
:

Now that your loggers are setup, you can require winston in any file in your application and access these pre-configured loggers:

If you prefer to manage the

Container
yourself, you can simply instantiate one:

Routing Console transport messages to the console instead of stdout and stderr

By default the

winston.transports.Console
transport sends messages to
stdout
and
stderr
. This is fine in most situations; however, there are some cases where this isn't desirable, including:

  • Debugging using VSCode and attaching to, rather than launching, a Node.js process
  • Writing JSON format messages in AWS Lambda
  • Logging during Jest tests with the
    --silent
    option

To make the transport log use

console.log()
,
console.warn()
and
console.error()
instead, set the
forceConsole
option to
true
:

Installation

Run Tests

All of the winston tests are written with

,
nyc
, and
assume
. They can be run with
npm
.

Author: Charlie Robbins

Contributors: Jarrett Cruger, David Hyde, Chris Alderson