node 日志工具

在 Node.js 项目中,日志记录是至关重要的一环,它能帮助开发者追踪系统运行状态、排查错误、分析用户行为等。下面将从日志的作用、常用工具、实现方式及最佳实践等方面,详细介绍 Node.js 项目的日志记录。

日志的作用

  • 错误排查:当程序出现异常时,日志可以提供错误发生的上下文、堆栈信息等,帮助快速定位问题。
  • 系统监控:通过记录系统的关键指标(如响应时间、内存占用等),可以实时监控系统运行状态,及时发现潜在风险。
  • 行为分析:记录用户的操作行为(如登录、点击等),有助于分析用户习惯,为产品优化提供依据。
  • 审计追踪:在一些对安全性要求较高的场景(如金融系统),日志可以用于审计用户操作,确保合规性。

常用的日志工具

  1. winston
  • 特点:功能强大、灵活,支持多种日志传输方式(如控制台、文件、数据库等),可以自定义日志格式和级别。

  • 安装:npm install winston

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const winston = require("winston");

// 创建日志器
const logger = winston.createLogger({
level: "info", // 日志级别,默认info,可选error、warn、info、verbose、debug、silly
format: winston.format.combine(
winston.format.timestamp(), // 添加时间戳
winston.format.json() // 以JSON格式输出
),
transports: [
new winston.transports.Console(), // 输出到控制台
new winston.transports.File({ filename: "error.log", level: "error" }), // 错误日志输出到文件
new winston.transports.File({ filename: "combined.log" }), // 所有日志输出到文件
],
});

// 使用日志器
logger.error("这是一个错误日志");
logger.warn("这是一个警告日志");
logger.info("这是一个信息日志");
  1. pino
  • 特点:高性能,日志输出格式简洁(默认 JSON 格式),适合在高并发场景下使用。

  • 安装:npm install pino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const pino = require("pino");

// 创建日志器
const logger = pino(
{
level: "info",
timestamp: () => `,"time":"${new Date().toISOString()}"`, // 自定义时间戳格式
},
pino.destination("app.log")
); // 输出到文件

// 使用日志器
logger.error("错误信息");
logger.info("信息内容");
  1. morgan
  • 特点:主要用于 HTTP 服务器的日志记录,能记录请求方法、URL、状态码、响应时间等信息,常与 Express 框架配合使用。

  • 安装:npm install morgan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require("express");
const morgan = require("morgan");

const app = express();

// 使用morgan记录日志,输出到控制台
app.use(morgan("combined"));

// 也可以输出到文件
const fs = require("fs");
const path = require("path");
const accessLogStream = fs.createWriteStream(
path.join(__dirname, "access.log"),
{ flags: "a" }
);
app.use(morgan("combined", { stream: accessLogStream }));

app.get("/", (req, res) => {
res.send("Hello World!");
});

app.listen(3000, () => {
console.log("Server is running on port 3000");
});
  1. log4js

log4js 是 Node.js 生态中一款功能丰富的日志管理工具,灵感源自 Java 的 log4j,提供了灵活的日志配置、多种输出方式和分级管理能力,广泛应用于各类 Node.js 项目中。

  • 安装:npm install log4js

核心特性

  • 多输出目标(Appenders)
    支持将日志输出到控制台、文件、数据库、邮件等多种目标,且可同时配置多个输出源。
  • 日志分级
    遵循标准日志级别(从高到低):trace < debug < info < warn < error < fatal,可通过配置过滤不同级别的日志。
  • 日志格式自定义
    支持自定义日志格式(如添加时间戳、日志级别、模块名等),也可使用内置格式(如 JSON 格式、彩色控制台格式)。
  • 日志轮转
    自动切割大日志文件(按大小、时间),避免单个日志文件过大,同时支持压缩旧日志。
  • 配置灵活
    可通过代码或配置文件(JSON/JS)定义日志行为,便于环境切换(开发 / 生产)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const log4js = require("log4js");

