node 日志工具
在 Node.js 项目中,日志记录是至关重要的一环,它能帮助开发者追踪系统运行状态、排查错误、分析用户行为等。下面将从日志的作用、常用工具、实现方式及最佳实践等方面,详细介绍 Node.js 项目的日志记录。
日志的作用
- 错误排查:当程序出现异常时,日志可以提供错误发生的上下文、堆栈信息等,帮助快速定位问题。
- 系统监控:通过记录系统的关键指标(如响应时间、内存占用等),可以实时监控系统运行状态,及时发现潜在风险。
- 行为分析:记录用户的操作行为(如登录、点击等),有助于分析用户习惯,为产品优化提供依据。
- 审计追踪:在一些对安全性要求较高的场景(如金融系统),日志可以用于审计用户操作,确保合规性。
常用的日志工具
- 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", format: winston.format.combine( winston.format.timestamp(), winston.format.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("这是一个信息日志");
|
- 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("信息内容");
|
- 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();
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"); });
|
- log4js
log4js 是 Node.js 生态中一款功能丰富的日志管理工具,灵感源自 Java 的 log4j,提供了灵活的日志配置、多种输出方式和分级管理能力,广泛应用于各类 Node.js 项目中。
核心特性
- 多输出目标(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); }
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", maxFiles: "14d", }), ], });
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" });
const httpLogger = morgan("combined", { stream: httpLogStream });
module.exports = { businessLogger, httpLogger, };
|
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();
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 等工具,便于日志分析和告警。
- 易用性:无需重复造轮子,现有中间件和工具链成熟稳定。