express默认日志组件morgan的方法(2)

// 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){ saveToDatabase(line); // 伪代码,保存到数据库 } }; // 将 dbStream 作为 stream 配置项的值 app.use(morgan('short', {stream: dbStream})); app.use(function(req, res, next){ res.send('ok'); }); app.listen(3000);

深入剖析

morgan的代码非常简洁,从设计上来说,morgan的生命周期包含:

token定义 --> 日志格式定义 -> 日志格式预编译 --> 请求达到/返回 --> 写日志

其中,token定义、日志格式定义前面已经讲到,这里就只讲下 日志格式预编译 的细节。

跟模板引擎预编译一样,日志格式预编译,也是为了提升性能。源码如下,最关键的代码就是compile(fmt)。

function getFormatFunction (name) { // lookup format var fmt = morgan[name] || name || morgan.default // return compiled format return typeof fmt !== 'function' ? compile(fmt) : fmt }

compile()方法的实现细节这里不赘述,着重看下compile(fmt)返回的内容:

var morgan = require('morgan'); var format = morgan['tiny']; var fn = morgan.compile(format); console.log(fn.toString());

运行上面程序,输出内容如下,其中tokens其实就是morgan。 

function anonymous(tokens, req, res /**/) { return "" + (tokens["method"](req, res, undefined) || "-") + " " + (tokens["url"](req, res, undefined) || "-") + " " + (tokens["status"](req, res, undefined) || "-") + " " + (tokens["res"](req, res, "content-length") || "-") + " - " + (tokens["response-time"](req, res, undefined) || "-") + " ms"; }

看下morgan.token()的定义,就很清晰了

function token (name, fn) { morgan[name] = fn return this }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pxwzd.html