This document is a work in progress. Having trouble upgrading to
winston@3.0.0? 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.
winston.transports.Memorywas removed. Use any Node.jsstream.Writeablewith a largehighWaterMarkinstance instead.- When writing transports use
winston-transportinstead ofwinston.Transport
winston.Containerinstances no longer have defaultConsoletransportswinston.Container.prototype.addno longer does crazy options parsing. Implementation inspired by segmentio/winston-logger
winston.Logger.addno longer accepts prototypes / classes. Pass an instance of our transport instead.
Don't do this
// 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 respond with an error when logging with no transportswinston.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.
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).
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
formats.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: Useformats.json().raw: Useformats.json().prettyPrint: Useformats.prettyPrint()or a custom format.colorize: Useformats.colorize().timestamp: Useformats.timestamp().logstash: Useformats.logstash().align: Useformats.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.formats.combine(
maskFormat(),
winston.formats.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()]
});