// 配置日志:输出到控制台和文件
log4js.configure({
appenders: {
console: { type: "console" }, // 控制台输出
file: { type: "file", filename: "app.log" }, // 文件输出
},
categories: {
default: { appenders: ["console", "file"], level: "info" }, // 默认日志类别
},
});

// 获取日志实例
const logger = log4js.getLogger();

// 输出不同级别日志
logger.trace("追踪信息(最低级别)");
logger.debug("调试信息");
logger.info("普通信息");
logger.warn("警告信息");
logger.error("错误信息");
logger.fatal("致命错误信息(最高级别)");

Node + Express 日志工具

在 Node.js + Express 项目中,日志插件的选择需要兼顾 HTTP 请求日志 和 业务逻辑日志 两方面。结合 Express 框架的特性,推荐以下组合方案:

1. 核心推荐:morgan + winston

  • morgan:专注处理 HTTP 请求日志
    作为 Express 官方推荐的中间件,它能完美记录请求方法、URL、状态码、响应时间、客户端 IP 等 HTTP 特有信息,配置简单且与 Express 无缝集成。
  • winston:处理业务日志和错误日志
    负责记录代码中的业务逻辑日志(如用户操作、数据变更)、错误堆栈、系统状态等,支持多输出目标(文件、控制台、数据库)和灵活的日志级别控制。

1.安装

1
npm install morgan winston winston-daily-rotate-file

2.配置(logger.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
const winston = require("winston");
const DailyRotateFile = require("winston-daily-rotate-file");
const morgan = require("morgan");
const fs = require("fs");
const path = require("path");

// 确保日志目录存在
const logDir = path.join(__dirname, "logs");
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}

// 1. 配置 winston(业务日志)
const businessLogger = winston.createLogger({
level: process.env.NODE_ENV === "production" ? "info" : "debug",
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
// 控制台输出(开发环境)
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
}),
// 按日期轮转的文件输出(生产环境)
new DailyRotateFile({
filename: path.join(logDir, "business-%DATE%.log"),
datePattern: "YYYY-MM-DD",
maxSize: "20m", // 单个文件最大20MB
maxFiles: "14d", // 保留14天日志
}),
],
});

// 2. 配置 morgan(HTTP 请求日志)
// 创建 HTTP 日志的输出流(接入 winston)
const httpLogStream = winston
.createLogger({
transports: [
new DailyRotateFile({
filename: path.join(logDir, "http-%DATE%.log"),
datePattern: "YYYY-MM-DD",
maxSize: "20m",
maxFiles: "14d",
}),
],
})
.stream({ level: "info" });

// morgan 中间件(格式化 HTTP 日志)
const httpLogger = morgan("combined", { stream: httpLogStream });

module.exports = {
businessLogger, // 业务日志实例
httpLogger, // HTTP 日志中间件
};

3.在 Express 中使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const express = require("express");
const { businessLogger, httpLogger } = require("./logger");

const app = express();

// 应用 HTTP 日志中间件
app.use(httpLogger);

// 业务逻辑示例
app.get("/", (req, res) => {
businessLogger.info("用户访问首页", { userAgent: req.headers["user-agent"] });
res.send("Hello World");
});

app.get("/error", (req, res) => {
try {
throw new Error("模拟错误");
} catch (err) {
businessLogger.error("发生错误", {
message: err.message,
stack: err.stack,
});
res.status(500).send("服务器错误");
}
});

app.listen(3000, () => {
businessLogger.info("服务器启动", { port: 3000, env: process.env.NODE_ENV });
});

方案优势

  • 职责分离:morgan 专注 HTTP 细节,winston 处理业务逻辑,日志结构更清晰。
  • 环境适配:开发环境日志输出到控制台(带颜色),生产环境自动轮转文件(避免磁盘占满)。
  • 可扩展性:winston 支持对接 Elasticsearch、Sentry 等工具,便于日志分析和告警。
  • 易用性:无需重复造轮子,现有中间件和工具链成熟稳定。