美文网首页server-xin
express 默认日志组件 morgan 学习

express 默认日志组件 morgan 学习

作者: Gary嘉骏 | 来源:发表于2017-09-09 22:47 被阅读20次

    入门

    morgan是express默认的日志中间件,也可以脱离express,作为node.js的日志组件单独使用

    • 简单例子index.js:
    var express = require('express');
    var app = express();
    var morgan = require('morgan');
    
    app.use(morgan('short'));
    app.use(function(req, res, next){
        res.send('ok');
    });
    
    app.listen(3000);
    

    node index.js运行程序,并在浏览器里访问 http://127.0.0.1:3000 ,打印日志如下:

    ::1 - GET / HTTP/1.1 200 2 - 3.487 ms
    ::1 - GET /favicon.ico HTTP/1.1 200 2 - 0.591 ms
    

    核心API

    morgan的API非常少,使用频率最高的就是morgan(),作用是返回一个express日志中间件。

    morgan(format, options)
    

    参数说明如下:

    • format:可选,morgan与定义了几种日志格式,每种格式都有对应的名称,比如combinedshort等,默认是- ---- default。不同格式的差别可参考这里
    • options:可选,配置项,包含stream(常用)、skipimmediate
    • stream:日志的输出流配置,默认是process.stdout。
    • skip:是否跳过日志记录,使用方式可以参考这里
    • immediate:布尔值,默认是false。当为true时,一收到请求,就记录日志;如果为false,则在请求返回后,再记录日志。

    自定义日志格式:

    morgan.format(name, format);  // 自定义日志格式
    morgan.token(name, fn);  // 自定义token
    
    • format:name是自定义的名称,format 是自定义的模块变量组合,例子:
    morgan.format('test', '[test] :method :url :status');
    app.use(morgan('test'));
    

    输出:

    [test] GET / 304
    [test] GET /favicon.ico 200
    
    • token: name模块的字符,fn渲染时运行并返回 设定string值,例子:
    // 自定义token
    morgan.token('from', function(req, res){
        return req.query.from || '-';
    });
    
    // 自定义format,其中包含自定义的token
    morgan.format('test', '[test] :method :url :status :from');
    

    运行程序,并在浏览器里先后访问 http://127.0.0.1:3000/hello?from=apphttp://127.0.0.1:3000/hello?from=pc

    [test] GET /hello?from=app 200 app
    [test] GET /favicon.ico 304 -
    [test] GET /hello?from=pc 200 pc
    [test] GET /favicon.ico 304 -
    

    中级使用

    将日志打印到本地文件

    var express = require('express');
    var app = express();
    var morgan = require('morgan');
    var fs = require('fs');
    var path = require('path');
    
    var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'});
    
    app.use(morgan('short', {stream: accessLogStream}));
    app.use(function(req, res, next){
        res.send('ok');
    });
    
    app.listen(3000);
    

    高级使用

    日志切割

    一个线上应用,如果所有的日志都落地到同一个本地文件,时间久了,文件会变得非常大,既影响性能,又不便于查看。这时候,就需要用到日志分割了。

    借助file-stream-rotator插件,可以轻松完成日志分割的工作。

    var FileStreamRotator = require('file-stream-rotator')
    var express = require('express')
    var fs = require('fs')
    var morgan = require('morgan')
    var path = require('path')
    
    var app = express()
    var logDirectory = path.join(__dirname, 'log')
    
    // ensure log directory exists
    fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory)
    
    // create a rotating write stream
    var accessLogStream = FileStreamRotator.getStream({
      date_format: 'YYYYMMDD',
      filename: path.join(logDirectory, 'access-%DATE%.log'),
      frequency: 'daily',
      verbose: false
    })
    
    // setup the logger
    app.use(morgan('combined', {stream: accessLogStream}))
    
    app.get('/', function (req, res) {
      res.send('hello, world!')
    })
    app.listen(3000)
    

    日志写入数据库

    有的时候,我们会有这样的需求,将访问日志写入数据库。这种需求常见于需要实时查询统计的日志系统。

    morgan里该如何实现呢?从文档上,并没有看到适合的扩展接口。于是查阅了下morgan的源码,发现实现起来非常简单。

    回顾下之前日志写入本地文件的例子,最关键的两行代码如下。通过stream指定日志的输出流。

    var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'});
    app.use(morgan('short', {stream: accessLogStream}));
    

    在morgan内部,大致实现是这样的(简化后)。

    // opt为配置文件
    var stream = opts.stream || process.stdout;
    var logString = createLogString();  // 伪代码,根据format、token的定义,生成日志
    stream.write(logString);
    

    于是,可以用比较取巧的方式来实现目的:声明一个带write方法的对象,并作为stream配置传入。

    var express = require('express');
    var app = express();
    var morgan = require('morgan');
    
    // 带write方法的对象
    var dbStream = {
      write: function(line){
       console.log(line);// 正常输出
        saveToDatabase(line);  // 伪代码,保存到数据库
      }
    };
    
    // 将 dbStream 作为 stream 配置项的值
    app.use(morgan('short', {stream: dbStream}));
    app.use(function(req, res, next){
      res.send('ok');
    });
    
    app.listen(3000);
    

    相关

    官方文档

    相关文章

      网友评论

        本文标题:express 默认日志组件 morgan 学习

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