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 towinston@3.0.0PLEASE open an issue so we can improve this guide!
winston.Loggerhas been replaced withwinston.createLogger.winston.setLevelshas been removed. Levels are frozen at the time of Logger creation.- Setting the level on the default
winstonlogger no longer sets the level on the transports associated with the defaultwinstonlogger. - The default logger exposed by
require('winston')no longer has defaultConsoletransports, and leaving it without transports may cause a high memory usage issue.
winston.transports.Memorywas removed. Use any Node.jsstream.Writeablewith a largehighWaterMarkinstance instead.- When writing transports use
winston-transportinstead 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.stderrLevelsoption now defaults to[].debugStdoutoption has been removed.
winston.Containerinstances no longer have defaultConsoletransports. Failing to add any transports may cause a high memory usage issue.winston.Container.prototype.addno 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.logand 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.addno 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.Loggerwill no longer do automatic splat interpolation by default. Be sure to useformat.splat()to enable this functionality.winston.Loggerwill no longer respond with an error when logging with no transports.winston.Loggerwill no longer respond with an error if the same transports are added twice.Logger.prototype.streamoptions.transportis removed. Use the transport instance on the logger directly.
Logger.prototype.queryoptions.transportis removed. Use the transport instance on the logger directly.
Logger.paddingswas removed.
winston.exceptionhas been removed. Use:
const exception = winston.ExceptionHandler();humanReadableUnhandledExceptionis 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 = falseon all transports.
- Call close on any explicit
winston.hashwas removed.winston.common.padwas removed.winston.common.serializedwas removed (usewinston-compat).winston.common.logwas removed (usewinston-compat).winston.paddingswas 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.depthis an option provided toformat.prettyPrint().
colorize: Useformat.colorize().timestamp: Useformat.timestamp().logstash: Useformat.logstash().align: Useformat.align().showLevel: Use a custom format.
In winston@3.x.x 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
winston@2.x 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
winston@2.x 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
winston@2.x.
As of winston@3.0.0 the project has been broken out into a few modules:
- winston-transport:
Transportstream implementation & legacyTransportwrapper. - logform: All formats exports through
winston.format. LEVELandMESSAGEsymbols 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()]
});