🌐 Nodejs.cn

morgan 中间件

用于 Node.js 的 HTTP 请求记录中间件

🌐 HTTP request logger middleware for node.js

Dexter 命名,你不应该在看完之前观看这部剧。

安装

🌐 Installation

这是一个可以通过npm注册表获取的Node.js模块。安装可以使用npm install命令完成:

🌐 This is a Node.js module available through the npm registry. Installation is done using the npm install command:

Terminal window
npm install morgan

Note

morgan 不包含其自身的 TypeScript 类型定义。如果你使用 TypeScript,还需要作为开发依赖从 DefinitelyTyped 安装社区维护的类型:

Terminal window
npm install --save-dev @types/morgan

API

var morgan = require('morgan');

morgan(format, options)

使用给定的 formatoptions 创建一个新的 morgan 日志中间件函数。format 参数可以是预定义名称的字符串(参见下文名称)、格式字符串的字符串,或者将生成日志条目的函数。

🌐 Create a new morgan logger middleware function using the given format and options. The format argument may be a string of a predefined name (see below for the names), a string of a format string, or a function that will produce a log entry.

format 函数将使用三个参数 tokensreqres 调用,其中 tokens 是包含所有已定义令牌的对象,req 是 HTTP 请求,res 是 HTTP 响应。该函数预计返回一个字符串作为日志行,或者返回 undefined / null 来跳过日志记录。

🌐 The format function will be called with three arguments tokens, req, and res, where tokens is an object with all defined tokens, req is the HTTP request and res is the HTTP response. The function is expected to return a string that will be the log line, or undefined / null to skip logging.

使用预定义的格式字符串

🌐 Using a predefined format string

morgan('tiny');

使用预定义标记的格式字符串

🌐 Using format string of predefined tokens

morgan(':method :url :status :res[content-length] - :response-time ms');

使用自定义格式函数

🌐 Using a custom format function

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'](https://github.com/expressjs/morgan/blob/HEAD/req, res), 'ms'
].join(' ')
})

选项

🌐 Options

Morgan 在选项对象中接受这些属性。

🌐 Morgan accepts these properties in the options object.

immediate

在请求时而不是响应时写日志。这意味着即使服务器崩溃,请求也会被记录,但响应中的数据(如响应代码、内容长度等)无法被记录

🌐 Write log line on request instead of response. This means that a requests will be logged even if the server crashes, but data from the response (like the response code, content length, etc.) cannot be logged.

skip

用于确定是否跳过日志记录的函数,默认值为 false。此函数将作为 skip(req, res) 被调用。

🌐 Function to determine if logging is skipped, defaults to false. This function will be called as skip(req, res).

// EXAMPLE: only log error responses
morgan('combined', {
skip: function (req, res) {
return res.statusCode < 400;
},
});
stream

用于写入日志行的输出流,默认为 process.stdout

🌐 Output stream for writing log lines, defaults to process.stdout.

预定义格式

🌐 Predefined Formats

提供了各种预定义格式:

🌐 There are various pre-defined formats provided:

combined

标准 Apache 综合日志输出。

🌐 Standard Apache combined log output.

: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 通用日志输出。

🌐 Standard Apache common log output.

: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 令牌在成功代码时将显示为绿色,服务器错误代码时为红色,客户端错误代码时为黄色,重定向代码时为青色,信息代码时不着色。

🌐 Concise output colored by response status for development use. The :status token will be colored green for success codes, red for server error codes, yellow for client error codes, cyan for redirection codes, and uncolored for information codes.

:method :url :status :response-time ms - :res[content-length]
# will output
GET /dev 200 0.224 ms - 2
short

比默认值短,也包括响应时间。

🌐 Shorter than default, also including response time.

: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

最小输出。

🌐 The minimal output.

:method :url :status :res[content-length] - :response-time ms
# will output
GET /tiny 200 2 - 0.188 ms

令牌

🌐 Tokens

创建新令牌

🌐 Creating new tokens

要定义一个令牌,只需使用名称和回调函数调用 morgan.token()。该回调函数应返回一个字符串值。返回的值随后在此情况下可作为 “:type” 使用:

🌐 To define a token, simply invoke morgan.token() with the name and a callback function. This callback function is expected to return a string value. The value returned is then available as “:type” in this case:

morgan.token('type', function (req, res) {
return req.headers['content-type'];
});

使用与现有令牌相同的名称调用 morgan.token() 将覆盖该令牌定义。

🌐 Calling morgan.token() using the same name as an existing token will overwrite that token definition.

token 函数预期会使用参数 reqres 被调用,分别表示 HTTP 请求和 HTTP 响应。此外,token 可以接受其他任意参数以自定义行为。

🌐 The token function is expected to be called with the arguments req and res, representing the HTTP request and HTTP response. Additionally, the token can accept further arguments of it’s choosing to customize behavior.

:date[format]

当前的 UTC 日期和时间。可用的格式有:

🌐 The current date and time in UTC. The available formats are:

  • 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

🌐 If no format is given, then the default is web.

:http-version

请求的 HTTP 版本。

🌐 The HTTP version of the request.

:method

请求的 HTTP 方法。

🌐 The HTTP method of the request.

:pid

处理该请求的 Node.js 进程的进程 ID。

🌐 The process ID of the Node.js process handling the request.

:referrer

请求的 Referrer 头。如果存在标准拼写错误的 Referer 头,则使用它,否则使用 Referrer。

