美文网首页
log4js日志管理(基于Nodejs)

log4js日志管理(基于Nodejs)

作者: 无懈可击 | 来源:发表于2021-05-06 22:44 被阅读0次

    log4js日志管理

    0 码云仓库代码(欢迎Start)

    码云仓库代码-https://gitee.com/hongjunyong/markdown-collect/tree/master

    1 基本介绍

    1.1 源码及文档

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

    1.2 介绍

    • 显示程序运行状态
    • 帮助开发者排除问题故障
    • 结合专业的日志分析工具(如 ELK )给出预警

    1.3 log4j的8个日志级别

    log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。

    1. ALL 最低等级的,用于打开所有日志记录。
    2. TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
    3. DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
    4. INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
    5. WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
    6. ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
    7. FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
    8. OFF 最高等级的,用于关闭所有日志记录。

    如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

    1.4 安装

        npm install log4js --save-dev   // log4js
        npm install ip --save-dev       // 获取ip地址
    

    1.5 文件解析

    1 目录结构

    |- middleware
        |- log4js
            |- access.js 记录和配置客户端信息
            |- index.js 对日志中间件进行错误处理
            |- logger.js log4js记录日志
    
    目录结构

    2 记录说明

    记录说明

    2 代码解析

    2.1 在koa入口文件(app.js)注册日志中间件

        // 引入日志中间件
        const logger = require("../middleware/log4js/index");
        const ip = require("ip");
        // 注册中间件
        app.use(logger({
          // koa提供的环境变量
          env: app.env,
          // 项目名,记录在日志中的项目信息
          projectName: 'vue-vant',
          // 指定记录的日志级别
          applogLevel: 'debug',
          // 指定日志存放的目录名
          dir: 'logs',
          // 默认情况下服务器 ip 地址
          serverIp: ip.address()
        }));
    

    2.2 index.js入口文件 --> 对日志中间件进行错误处理

    const logger = require('./logger');
    module.exports = (options) => {
        const loggerMiddleware = logger(options);
    
        return (ctx, next) => {
            return loggerMiddleware(ctx, next)
                .catch((e) => {
    
                    // 如果中间件里面有抛出错误,这里将通过 catch 函数捕捉到并处理,将状态码小于 500 的错误统一按照 500 错误码处理,以方便后面的 http-error 中间件显示错误页面。
                    if (ctx.status < 500) {
                        ctx.status = 500;
                    }
                    // 异常日志打印
                    ctx.log.error(e.stack);
                    ctx.state.logged = true;
                    ctx.throw(e);
                })
        }
    }
    

    2.3 logger.js记录日志

    2.3.1 参数定义

        // 将日志的不同级别提取为数组,方便后面做处理
        const methods = ['trace', 'debug', 'info', 'warn', 'error', 'fatal', 'mark'];
    
        let contextLogger = {};
        // 提取默认公用参数对象(以防注册中间件,用户没有传入参数)
        const defaultInfo = {
            // 开发环境
            env: 'dev',
            // 输出的文件夹名称
            dir: 'logs',
            // 错误级别
            applogLevel: 'info'
        };
        // 继承自 defaultInfo 默认参数(options会把defaultInfo里的参数覆盖掉)
        const opts = Object.assign({}, defaultInfo, options || {});
        // 需要的变量解构 方便使用
        const { env, dir, applogLevel } = opts;
    

    2.3.2 日志文件命名、日志切割

        const appenders = { cheese: {
            // 日志类型
            type: 'dateFile',
            // 输出日志文件名称
            filename: `server/${dir}/task`,
            // 名称后面添加年月日
            pattern: '-yyyy-MM-dd.log',
            // 是否总是有后缀名
            alwaysIncludePattern: true
        } };
    

    2.3.3 把日志在终端输出(默认关闭,需要时可以把注释去掉)

        // if (env === 'dev' || env === 'local' || env === 'development') {
        //     appenders.out = {
        //         type: 'console'
        //     }
        // }
    

    2.3.4 指定日志的默认配置项

        const config = {
            appenders: appenders,
            /**
             * 指定日志的默认配置项
             * 如果 log4js.getLogger 中没有指定,默认为 cheese 日志的配置项
             * 指定 cheese 日志的记录内容为 error 及 error 以上级别的信息
             *
             * var obj = {'a':'123','b':'345'};
             * console.log(Object.keys(obj));  //['a','b']
             *
             * Object.keys(appenders) // cheese
             */
            categories: {
                default: {
                    appenders: Object.keys(appenders),
                    level: applogLevel
                }
            }
        };
    

    2.3.5 计算响应时间

    1 记录请求开始的时间

        const start = Date.now();
        log4js.configure(config);
    
        await next();
    

    2 记录请求结束的时间

      const end = Date.now();
      const responseTime = end - start;
    

    3 响应时间

    响应时间为${responseTime/1000}s
    

    2.3.5 循环methods将所有方法挂载到ctx上

        methods.forEach((method, i) => {
            contextLogger[method] = (message) => {
                // 将入参换为函数返回的字符串
                logger[method](access(ctx, message, {}))
            }
        });
        ctx.log = contextLogger;
    
    • 调用:ctx.log.error('错误啦')

    2.3.6 把日志输出在指定的文件里,并且把options操作过滤

        // 过滤掉options操作(跨域)
        if (ctx.request.method != 'OPTIONS') {
            logger.info(access(ctx, `响应时间为${responseTime/1000}s`, {}));
        }
    

    2.4 access.js封装打印信息

    2.4.1 获取用户提交数据、服务端返回的json

        // 请求方法
        var getMethod = ctx.request.method;
        // 用户提交的数据
        var params = '';
        // 服务端返回的json
        var data = '';
    
        if (getMethod === 'GET') {
            params = ctx.query
        } else if (getMethod === 'POST') {
            params = ctx.request.body
        } else if (getMethod === 'PUT') {
            params = ctx.request.body
        } else if (getMethod === 'DELETE') {
            params = ctx.query
        }
        data = ctx.body
    

    2.4.2 获取参数

        const {
            // 请求方法 get post或其他
            method,
            // 请求链接
            url,
            // 发送请求的客户端的host
            host,
            // 请求中的headers
            headers
        } = ctx.request;
    

    2.4.3 返回打印信息

        const client = {
            method,
            url,
            host,
            message,
            params,
            data,
            // 请求的源地址
            referer: headers['referer'],
            // 客户端信息设备 及 浏览器信息
            userAgent: headers['user-agent'],
        };
        // client的参数拷贝给commonInfo
        return JSON.stringify(Object.assign(commonInfo, client));
    

    2.5 THE END

    相关文章

      网友评论

          本文标题:log4js日志管理(基于Nodejs)

          本文链接:https://www.haomeiwen.com/subject/uzsjdltx.html