注意
此页面生成自 morgan README。morgan
用于 Node.js 的 HTTP 请求日志中间件
以 Dexter 命名,这是一部你不应该看完的剧。
安装
这是一个通过 npm 注册表 提供的 Node.js 模块。安装使用 npm install
命令
$ npm install morgan
API
var morgan = require('morgan')
morgan(format, options)
使用给定的 format
和 options
创建一个新的 morgan 日志中间件函数。format
参数可以是预定义名称的字符串(名称见下文)、格式字符串的字符串,或者是一个将生成日志条目的函数。
format
函数将以三个参数调用:tokens
、req
和 res
,其中 tokens
是一个包含所有已定义 token 的对象,req
是 HTTP 请求,res
是 HTTP 响应。该函数应返回一个字符串作为日志行,或返回 undefined
/ null
以跳过日志记录。
使用预定义格式字符串
morgan('tiny')
使用预定义 token 的格式字符串
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(' ')
})
选项
Morgan 在 options 对象中接受以下属性。
immediate
在请求时而非响应时写入日志行。这意味着即使服务器崩溃,请求也会被记录,但响应中的数据(如响应代码、内容长度等)无法记录。
skip
用于确定是否跳过日志记录的函数,默认为 false
。此函数将以 skip(req, res)
的形式调用。
// EXAMPLE: only log error responses
morgan('combined', {
skip: function (req, res) { return res.statusCode < 400 }
})
stream
用于写入日志行的输出流,默认为 process.stdout
。
预定义格式
提供了多种预定义格式
combined
标准 Apache 联合日志输出。
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
# will output
::1 - - [27/Nov/2024:06:21:42 +0000] "GET /combined HTTP/1.1" 200 2 "-" "curl/8.7.1"
common
标准 Apache 通用日志输出。
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
# will output
::1 - - [27/Nov/2024:06:21:46 +0000] "GET /common HTTP/1.1" 200 2
dev
简洁输出,响应状态根据颜色区分,用于开发。对于成功代码,:status
token 为绿色;对于服务器错误代码,为红色;对于客户端错误代码,为黄色;对于重定向代码,为青色;对于信息代码,则无色。
:method :url :status :response-time ms - :res[content-length]
# will output
GET /dev 200 0.224 ms - 2
short
比默认更短,也包括响应时间。
:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
# will output
::1 - GET /short HTTP/1.1 200 2 - 0.283 ms
tiny
最小化输出。
:method :url :status :res[content-length] - :response-time ms
# will output
GET /tiny 200 2 - 0.188 ms
Token
创建新 token
要定义一个 token,只需使用名称和回调函数调用 morgan.token()
。此回调函数应返回一个字符串值。返回的值在本例中可作为“:type”使用
morgan.token('type', function (req, res) { return req.headers['content-type'] })
使用与现有 token 相同的名称调用 morgan.token()
将覆盖该 token 定义。
token 函数应以参数 req
和 res
调用,分别表示 HTTP 请求和 HTTP 响应。此外,token 可以接受其选择的额外参数来自定义行为。
:date[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
)
如果未给出格式,则默认为 web
。
:http-version
请求的 HTTP 版本。
:method
请求的 HTTP 方法。
:referrer
请求的 Referrer 头部。如果存在,将使用标准拼写错误的 Referer 头部,否则使用 Referrer。
:remote-addr
请求的远程地址。这将使用 req.ip
,否则使用标准的 req.connection.remoteAddress
值(套接字地址)。
:remote-user
作为请求基本认证一部分的用户。
:req[header]
请求的给定 header
。如果头部不存在,其值将在日志中显示为 "-"
。
:res[header]
响应的给定 header
。如果头部不存在,其值将在日志中显示为 "-"
。
:response-time[digits]
请求进入 morgan
到响应头写入之间的时间,单位为毫秒。
digits
参数是一个数字,指定要包含在数字中的位数,默认为 3
,提供微秒精度。
:status
响应的状态码。
如果请求/响应周期在响应发送到客户端之前完成(例如,TCP 套接字被客户端中止请求而过早关闭),则状态将为空(在日志中显示为 "-"
)。
:total-time[digits]
请求进入 morgan
到响应完成写入连接之间的时间,单位为毫秒。
digits
参数是一个数字,指定要包含在数字中的位数,默认为 3
,提供微秒精度。
:url
请求的 URL。如果存在,将使用 req.originalUrl
,否则使用 req.url
。
:user-agent
请求的 User-Agent 头部内容。
morgan.compile(format)
将格式字符串编译成一个 format
函数,供 morgan
使用。格式字符串表示单行日志,并可利用 token 语法。token 通过 :token-name
引用。如果 token 接受参数,可以使用 []
传递,例如::token-name[pretty]
会将字符串 'pretty'
作为参数传递给 token token-name
。
从 morgan.compile
返回的函数接受三个参数:tokens
、req
和 res
,其中 tokens
是包含所有已定义 token 的对象,req
是 HTTP 请求,res
是 HTTP 响应。该函数将返回一个字符串作为日志行,或返回 undefined
/ null
以跳过日志记录。
通常格式使用 morgan.format(name, format)
定义,但对于某些高级用法,此编译函数可直接使用。
示例
express/connect
示例应用程序,将所有请求以 Apache combined 格式记录到标准输出 (STDOUT)
var express = require('express')
var morgan = require('morgan')
var app = express()
app.use(morgan('combined'))
app.get('/', function (req, res) {
res.send('hello, world!')
})
原生 HTTP 服务器
示例应用程序,将所有请求以 Apache combined 格式记录到标准输出 (STDOUT)
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!')
})
})
将日志写入文件
单个文件
示例应用程序,将所有请求以 Apache combined 格式记录到文件 access.log
。
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!')
})
日志文件轮换
示例应用程序,将所有请求以 Apache combined 格式,使用 rotating-file-stream 模块,每天记录到一个新的日志文件,存放在 log/
目录中。
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!')
})
拆分 / 双重日志记录
morgan
中间件可以根据需要多次使用,实现以下组合:
- 在请求时记录一次,在响应时记录一次
- 将所有请求记录到文件,但将错误记录到控制台
- ……等等!
示例应用程序,将所有请求以 Apache 格式记录到文件,但错误响应记录到控制台
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!')
})
使用自定义 token 格式
示例应用程序,将使用自定义 token 格式。这会为所有请求添加一个 ID,并使用 :id
token 显示它。
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()
}