morgan
安装
1 | npm install morgan -D |
使用
1 | const morgan = require('morgan') |
morgan(format,options)
format
使用给定的format和options创建一个新的morgan中间件
format:字符串、格式化字符串、生成日志功能的函数
format函数有三个参数:tokens、req、res.
tokens是所有已定义标记的对象,req是HTTP请求,res是HTTP响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //使用预定义的格式化字符串 morgan('tiny') //使用预定义tokens的格式化字符串 morgan(':method :url :status :res[content-length] - :response-time ms') //使用自定义格式化函数 morgan(function (tokens, req, res) { return [ tokens.method(req, res), tokens.url(req, res), tokens.status(req, res), tokens.res(req, res, 'content-length'), '-', tokens['response-time'](req, res), 'ms' ].join(' ') }) |
Options
immediate 在请求而不是响应写入日志行,这意味着即使服务器崩溃,也将记录请求,但是无法记录来自响应的数据(例如响应代码,内容长度等)
skip 确定是否跳过日志记录函数,默认false,该函数将调用skip(req,res)
1
2
3
4 //仅记录错误的响应日志
morgan('combined', {
skip: function (req, res) { return res.statusCode < 400 }
})
stream: 写入日支行的输出流,默认为process.stdout
format 预定义格式
combined 标准的Apache组合日志输出
1 :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"common 标准Apache通用日志输出
1 :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]dev
1 :method :url :status :response-time ms - :res[content-length]short
1 :remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time mstiny
1 :method :url :status :res[content-length] - :response-time ms
自定义 tokens
morgan.token(‘format_name’,callback)
回调函数应该返回字符串,返回值可用作"format_name"
1 morgan.token('type', function (req, res) { return req.headers['content-type'] })
format_name与预定义的tokens相同覆盖默认的
回调函数应该使用req,res,代表请求、响应,此外还可以使用其他参数,其他参数如下
:data[format] 当前UTC时间,可用格式如下
? clf 通用日志格式(
"10/Oct/2000:13:55:36 +0000" )? iso 通用的ISO 8601 日期时间格式(
2000-10-10T13:55:36.000Z )? web 通用的RFC 1123 日期时间格式(
Tue, 10 Oct 2000 13:55:36 GMT )? 如果format为空,默认为web
:http-version 请求的HTTP版本
:method HTTP请求方法
:referrer 请求的referrer标头
:remote-addr 请求的远程地址
:remote-user 身份验证的用户
:req[header] 请求的给定标头。 如果标题不存在,则该值将在日志中显示为“-”
:res[header] 给定的响应标头。 如果响应头不存在,则该值将在日志中显示为“-”
:response-time[digits] 从请求进入morgan到响应头被写入的时间(ms),digits参数是一个数字,指定要包括在该数字上的位数,默认为3,可提供微秒精度
:status 响应的状态码
:total-time[digits] 从请求进入morgan到响应完成之间的时间(ms),digits参数是一个数字,指定要包括在该数字上的位数,默认为3,可提供微秒精度
:url 请求的url
:user-agent 请求的User-Agent标头的内容
morgan.compile(format)
? 将格式字符串编译为供morgan使用的格式函数。 格式字符串是表示单个日志行并可以使用令牌语法的字符串。 tokens是通过:token-name引用的。 如果令牌接受参数,则可以使用[]进行传递,例如::token-name [pretty]将字符串’pretty’作为令牌令牌名称的参数传递
? 从morgan.compile返回的函数采用三个参数tokens,req和res,其中tokens是具有所有已定义tokens的对象,req是HTTP请求,res是HTTP响应。 该函数将返回一个字符串,该字符串将是日志行,或者返回undefined / null以跳过日志记录。
? 通常,格式是使用morgan.format(name,format)定义的,但是对于某些高级用法,此编译功能可直接使用。
使用例子
express/connect
输出到标准输出
1 2 3 4 5 6 7 8 9 10 | var express = require('express') var morgan = require('morgan') var app = express() app.use(morgan('combined')) app.get('/', function (req, res) { res.send('hello, world!') }) |
vanilla http server
输出到标准输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var finalhandler = require('finalhandler') var http = require('http') var morgan = require('morgan') // create "middleware" var logger = morgan('combined') http.createServer(function (req, res) { var done = finalhandler(req, res) logger(req, res, function (err) { if (err) return done(err) // respond to request res.setHeader('content-type', 'text/plain') res.end('hello, world!') }) }) |
日志写入文件
单文件
将所有请求记录到文件access.log中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var express = require('express') var fs = require('fs') var morgan = require('morgan') var path = require('path') var app = express() // create a write stream (in append mode) var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' }) // setup the logger app.use(morgan('combined', { stream: accessLogStream })) app.get('/', function (req, res) { res.send('hello, world!') }) |
循环日志文件
以一天为周期记录日志到/log目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var express = require('express') var morgan = require('morgan') var path = require('path') var rfs = require('rotating-file-stream') // version 2.x var app = express() // create a rotating write stream var accessLogStream = rfs.createStream('access.log', { interval: '1d', // rotate daily path: path.join(__dirname, 'log') }) // setup the logger app.use(morgan('combined', { stream: accessLogStream })) app.get('/', function (req, res) { res.send('hello, world!') }) |
分割日志
该示例应用程序将使用Apache格式将所有请求记录到一个文件,但是错误响应将记录到控制台
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var express = require('express') var fs = require('fs') var morgan = require('morgan') var path = require('path') var app = express() // log only 4xx and 5xx responses to console app.use(morgan('dev', { skip: function (req, res) { return res.statusCode < 400 } })) // log all requests to access.log app.use(morgan('common', { stream: fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' }) })) app.get('/', function (req, res) { res.send('hello, world!') }) |
自定义tokens格式
使用自定义令tokens式的示例应用。 这会向所有请求添加一个ID,并使用:id tokens显示它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var express = require('express') var morgan = require('morgan') var uuid = require('node-uuid') morgan.token('id', function getId (req) { return req.id }) var app = express() app.use(assignId) app.use(morgan(':id :method :url :response-time')) app.get('/', function (req, res) { res.send('hello, world!') }) function assignId (req, res, next) { req.id = uuid.v4() next() } |