Upgrading to [email protected]
This document represents a living guide on upgrading to
winston@3
. Much attention has gone into the details, but if you are having trouble upgrading to[email protected]
PLEASE open an issue so we can improve this guide!
winston.Logger
has been replaced withwinston.createLogger
.winston.setLevels
has been removed. Levels are frozen at the time of Logger creation.- Setting the level on the default
winston
logger no longer sets the level on the transports associated with the defaultwinston
logger. - The default logger exposed by
require('winston')
no longer has defaultConsole
transports, and leaving it without transports may cause a high memory usage issue.
winston.transports.Memory
was removed. Use any Node.jsstream.Writeable
with a largehighWaterMark
instance instead.- When writing transports use
winston-transport
instead ofwinston.Transport
. - Many formatting options that were previously configurable on transports
(e.g.
json
,raw
,colorize
,prettyPrint
,timestamp
,logstash
,align
) should now be set by adding the appropriate formatter instead. (See: "Removedwinston.transports.{File,Console,Http}
formatting options" below) - In
winston.transports.Console
, output for all log levels are now sent to stdout by default.stderrLevels
option now defaults to[]
.debugStdout
option has been removed.
winston.Container
instances no longer have defaultConsole
transports. Failing to add any transports may cause a high memory usage issue.winston.Container.prototype.add
no longer does crazy options parsing. Implementation inspired by segmentio/winston-logger
-
Do not use
new winston.Logger(opts)
– it has been removed for improved performance. Usewinston.createLogger(opts)
instead. -
winston.Logger.log
and level-specific methods (.info
,.error
, etc) no longer accepts a callback. The vast majority of use cases for this feature was folks awaiting all logging to complete, not just a single logging message. To accomplish this:
logger.log('info', 'some message');
logger.on('finish', () => process.exit());
logger.end();
winston.Logger.add
no longer accepts prototypes / classes. Pass an instance of our transport instead.
// DON'T DO THIS. It will no longer work
logger.add(winston.transports.Console);
// Do this instead.
logger.add(new winston.transports.Console());
winston.Logger
will no longer do automatic splat interpolation by default. Be sure to useformat.splat()
to enable this functionality.winston.Logger
will no longer respond with an error when logging with no transports.winston.Logger
will no longer respond with an error if the same transports are added twice.Logger.prototype.stream
options.transport
is removed. Use the transport instance on the logger directly.
Logger.prototype.query
options.transport
is removed. Use the transport instance on the logger directly.
Logger.paddings
was removed.
winston.exception
has been removed. Use:
const exception = winston.ExceptionHandler();
humanReadableUnhandledException
is now the default exception format..unhandleExceptions()
will no longer modify transports state, merely just add / remove theprocess.on('uncaughtException')
handler.- Call close on any explicit
ExceptionHandlers
. - Set
handleExceptions = false
on all transports.
- Call close on any explicit
winston.hash
was removed.winston.common.pad
was removed.winston.common.serialized
was removed (usewinston-compat
).winston.common.log
was removed (usewinston-compat
).winston.paddings
was removed.
The biggest issue with winston@2
and previous major releases was that any
new formatting options required changes to winston
itself. All formatting is
now handled by formats.
Custom formats can now be created with no changes to winston
core.
We encourage you to consider a custom format before opening an issue.
- The default output format is now
format.json()
. filters
: Use a customformat
. See: Filters and Rewriters below.rewriters
: Use a customformat
. See: Filters and Rewriters below.
stringify
: Use a custom format.formatter
: Use a custom format.json
: Useformat.json()
.raw
: Useformat.json()
.label
: Useformat.label()
.logstash
: Useformat.logstash()
.prettyPrint
: Useformat.prettyPrint()
or a custom format.depth
is an option provided toformat.prettyPrint()
.
colorize
: Useformat.colorize()
.timestamp
: Useformat.timestamp()
.logstash
: Useformat.logstash()
.align
: Useformat.align()
.showLevel
: Use a custom format.
In [email protected]
info
objects are considered mutable. The API combined
formatters and rewriters into a single, new concept: formats.
If you are looking to upgrade your filter
behavior please read on. In
[email protected]
this filter behavior:
const isSecret = /super secret/;
const logger = new winston.Logger(options);
logger.filters.push(function(level, msg, meta) {
return msg.replace(isSecret, 'su*** se****');
});
// Outputs: {"level":"error","message":"Public error to share"}
logger.error('Public error to share');
// Outputs: {"level":"error","message":"This is su*** se**** - hide it."}
logger.error('This is super secret - hide it.');
Can be modeled as a custom format that you combine with other formats:
const { createLogger, format, transports } = require('winston');
// Ignore log messages if the have { private: true }
const isSecret = /super secret/;
const filterSecret = format((info, opts) => {
info.message = info.message.replace(isSecret, 'su*** se****');
return info;
});
const logger = createLogger({
format: format.combine(
filterSecret(),
format.json()
),
transports: [new transports.Console()]
});
// Outputs: {"level":"error","message":"Public error to share"}
logger.log({
level: 'error',
message: 'Public error to share'
});
// Outputs: {"level":"error","message":"This is su*** se**** - hide it."}
logger.log({
level: 'error',
message: 'This is super secret - hide it.'
});
If you are looking to upgrade your rewriter
behavior please read on. In
[email protected]
this rewriter behavior:
const logger = new winston.Logger(options);
logger.rewriters.push(function(level, msg, meta) {
if (meta.creditCard) {
meta.creditCard = maskCardNumbers(meta.creditCard)
}
return meta;
});
logger.info('transaction ok', { creditCard: 123456789012345 });
Can be modeled as a custom format that you combine with other formats:
const maskFormat = winston.format(info => {
// You can CHANGE existing property values
if (info.creditCard) {
info.creditCard = maskCardNumbers(info.creditCard);
}
// You can also ADD NEW properties if you wish
info.hasCreditCard = !!info.creditCard;
return info;
});
const logger = winston.createLogger({
format: winston.format.combine(
maskFormat(),
winston.format.json()
)
});
logger.info('transaction ok', { creditCard: 123456789012345 });
See examples/format-mutate.js for a complete
end-to-end example that covers both filtering and rewriting behavior in
[email protected]
.
As of [email protected]
the project has been broken out into a few modules:
- winston-transport:
Transport
stream implementation & legacyTransport
wrapper. - logform: All formats exports through
winston.format
. LEVEL
andMESSAGE
symbols exposed through triple-beam.- Shared test suite for community transports.
Let's dig in deeper. The example below has been annotated to demonstrate the different packages that compose the example itself:
const { createLogger, transports, format } = require('winston');
const Transport = require('winston-transport');
const logform = require('logform');
const { combine, timestamp, label, printf } = logform.format;
// winston.format is require('logform')
console.log(logform.format === format) // true
const logger = createLogger({
format: combine(
label({ label: 'right meow!' }),
timestamp(),
printf(nfo => {
return `${nfo.timestamp} [${nfo.label}] ${nfo.level}: ${nfo.message}`;
})
),
transports: [new transports.Console()]
});