zoukankan      html  css  js  c++  java
  • nodejs之日志管理

    开发一个项目时,可以通过控制台输出或者debug来获取到项目的运行信息。当项目上线时,我们就需要通过日志来分析。如同Java的log4j,nodejs中也有相关的log4js。使用过log4j的同学应该对此不会陌生。

    1、日志级别

    log4js共有6种日志级别,分别为:trace、debug、info、warn、error、fatal。权值从小到大,其初始化代码为:

    TRACE: new Level(5000, "TRACE"), 
    DEBUG: new Level(10000, "DEBUG"), 
    INFO: new Level(20000, "INFO"), 
    WARN: new Level(30000, "WARN"), 
    ERROR: new Level(40000, "ERROR"), 
    FATAL: new Level(50000, "FATAL"),

    假如设置默认的日志级别为info,那么权值小于info的日志不会被记录下来,也就是说只有调用log.info(), log.warn(), log.error()或者log.fatal()才会触发记录日志。该部分代码在lib/logger.js中。

    Logger.prototype.log = function() {
      var args = Array.prototype.slice.call(arguments)
      , logLevel = levels.toLevel(args.shift())
      , loggingEvent;
      if (this.isLevelEnabled(logLevel)) {
        loggingEvent = new LoggingEvent(this.category, logLevel, args, this);
        this.emit("log", loggingEvent);
      }
    };

     

    2、集成express

    log4js可以作为express的一个中间件来使用。首先需要引入log4js

    var express = require("express");
    var log4js = require("log4js");
    
    var app = express();

    接着配置log4js

    log4js.configure({
     appenders: [
       { type: 'console' },
       { type: 'file', filename: 'cheese.log', category: 'cheese' }
      ]
    });

    该配置的意思是console是默认的appender,使用cheese这个appender时会将日志记录文件中,日志文件名为cheese.log。

    然后用use连接到中间件,我们默认使用的是cheese这个appender,级别为info。

    app.use(log4js.connectLogger(log4js.getLogger("cheese"), {level: log4js.levels.INFO}));

    其输出与此类似:

    [2014-07-04 20:27:21.205] [INFO] cheese - 127.0.0.1 - - "GET / HTTP/1.1" 200 22896 "" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36"

    ......

    3、再修改一下中间件

    上面的做法是可以的,只是当中间件太多的时候,都写在同一个文件中也许感觉会有些丑陋。所以我倾向于将其分离出来作为单独的一个模块,也就是一个单独的文件。然后对外暴露接口。

    var path = require("path");
    var log4js = require("log4js");
    
    
    /**
     * 日志配置
     */
    exports.configure = function() {
        log4js.configure(path.join(__dirname, "log4js.json"));    
    }
    
    /**
     * 暴露到应用的日志接口,调用该方法前必须确保已经configure过
     * @param name 指定log4js配置文件中的category。依此找到对应的appender。
     *              如果appender没有写上category,则为默认的category。可以有多个
     * @returns {Logger}
     */
    exports.logger = function(name) {
        var dateFileLog = log4js.getLogger(name);
        dateFileLog.setLevel(log4js.levels.INFO);
        return dateFileLog;
    }
    
    /**
     * 用于express中间件,调用该方法前必须确保已经configure过
     * @returns {Function|*}
     */
    exports.useLog = function() {
        return log4js.connectLogger(log4js.getLogger("app"), {level: log4js.levels.INFO});
    } 

    log4js.json文件内容如下

    {
        "appenders": [
            {
                "type": "console"
            },
            {
                "type": "dateFile",
                "filename": "logs/booklist.log",
                "pattern": "-yyyy-MM-dd",
                "alwaysIncludePattern": true
            }
        ]
    }

    配置很简单,配置了两个appender,一个是控制台的,一个是dateFile,意思是每天都产生一个日志文件。注意到我这里并没有配置category,这样的话当没有找到对应的appender时,这两个appender就是默认的appender。有些时候明明感觉配置没有错,但是日志文件并没有产生日志,往往问题就出在这里。

    然后在app.js中我们修改为如下

    var express = require("express");
    // 这个是我们上面自定义的模块
    var log4js = require("./log");
    
    var app = express();
    app.configure();
    
    app.use(log4js.useLog());
    
    ...

     

    4、单进程与多进程

    好了,上面对于单进程是适用的,但是如果你的nodejs应用是多进程的,使用上面的配置你会看到日志的输出有点奇怪,比如:

    感觉有点像是资源抢占了。

    log4js的wiki中有给出multiprocess的配置。但是当时使用的时候也会有问题,当时没有细究。不过社区中有人建立了另外一种方式,我采用了这种。可以参看一下这个issue。下面我们来配置一下。修改我们在上面修改的log模块文件,变为:

    var path = require("path");
    var log4js = require("log4js");
    
    
    /**
     * 多进程的日志配置
     */
    exports.configure = function(mode) {
        if (mode === "master") {
            log4js.configure(path.join(__dirname, "./log4js-master.json"));
        } else {
            // 多进程的配置项
            log4js.configure(path.join(__dirname, "./log4js-worker.json"));
            // 单进程的配置项
    //        log4js.configure(path.join(__dirname, "../config/log4js.json"));
        }
    }
    
    /**
     * 暴露到应用的日志接口,调用该方法前必须确保已经configure过
     * @param name 指定log4js配置文件中的category。依此找到对应的appender。
     *              如果appender没有写上category,则为默认的category。可以有多个
     * @returns {Logger}
     */
    exports.logger = function(name) {
        var dateFileLog = log4js.getLogger(name);
        dateFileLog.setLevel(log4js.levels.INFO);
        return dateFileLog;
    }
    
    /**
     * 用于express中间件,调用该方法前必须确保已经configure过
     * @returns {Function|*}
     */
    exports.useLog = function() {
        return log4js.connectLogger(log4js.getLogger("app"), {level: log4js.levels.INFO});
    }

    主要是修改了configure方法。

    log4js-master.json的内容为:

    {
        "appenders": [{
            "type": "clustered",
            "appenders": [
                {
                    "type": "console"
                },
                {
                    "type": "dateFile",
                    "filename": "logs/booklist.log",
                    "pattern": "-yyyy-MM-dd",
                    "alwaysIncludePattern": true,
                    "pollInterval": 1,
                    "category": "dateFileLog"
                }
            ]
        }]
    }

    log4js-worker.js的内容为:

    {
        "appenders": [{
            "type": "clustered"
        }]
    }

    假设主进程的内容在文件master.js,工作进程在worker.js。master.js中的配置内容为:

    var log4js = require("./lib/log");
    log4js.configure("master");

    worker.js的配置内容为:

    var express = require("express");
    // 这个是我们上面自定义的模块
    var log4js = require("./log");
    
    var app = express();
    app.configure("worker");
    
    app.use(log4js.useLog());
    
    ...

    如此就完成了。

    需要在某个地方记录日志的时候,我们可以如此

    var log = require("./log").logger("index"); // logger中的参数随便起
    
    ...
    log.info("..."); log.error("...")

     

    5、写在后面

    log4js还有挺多好玩的内容,比如smtp。这是个很有用的功能,比如当项目发生某个错误时,你希望程序能发邮件通知你,该功能就能派出用场了。

    另外,我开源了一个项目booklist。该项目主要在于探讨nodejs建立应用所需要或者注意的地方,非常期待各位指导与探讨,谢谢!

     

    参考

    https://github.com/nomiddlename/log4js-node   

    https://github.com/gcfeng/booklist

  • 相关阅读:
    Kubernetes笔记 (2)
    Kubernetes笔记(3)
    Kubernetes笔记 (1)
    《深入浅出React和Redux》(4)
    【从0安装】xshell和xftp
    【从0安装】Sourcetree
    postman测试需要登录的接口
    vue自定义滚动条组件-vuebar组件
    charles 抓包http 和 https
    pycharm 面板颜色调整和中文汉化
  • 原文地址:https://www.cnblogs.com/yjfengwen/p/3827217.html
Copyright © 2011-2022 走看看