Although a custom transport is also a good way of doing this, what I would recommend would be adding custom filters for each level you need.
In the example below I have custom levels where it will save to files in groups
errors
, warn & info
, debug
, all
.
const { format, createLogger, transports, addColors } = require("winston");
const { timestamp, combine, printf, errors, json } = format;
require("winston-daily-rotate-file");
function buildDevLogger() {
const consoleFormat = printf(({ level, message, timestamp, stack }) => {
return `${timestamp} ${level}: ${stack || message}`;
});
const infoAndWarnFilter = format((info, opts) => {
return info.level === "info" || info.level === "warn" ? info : false;
});
const errorFilter = format((info, opts) => {
return info.level === "error" ? info : false;
});
const debugFilter = format((info, opts) => {
return info.level === "debug" ? info : false;
});
const customLevels = {
levels: {
error: 0,
warn: 1,
info: 2,
debug: 3,
all: 4,
},
colors: {
error: "red",
warn: "yellow",
info: "green",
debug: "grey",
all: "white",
},
};
var logger = createLogger({
levels: customLevels.levels,
format: combine(
timestamp({ format: "DD-MM-YYYY HH:mm:ss" }),
errors({ stack: true }),
json(),
consoleFormat
),
exitOnError: false,
transports: [
new transports.Console({
format: combine(format.colorize(), _consoleFormat),
level: "all",
}),
new transports.File({
filename: "./logs/0-error.log",
level: "error",
format: combine(errorFilter(), _format),
}),
new transports.File({
filename: "./logs/warn-info.log",
level: "info",
format: combine(infoAndWarnFilter(), _format),
}),
new transports.DailyRotateFile({
filename: "./logs/%DATE% - debug.log",
datePattern: "DD-MM-YYYY",
zippedArchive: true,
level: "debug",
format: combine(debugFilter(), _format),
}),
new transports.DailyRotateFile({
filename: "./logs/%DATE% - general.log",
datePattern: "DD-MM-YYYY",
zippedArchive: true,
level: "all",
}),
],
});
addColors(customLevels.colors);
return logger;
}
module.exports = buildDevLogger;
This topic came first on my search when I needed and I hope the above could help a bit more.
For the example the infoAndWarnFilter
will read the level of the generated log and if not info
or warn
it will return false. When combined in the format
for the transports
it will filter it
...
const infoAndWarnFilter = format((info, opts) => {
return info.level === "info" || info.level === "warn" ? info : false;
});
...
new transports.File({
filename: "./logs/warn-info.log",
level: "info",
format: combine(infoAndWarnFilter(), _format),
}),
...