morgan
[TOC]
索引
General:
- morgan():
(format, options?),用于创建一个 HTTP 请求日志中间件,并根据传入的参数配置日志格式、输出方式等行为。
方法/属性
General
morgan()
morgan():(format, options?),用于创建一个 HTTP 请求日志中间件,并根据传入的参数配置日志格式、输出方式等行为。
morgan():
(format, options),完整语法(指定格式 + 选项)。morgan():
(format),简化语法(仅指定格式,使用默认选项)。morgan():
(options),特殊情况(仅指定选项,格式使用默认值'default')。format:
string|Function,用于定义日志格式,支持 字符串 或 函数 两种类型。options?:
object,配置选项,用于控制日志的输出方式、过滤规则等。stream:
stream.Writable,默认:process.stdout(控制台),日志的输出流(如文件流、控制台)。用于将日志写入文件或其他目的地。skip:
(req,res)=>boolean,默认:undefined,过滤函数。返回
true则跳过当前请求的日志记录,返回
false则记录。
immediate:
boolean,默认:false,日志记录时机。返回
false(默认)在响应发送后记录(可获取响应状态码等);返回
true在请求到达时立即记录(无法获取响应信息)。
prettify:
boolean,默认:false,(已废弃)是否美化 JSON 格式日志,最新版本建议手动处理。
返回:
middleware:
(req,res,next)=>void,返回一个 Express 中间件函数。
示例:
使用内置的 'dev' 格式:
jsapp.use(morgan('dev')); // 使用内置的 'dev' 格式自定义格式:时间 + 方法 + URL + 状态码 + 响应时间:
js// 自定义格式:时间 + 方法 + URL + 状态码 + 响应时间 app.use(morgan(':date[iso] :method :url :status :response-time ms'));自定义函数:根据状态码动态调整日志前缀(成功用绿色,错误用红色):
js// 自定义函数:根据状态码动态调整日志前缀(成功用绿色,错误用红色) app.use(morgan((tokens, req, res) => { const status = tokens.status(req, res); const prefix = status >= 400 ? '\x1b[31m' : '\x1b[32m'; // 红色(错误)/绿色(成功) return `${prefix}[${tokens.date(req, res, 'iso')}] ${tokens.method(req, res)} ${tokens.url(req, res)} ${status} \x1b[0m`; }));将日志写入文件(配置
stream)jsconst fs = require('fs'); const logStream = fs.createWriteStream('access.log', { flags: 'a' }); app.use(morgan('combined', { stream: logStream })); // 日志写入 access.log过滤静态资源请求(配置
skip)jsapp.use(morgan('dev', { skip: (req, res) => { // 跳过所有静态资源(/public 路径下的请求) return req.originalUrl.startsWith('/public'); } }));请求到达时立即记录日志(配置
immediate)javascriptapp.use(morgan('dev', { immediate: true })); // 不等待响应,请求一来就记录
基本使用
介绍 morgan
morgan:是 Express 生态中最常用的 HTTP 请求日志中间件,核心作用是自动记录客户端发起的每一次 HTTP 请求细节(如请求方法、URL、响应时间等),帮助开发者调试问题、监控服务运行状态。
核心定位与价值:
调试辅助:
开发阶段,通过日志快速定位请求异常(如 404/500 错误对应的 URL、参数)。
服务监控:
生产阶段,记录请求量、响应时间、客户端 IP 等数据,用于分析服务负载和用户行为。
安装
在 Express 项目根目录执行命令,安装 morgan:
npm i morgan基本示例
在项目入口文件(如
app.js)中引入并使用,默认会将日志输出到 控制台:js// 1. 引入 express 和 morgan const express = require('express'); const morgan = require('morgan'); const app = express(); // 2. 挂载 morgan 中间件(指定日志格式为 'dev',适合开发环境) app.use(morgan('dev')); // 3. 定义测试路由 app.get('/', (req, res) => { res.send('Hello Morgan!'); }); // 启动服务 app.listen(3000, () => { console.log('Server running on port 3000'); });启动服务后,访问
http://localhost:3000,控制台会输出类似日志:shGET / 200 3.245 ms - 13
日志格式
morgan 支持多种日志格式,可通过参数指定,分为 内置格式 和 自定义格式 两类。
内置格式(常用)
内置格式已预设好日志内容,直接使用即可,适合大多数场景。
| 格式名称 | 特点 | 适用场景 | 日志示例 |
|---|---|---|---|
dev | 简洁格式,包含核心信息(方法、URL、状态码、响应时间、响应大小) | 开发环境 | GET / 200 3.245 ms - 13 |
combined | 完整格式,包含客户端 IP、时间、Referer、User-Agent | 生产环境(需详细日志) | 127.0.0.1 - - [10/Oct/2024:10:00:00 +0800] "GET / HTTP/1.1" 200 13 "http://localhost/" "Chrome/118.0.0.0" |
common | 基础格式,比 combined 少 Referer 和 User-Agent | 生产环境(简化日志) | 127.0.0.1 - - [10/Oct/2024:10:00:00 +0800] "GET / HTTP/1.1" 200 13 |
short | 简短格式,包含客户端 IP、方法、URL、状态码、响应时间、响应大小 | 快速查看关键信息 | 127.0.0.1 GET / 200 13 - 3.245 ms |
tiny | 极简格式,仅包含方法、URL、状态码 | 仅需最基础日志 | GET / 200 |
自定义格式
若内置格式不满足需求,可通过 “格式字符串” 自定义日志内容,核心是使用 morgan 提供的 占位符(以 : 开头)。
常用占位符:
:method:HTTP 请求方法(GET、POST 等):url:请求的 URL 路径:status:HTTP 响应状态码(200、404、500 等):response-time:响应时间(单位:毫秒):remote-addr:客户端 IP 地址:date[format]:请求时间(格式可自定义,如:date[iso]为 ISO 标准时间):res[content-length]:响应体大小
示例:自定义格式
// 自定义格式字符串
app.use(morgan(':date[iso] :method :url :status :response-time ms'));
// 输出日志示例
// 2024-10-10T02:00:00.000Z GET / 200 3.245 ms日志写入文件
默认情况下,morgan 会将日志输出到控制台(process.stdout),但生产环境中通常需要将日志写入文件,或过滤不必要的请求日志(如静态资源请求)。
const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');
const app = express();
// 1. 创建日志写入流(append 模式,避免覆盖历史日志)
const accessLogStream = fs.createWriteStream(
path.join(__dirname, 'access.log'), // 日志文件路径
{ flags: 'a' } // flags: 'a' 表示“追加写入”
);
// 2. 指定日志格式为 'combined',并输出到文件流
app.use(morgan('combined', { stream: accessLogStream }));
// 测试路由
app.get('/', (req, res) => {
res.send('Log to file!');
});
app.listen(3000);日志过滤
通过 skip 选项,可跳过不需要记录的请求(如排除静态资源、特定 URL 的请求)。
示例:不记录静态资源
app.use(morgan('dev', {
skip: (req, res) => {
// 若请求路径以 /public 开头,则跳过日志记录
return req.originalUrl.startsWith('/public');
}
}));按环境切换配置
开发环境中输出到控制台,生产环境中写入文件,可通过 process.env.NODE_ENV 区分环境。
const app = express();
if (process.env.NODE_ENV === 'development') {
// 开发环境:输出到控制台,使用 dev 格式
app.use(morgan('dev'));
} else {
// 生产环境:写入文件,使用 combined 格式
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });
app.use(morgan('combined', { stream: accessLogStream }));
}