[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.* APIwinston.Logger has been replaced with winston.createLogger.winston.setLevels has been removed. Levels are frozen at the time of Logger creation.winston logger no longer sets the level on the transports associated with the default winston logger.require('winston') no longer has default Console transports,
and leaving it without transports may cause a high memory usage issue.winston.transports.Memory was removed. Use any Node.js stream.Writeable with a large highWaterMark instance instead.winston-transport instead of
winston.Transport.json, raw, colorize, prettyPrint, timestamp, logstash,
align) should now be set by adding the appropriate formatter instead.
(See: "Removed winston.transports.{File,Console,Http} formatting options"
below)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 and winston.loggerswinston.Container instances no longer have default Console 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-loggerwinston.LoggerDo not use new winston.Logger(opts) – it has been removed for
improved performance. Use winston.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 use format.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 the process.on('uncaughtException') handler.
ExceptionHandlers.handleExceptions = false on all transports.winston.hash was removed.winston.common.pad was removed.winston.common.serialized was removed (use winston-compat).winston.common.log was removed (use winston-compat).winston.paddings was removed.winston.formatThe 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.
winston.Logger formatting options:format.json().filters: Use a custom format. See: Filters and Rewriters below.rewriters: Use a custom format. See: Filters and Rewriters below.winston.transports.{File,Console,Http} formatting optionsstringify: Use a custom format.formatter: Use a custom format.json: Use format.json().raw: Use format.json().label: Use format.label().logstash: Use format.logstash().prettyPrint: Use format.prettyPrint() or a custom format.
depth is an option provided to format.prettyPrint().colorize: Use format.colorize().timestamp: Use format.timestamp().logstash: Use format.logstash().align: Use format.align().showLevel: Use a custom format.filters and rewriters to formats in winston@3In [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].
winston-transport, logform and more...As of [email protected] the project has been broken out into a few modules:
Transport stream implementation & legacy Transport
wrapper.winston.format.LEVEL and MESSAGE symbols exposed through triple-beam.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()]
});