WinstonJS 自定义级别文件

WinstonJS custom level to file

我更改了 Winston.JS 中的默认级别,以删除 2 个级别并添加 1 个自定义级别。我想在一个单独的文件中记录这个新级别。因此该文件将仅包含该级别的日志。

const appRoot = require('app-root-path');
const winston = require('winston');
require('winston-daily-rotate-file');

const levels = {
    levels: {
        product: 0,
        error: 1,
        warn: 2,
        info: 3,
        debug: 4,
        product: 5,
    },
    colors: {
        product: 'magenta',
        error: 'red',
        warning: 'yellow',
        info: 'green',
        debug: 'blue',
    }
}

const logger = winston.createLogger({
    levels: levels.levels,
    format: winston.format.combine(
        winston.format.colorize(),
        winston.format.timestamp({
            format: 'DD-MM-YYYY HH:mm:ss'
        }),
        winston.format.printf(info => `[${info.timestamp}] [${info.level}]: ${info.message}`)
    ),
    transports: [
        new winston.transports.DailyRotateFile({
            filename: `${appRoot}/logs/error-%DATE%.log`,
            level: 'error', 
            datePattern: 'YYYY-MM-DD',
            maxSize: '20m',
            maxFiles: '14d'
        }),
        new winston.transports.DailyRotateFile({
            filename: `${appRoot}/logs/product-%DATE%.log`,
            level: 'product',
            datePattern: 'YYYY-MM-DD',
            maxSize: '20m',
            maxFiles: '14d' 
        })
    ]
})
winston.addColors(levels.colors);

logger.stream = {
    write: (message, encoding) => {
        logger.info(message);
    }
}

在这种情况下,我想将所有 console.product() 日志放在 product-%DATE%.log 文件中。 目前文件已满,但仅包含也在日志中显示的有关来自 express (app.use(morgan("combined", {stream: winston.stream}));) 的信息 在开发中,我还在控制台上添加了一个额外的调试传输:

let env = process.env.NODE_ENV;

if (env !== 'production'){
    logger.add(new winston.transports.Console({
        level: 'debug',
        prettyPrint: function ( object ){
            return JSON.stringify(object);
        }
    }))
}

如何才能只将 console.product() 日志放入 product.log 文件?

我已借助以下代码片段修复了此问题:https://github.com/winstonjs/winston/issues/614#issuecomment-405015322

所以我的整个配置现在看起来像这样:

const appRoot = require('app-root-path');
const winston = require('winston');
const path = require('path')
require('winston-daily-rotate-file');

const levels = {
    levels: {
        product: 1,
        error: 1,
        warn: 3,
        info: 4,
        debug: 5
    },
    colors: {
        product: 'magenta',
        error: 'red',
        warning: 'yellow',
        info: 'green',
        debug: 'blue',
    }
}

let getLabel = function(callingModule){
    //To support files which don't have an module
    if(typeof callingModule == 'string'){
        return callingModule;
    }
    let parts = callingModule.filename.split(path.sep);
    return path.join(parts[parts.length -2], parts.pop());
}

const errorFilter = winston.format( (info, opts) => {
    return info.level == 'error' ? info : false;
})

const productFilter = winston.format( (info, opts) => {
    return info.level == 'product' ? info : false
})

module.exports = function(callingModule){
    const logger = winston.createLogger({
        levels: levels.levels,
        format: winston.format.combine(
            winston.format.colorize(),
            winston.format.timestamp({
                format: 'DD-MM-YYYY HH:mm:ss'
            }),
            winston.format.label({label: getLabel(callingModule)}),
            winston.format.printf(info => `[${info.timestamp}] [${info.level}] [${info.label}]: ${info.message}`)
        ),
        transports: [
            new winston.transports.DailyRotateFile({
                name: "Error logs",
                filename: `${appRoot}/logs/error-%DATE%.log`,
                level: 'error', 
                label: getLabel(callingModule),
                datePattern: 'YYYY-MM-DD',
                maxSize: '20m',
                maxFiles: '14d',
                format: winston.format.combine(
                    errorFilter(),
                    winston.format.colorize(),
                    winston.format.timestamp({
                        format: 'DD-MM-YYYY HH:mm:ss'
                    }),
                    winston.format.label({label: getLabel(callingModule)}),
                    winston.format.printf(info => `[${info.timestamp}] [${info.level}] [${info.label}]: ${info.message}`)
                ),
            }),
            new winston.transports.DailyRotateFile({
                name: "Product logs",
                filename: `${appRoot}/logs/product-%DATE%.log`,
                level: 'product',
                label: getLabel(callingModule),
                datePattern: 'YYYY-MM-DD',
                maxSize: '20m',
                maxFiles: '14d',
                format: winston.format.combine(
                    productFilter(),
                    winston.format.colorize(),
                    winston.format.timestamp({
                        format: 'DD-MM-YYYY HH:mm:ss'
                    }),
                    winston.format.label({label: getLabel(callingModule)}),
                    winston.format.printf(info => `[${info.timestamp}] [${info.level}] [${info.label}]: ${info.message}`)
                ),
            })
        ]
    })
    winston.addColors(levels.colors);

    let env = process.env.NODE_ENV;

    if (env !== 'production'){
        logger.add(new winston.transports.Console({
            name: "Debug logs",
            level: 'debug',
            label: getLabel(callingModule),
            prettyPrint: function ( object ){
                return JSON.stringify(object);
            }
        }))
    }
    else if (env !== 'development') {
        logger.add(winston.transports.DailyRotateFile({
            name: "Combined logs",
            filename: `${appRoot}/logs/combined-%DATE%.log`,
            level: 'error', 
            datePattern: 'YYYY-MM-DD-HH',
            maxSize: '20m',
            maxFiles: '14d'
        }))
    }

    logger.stream = {
        write: (message, encoding) => {
            logger.info(message);
        }
    }

    return logger;
}

我还注意到我以优先级 1 和 5 两次声明了产品级别。 在不同的传输上,我添加了一个过滤器,它基于我在 Github 上找到的代码。它会将打印的日志过滤到仅设置的级别。

为了在日志中显示调用文件的文件名,我添加了 callingModule

现在我可以使用

请求控制台
const console = require(path.join(__dirname, 'winston.config'))(module);

来电

console.info('NODE_ENV is undefined or its value was not understood. Default to development mode. ');

在日志中将显示为 [28-08-2019 11:39:51] [info] [config\env.config.js]: NODE_ENV is undefined or its value was not understood. Default to development mode.