🌐 The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer.

:remote-addr

请求的远程地址。如果可用,将使用 req.ip,否则使用标准的 req.connection.remoteAddress 值(套接字地址)。

🌐 The remote address of the request. This will use req.ip, otherwise the standard req.connection.remoteAddress value (socket address).

:remote-user

用户作为请求的基本身份验证的一部分进行了身份验证。

🌐 The user authenticated as part of Basic auth for the request.

:req[header]

请求中给定的 header。如果头部不存在,该值将在日志中显示为 "-"

🌐 The given header of the request. If the header is not present, the value will be displayed as "-" in the log.

:res[header]

响应中给定的 header。如果头部不存在,该值将在日志中显示为 "-"

🌐 The given header of the response. If the header is not present, the value will be displayed as "-" in the log.

:response-time[digits]

从请求进入 morgan 到响应头被写入的时间,以毫秒为单位。

🌐 The time between the request coming into morgan and when the response headers are written, in milliseconds.

digits 参数是一个数字,用于指定要包含在数字中的位数,默认为 3,它提供微秒精度。

🌐 The digits argument is a number that specifies the number of digits to include on the number, defaulting to 3, which provides microsecond precision.

:status

响应的状态码。

🌐 The status code of the response.

如果请求/响应周期在向客户端发送响应之前完成(例如,TCP 套接字因客户端中止请求而过早关闭),则状态将为空(在日志中显示为 "-")。

🌐 If the request/response cycle completes before a response was sent to the client (for example, the TCP socket closed prematurely by a client aborting the request), then the status will be empty (displayed as "-" in the log).

:total-time[digits]

从请求进入 morgan 到响应完成写入连接所花费的时间,单位为毫秒。

🌐 The time between the request coming into morgan and when the response has finished being written out to the connection, in milliseconds.

digits 参数是一个数字,用于指定要包含在数字中的位数,默认为 3,它提供微秒精度。

🌐 The digits argument is a number that specifies the number of digits to include on the number, defaulting to 3, which provides microsecond precision.

:url

请求的 URL。如果存在,将使用 req.originalUrl,否则使用 req.url

🌐 The URL of the request. This will use req.originalUrl if exists, otherwise req.url.

:user-agent

请求的 User-Agent 头的内容。

🌐 The contents of the User-Agent header of the request.

morgan.compile(format)

将格式字符串编译成供 morgan 使用的 format 函数。格式字符串是一种表示单条日志行的字符串,并且可以使用标记语法。标记通过 :token-name 引用。如果标记接受参数,可以使用 [] 传递,例如::token-name[pretty] 会将字符串 'pretty' 作为参数传递给标记 token-name

🌐 Compile a format string into a format function for use by morgan. A format string is a string that represents a single log line and can utilize token syntax. Tokens are references by :token-name. If tokens accept arguments, they can be passed using [], for example: :token-name[pretty] would pass the string 'pretty' as an argument to the token token-name.

morgan.compile 返回的函数接受三个参数 tokensreqres,其中 tokens 是包含所有已定义令牌的对象,req 是 HTTP 请求,res 是 HTTP 响应。该函数将返回一个字符串作为日志行,或者返回 undefined / null 来跳过记录日志。

🌐 The function returned from morgan.compile takes three arguments tokens, req, and res, where tokens is object with all defined tokens, req is the HTTP request and res is the HTTP response. The function will return a string that will be the log line, or undefined / null to skip logging.

通常格式使用 morgan.format(name, format) 定义,但对于某些高级用法,此编译函数可以直接使用。

🌐 Normally formats are defined using morgan.format(name, format), but for certain advanced uses, this compile function is directly available.

例子

🌐 Examples

express/connect

示例应用,将以 Apache 组合格式将所有请求记录到 STDOUT

🌐 Sample app that will log all request in the Apache combined format to 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 服务器

🌐 vanilla http server

示例应用,将以 Apache 组合格式将所有请求记录到 STDOUT

🌐 Sample app that will log all request in the Apache combined format to 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!');
});
});

将日志写入文件

🌐 write logs to a file

单个文件

🌐 single file

示例应用,将以 Apache 组合格式记录所有请求到文件 access.log

🌐 Sample app that will log all requests in the Apache combined format to the file 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!');
});

日志文件轮换

🌐 log file rotation

示例应用,将以 Apache 组合格式记录所有请求到 log/ 目录中的每日日志文件,使用 rotating-file-stream 模块

🌐 Sample app that will log all requests in the Apache combined format to one log file per day in the log/ directory using the rotating-file-stream module.

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!');
});

分割/双重记录

🌐 split / dual logging

morgan 中间件可以根据需要多次使用,从而实现如下组合:

🌐 The morgan middleware can be used as many times as needed, enabling combinations like:

  • 请求的日志条目和响应的日志条目
  • 将所有请求记录到文件,但错误记录到控制台
  • …等等!

示例应用,将使用 Apache 格式将所有请求记录到文件中,但错误响应会记录到控制台:

🌐 Sample app that will log all requests to a file using Apache format, but error responses are logged to the console:

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!');
});

使用自定义令牌格式

🌐 use custom token formats

示例应用,将使用自定义令牌格式。这会为所有请求添加一个 ID,并使用 :id 令牌显示它。

🌐 Sample app that will use custom token formats. This adds an ID to all requests and displays it using the :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();
}

许可证

🌐 License

MIT