【问题标题】:Outputting Logs inside JSON Object with Winston in Node.js在 Node.js 中使用 Winston 在 JSON 对象中输出日志
【发布时间】:2019-05-14 21:24:55
【问题描述】:

所以我使用winston.js 登录到文件。我已将记录器设置为使用 Winston 默认 JSON 格式输出 JSON。

这是我的记录器配置。

logger.util.js:

'use strict';

const winston = require('winston');
const moment = require('moment');

const logger = winston.createLogger({
    format: winston.format.json(),
    transports: [
        new winston.transports.File({
  filename: './logs/' + moment(moment.now()).format('DD-MM-YYYY') + '-API.json',
    handleExceptions: true
  })
 ],
});

module.exports = logger;

当像这样记录事件时:

logger.log({
  'level': 'info',
  'timestamp': moment.now(),
  'account_id': res.account_id || null,
  'action': JSON.stringify(payload),
  'request_id':  res.request_id,
  'status': success.status.code,
  'route' : res.method +  ' ' + res.route,
  'bytes': res.socket.bytesRead || null,
  'elapsed': res.elapsed || null,
});

我在日志文件中得到以下输出

输出:

{
   "level": "error",
   "timestamp": 1544708669700,
   "account_id": 7,
   "action": "SequelizeDatabaseError: column \"alert\" does not exist",
   "request_id": "27cc338b-3980-4818-a9e7-83380b1b2c3a",
   "status": 500,
   "route": "POST /post/new",
   "bytes": 714,
   "elapsed": 35
}
{
   "level": "info",
   "timestamp": 1544709322038,
   "action": "{\"device\":{\"id\":57},\"removed\":55}",
   "status": 200,
   "route": "undefined undefined",
   "bytes": 517,
   "elapsed": null
}

我希望日志像这样输出到我的文件中。因此可以在以后搜索数据。

期望的输出:

[
  {
     "level": "error",
     "timestamp": 1544708669700,
     "account_id": 7,
     "action": "SequelizeDatabaseError: column \"alert\" does not exist",
     "request_id": "27cc338b-3980-4818-a9e7-83380b1b2c3a",
     "status": 500,
     "route": "POST /post/new",
     "bytes": 714,
     "elapsed": 35
  },
  {
     "level": "info",
     "timestamp": 1544709322038,
     "action": "{\"device\":{\"id\":57},\"removed\":55}",
     "status": 200,
     "route": "undefined undefined",
     "bytes": 517,
     "elapsed": null
  }
]

我知道我可能需要使用 Winston 创建自定义格式,并想知道是否有人可以给我一个示例?经过我的研究,我找不到足够相似的东西来解决问题,而且文档也没有给出类似的例子。

【问题讨论】:

    标签: node.js json logging winston


    【解决方案1】:

    我希望这就是你要找的。​​p>

    通过以下方式创建自定义传输:

    const Transport = require('winston-transport');
    const util = require('util');
    const fs = require('fs');
    
    module.exports = class CustomTransport extends Transport {
        constructor(opts) {
            super(opts);
            this.filename = opts.filename;
            this.setup();
        }
    
        initialize() {
            try {
                fs.writeFileSync(this.filename, [], 'utf8');
            } catch (error) {
                console.log(error);
            }
        }
    
        setup() {
            // This checks if the file exists
            if (fs.existsSync(this.filename)) {
                // The content of the file is checked to know if it is necessary to adapt the array
                try {
                    const data = fs.readFileSync(this.filename, 'utf8');
                    // If the content of the file is not an array, it is set
                    const content = JSON.parse(data);
                    if (!Array.isArray(content)) {
                        this.initialize();
                    }
                } catch (error) {
                    this.initialize();
                    console.log(error);
                }
            }
            // Otherwise create the file with the desired format
            else {
                this.initialize();
            }
        }
    
        readLog() {
            let data = null;
            try {
                data = fs.readFileSync(this.filename, 'utf8');
            } catch (error) {
    
                console.log(error);
            }
            return data;
        }
    
        writeLog(info) {
            const data = this.readLog();
            let arr = [];
            if (data) {
                arr = JSON.parse(data);
            }
            //add data
            arr.push(info);
            //convert it back to json
            const json = JSON.stringify(arr);
            try {
                // Writing the array again
                fs.writeFileSync(this.filename, json, 'utf8');
            } catch (error) {
                console.log(error)
            }
        }
    
        log(info, callback) {
            setImmediate(() => {
                this.emit('logged', info);
            });
            // Perform the writing
            this.writeLog(info);
    
            callback();
        }
    };
    

    然后按照您放置的代码进行自定义传输器的适配:

    'use strict';
    
    const winston = require('winston');
    const CustomTransport = require('./CustomTransport');
    const moment = require('moment');
    
    const logger = winston.createLogger({
        format: winston.format.json(),
        transports: [
            new CustomTransport({
                filename: moment(moment.now()).format('DD-MM-YYYY') + '-API.json',
                handleExceptions: true
            })
        ],
    });
    
    logger.log({
        'level': 'info',
        'timestamp': moment.now(),
        'account_id': res.account_id || null,
        'action': JSON.stringify(payload),
        'request_id': res.request_id,
        'status': success.status.code,
        'route': res.method + ' ' + res.route,
        'bytes': res.socket.bytesRead || null,
        'elapsed': res.elapsed || null,
    });
    

    我尝试了使用虚拟数据的服务,结果如下:

    [
        {
            "level": "info",
            "timestamp": 1544723041103,
            "account_id": 1,
            "action": 6,
            "request_id": 2,
            "status": 3,
            "route": 4,
            "bytes": 5,
            "elapsed": 5
        },
        {
            "level": "info",
            "timestamp": 1544724862768,
            "account_id": 1,
            "action": 6,
            "request_id": 2,
            "status": 3,
            "route": 4,
            "bytes": 5,
            "elapsed": 5
        }
    ]
    

    【讨论】:

    • 非常感谢您。除了有一个问题:它说文件或目录丢失。在打开文件和目录之前,我会在哪里告诉代码创建文件和目录?
    • fs.writeFile(file, data[, options], callback); 不会为文件创建父文件夹,如果要创建该文件夹,如果不存在,则必须在 initialize 中添加此操作CustomTransport 类中的方法。
    • 如何停止文件覆盖自身?目前,它会清除文件,然后写入新日志,因此过去的日志被删除。
    • @MwikalaKangwa 感谢您的评论,将我的回复更新为同步版本,现在一切正常。
    猜你喜欢
    • 2020-09-28
    • 2019-09-29
    • 2019-08-28
    • 2013-03-10
    • 2015-04-15
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    相关资源
    最近更新 更多