正在加载文档...
文档内容较大,正在处理中,请稍候
正在加载文档...
文档内容较大,正在处理中,请稍候
本文档详细说明了后端服务实现的日志管理模块,涵盖日志级别、模块级别控制、结构化输出、敏感信息脱敏、自动轮转、请求追踪等核心功能,以及日志使用、最佳实践、常见问题等内容,确保系统的可观测性和可维护性。
日志管理模块是后端服务的核心组件,提供了统一的日志记录功能,支持:
日志是系统运维和问题排查的重要工具:
const { getLogger } = require("../logger");
const logger = getLogger("controllers.userController");// 业务操作成功
logger.info("用户创建成功", { userId: 123 });
// 错误异常
logger.error("用户创建失败", { error: err, payload: req.body });
// 调试信息
logger.debug("获取用户列表", { page, limit, filters });
// 警告信息
logger.warn("访问次数超过限制", { userIp, accessCount });const { createRequestLogger, createErrorLogger } = require("../logger");
const requestIdMiddleware = require("../middlewares/requestIdMiddleware");
// 请求 ID 中间件(必须最先使用)
app.use(requestIdMiddleware);
// 请求日志中间件
app.use(createRequestLogger({ moduleName: "http", logBody: true }));
// 错误日志中间件(放在路由之后)
app.use(createErrorLogger("error"));恭喜! 你已经掌握了日志的基本使用。接下来让我们深入了解各个概念。
日志模块支持四个日志级别,按优先级从高到低:
| 级别 | 优先级 | 使用场景 | 示例 |
|---|---|---|---|
| ERROR | 3 | 错误异常,需要立即处理 | 系统错误、数据库查询失败 |
| WARN | 2 | 警告信息,需要关注但不影响主流程 | 权限不足、访问限制、慢请求 |
| INFO | 1 | 业务操作成功和关键流程节点 | 用户创建成功、登录成功 |
| DEBUG | 0 | 调试信息、缓存操作、查询操作 | 缓存命中、查询参数、内部状态 |
DEBUG - 调试信息、缓存操作、查询操作
// ✅ 正确使用
logger.debug("缓存命中", { cacheKey });
logger.debug("从缓存获取用户列表", { page, limit });
logger.debug("获取用户列表参数", { page, limit, filters });
// ❌ 错误使用
logger.info("缓存命中", { cacheKey }); // 应该用 debug
logger.debug("用户创建成功", { userId }); // 应该用 infoINFO - 业务操作成功、关键流程节点
// ✅ 正确使用
logger.info("用户创建成功", { userId: 123 });
logger.info("用户更新成功", { userId: 123 });
logger.info("文件上传成功", { userId, filename });
logger.info("SSE连接已建立", { userId });
// ❌ 错误使用
logger.debug("用户创建成功", { userId }); // 应该用 info
logger.info("获取用户列表", { list }); // 查询操作应该用 debug,且不要记录完整列表WARN - 警告信息,不影响主流程
// ✅ 正确使用
logger.warn("访问次数超过限制", { userIp, accessCount });
logger.warn("权限不足", { currentUserId, targetUserId });
logger.warn("请求慢响应", { duration: 1500, url: "/api/users" });
// ❌ 错误使用
logger.error("访问次数超过限制", { userIp }); // 应该用 warn
logger.info("权限不足", { userId }); // 应该用 warnERROR - 错误异常,需要立即处理
// ✅ 正确使用
logger.error("获取用户列表失败", { error: err });
logger.error("用户创建失败", { error: err, payload: req.body });
logger.error("数据库查询失败", { error: err, sql });
// ❌ 错误使用
logger.warn("用户创建失败", { error: err }); // 应该用 error
logger.error("访问次数超过限制", { userIp }); // 应该用 warn模块级别控制允许为不同的模块设置不同的日志级别,实现精细化的日志管理。
全局日志级别(上限)
↓
模块日志级别(可以更严格,但不能更宽松)
↓
最终有效级别 = max(全局级别, 模块级别)// config/base/logger.js
const MODULE_LOG_LEVELS = {
default: "info", // 默认级别
database: "warn", // 数据库模块:只记录警告和错误
api: "info", // API模块:记录信息、警告和错误
auth: "debug", // 认证模块:记录所有日志(但受全局限制)
cache: "warn", // 缓存模块:只记录警告和错误
};系统会自动将模块名称映射到配置键:
精确匹配(最高优先级):
infra.dbClient → databasecontrollers.authController → authcache.redisCache → cache前缀匹配:
models.* → databasecontrollers.* → apiroutes.* → apimiddlewares.* → api默认匹配:
default 配置| 全局级别 | 模块级别 | 有效级别 | 说明 |
|---|---|---|---|
info |
debug |
info |
模块不能比全局更宽松 |
info |
warn |
warn |
模块可以更严格 |
warn |
debug |
warn |
模块不能比全局更宽松 |
warn |
error |
error |
模块可以更严格 |
debug |
warn |
warn |
模块可以更严格 |
日志以 JSON 格式输出,包含以下字段:
{
"timestamp": "2025-12-10T10:00:00.000Z",
"level": "info",
"message": "用户创建成功",
"app_id": "node-express-mysql",
"service_name": "api-service",
"environment": "production",
"correlation_id": "uuid-v4-string",
"module": "controllers.userController",
"file": "userController.js",
"line": 123,
"function": "createUser",
"meta": {
"userId": 123,
"username": "testuser"
}
}日志模块自动对敏感信息进行脱敏处理,保护用户隐私。
| 字段类型 | 脱敏方式 | 示例 |
|---|---|---|
| password | 完全脱敏 | password123 → *** |
| token | 完全脱敏 | abc123 → *** |
| 邮箱脱敏 | user@example.com → us***@example.com |
|
| phone | 中间脱敏 | 13812345678 → 138****5678 |
| idCard | 中间脱敏 | 110101199001011234 → 110101********1234 |
| bankCard | 中间脱敏 | 6222021234567890 → 6222********7890 |
所有通过 logger 记录的日志都会自动脱敏:
logger.info("用户登录", {
username: "testuser",
password: "secret123", // 自动脱敏为 ***
email: "user@example.com", // 自动脱敏为 us***@example.com
phone: "13812345678", // 自动脱敏为 138****5678
});const { getLogger } = require("../logger");
// 为当前模块创建 logger 实例
const logger = getLogger("controllers.userController");为了确保模块级别日志配置生效,请遵循以下命名规范:
controllers.{ControllerName}models.{ModelName}routes.{RouteName}middlewares.{MiddlewareName}services.{ServiceName}infra.{ClientName}cache.{CacheName}// 缓存操作
logger.debug("缓存命中", { cacheKey: "user:123" });
logger.debug("缓存未命中", { cacheKey: "user:123" });
// 查询操作
logger.debug("获取用户列表", { page: 1, limit: 10, filters: { username: "test" } });
// 内部状态
logger.debug("初始化缓存服务", { provider: "RedisCache" });// 业务操作成功
logger.info("用户创建成功", { userId: 123, username: "testuser" });
logger.info("用户更新成功", { userId: 123 });
logger.info("用户删除成功", { userId: 123 });
// 关键流程节点
logger.info("用户登录成功", { userId: 123 });
logger.info("文件上传成功", { userId: 123, filename: "avatar.jpg" });
logger.info("SSE连接已建立", { userId: 123 });// 警告信息
logger.warn("访问次数超过限制", { userIp: "192.168.1.1", accessCount: 100 });
logger.warn("权限不足", { currentUserId: 123, targetUserId: 456 });
logger.warn("请求慢响应", { duration: 1500, url: "/api/users" });// 错误异常
logger.error("获取用户列表失败", { error: err });
logger.error("用户创建失败", { error: err, payload: req.body });
logger.error("数据库查询失败", { error: err, sql: "SELECT * FROM users" });何时使用 DEBUG:
何时使用 INFO:
何时使用 WARN:
何时使用 ERROR:
// ❌ 错误:记录完整列表数据
logger.debug("获取用户列表", { list: users }); // 列表可能很大
// ✅ 正确:只记录关键信息
logger.debug("获取用户列表", { page: 1, limit: 10, total: 100 });
// ❌ 错误:记录完整缓存数据
logger.debug("缓存命中", { cacheData: largeObject });
// ✅ 正确:只记录缓存键
logger.debug("缓存命中", { cacheKey: "user:123" });请求日志中间件自动记录所有 HTTP 请求的详细信息。
const { createRequestLogger } = require("../logger");
// 创建请求日志中间件
app.use(
createRequestLogger({
moduleName: "http",
logBody: true, // 是否记录请求体(默认 true)
logHeaders: false, // 是否记录请求头(默认 false)
})
);"http")true,GET 请求不记录)false)中间件会根据响应状态码和响应时间自动选择日志级别:
{
"level": "debug",
"message": "请求完成",
"method": "POST",
"url": "/api/users",
"status_code": 200,
"duration_ms": 150,
"response_size": 1024,
"response_time_category": "normal",
"ip": "192.168.1.1",
"userId": "123",
"params": {},
"query": {},
"body": { "username": "testuser" }
}错误日志中间件自动捕获和处理所有未处理的错误。
const { createErrorLogger } = require("../logger");
// 创建错误日志中间件(放在路由之后)
app.use(createErrorLogger("error"));{
"level": "error",
"message": "Error occurred during request processing",
"method": "POST",
"url": "/api/users",
"ip": "192.168.1.1",
"userId": "123",
"errorName": "ValidationError",
"errorMessage": "用户名不能为空",
"errorStack": "Error: 用户名不能为空\n at ...",
"statusCode": 400
}请求 ID 追踪用于跨服务/请求的关联追踪。
const requestIdMiddleware = require("../middlewares/requestIdMiddleware");
// 请求 ID 中间件(必须最先使用)
app.use(requestIdMiddleware);X-Correlation-ID(如果存在)req.correlationId 和 global.correlationIdX-Correlation-ID// 服务 A 发起请求
const correlationId = req.correlationId;
fetch("http://service-b/api/data", {
headers: {
"X-Correlation-ID": correlationId, // 传递 correlation_id
},
});
// 服务 B 接收请求
// 自动从请求头获取 correlation_id,所有日志都会包含相同的 correlation_id
logger.info("处理请求", { correlationId: req.correlationId });可以在运行时动态调整日志级别。
const { setGlobalLogLevel } = require("../logger");
// 设置全局日志级别
setGlobalLogLevel("warn"); // 只记录警告和错误const { setModuleLogLevel } = require("../logger");
// 设置特定模块的日志级别
setModuleLogLevel("controllers.userController", "debug");
setModuleLogLevel("models.userModel", "warn");src/logger/
├── index.js # 入口文件,导出所有功能
├── enhanced-logger.js # 增强日志(模块级别控制、调用方信息)
├── logger-core.js # 核心功能(写盘、轮转、格式化)
├── data-masker.js # 敏感信息脱敏
└── utils.js # 工具函数(目录创建、ID生成等)应用代码
↓
getLogger(moduleName)
↓
logger.debug/info/warn/error()
↓
shouldLog() 检查级别
↓
logger-core.log() 格式化
↓
data-masker.maskObject() 脱敏
↓
writeLogToFile() 写入文件
↓
checkLogRotation() 检查轮转当日志文件大小超过 10MB 时,自动进行轮转:
logs/output/2025-12-10.log (当前文件,10MB)
↓ 超过大小限制
logs/output/2025-12-10.log.1 (备份1)
logs/output/2025-12-10.log.2 (备份2)
...
logs/output/2025-12-10.log.5 (备份5,最旧的会被删除)// config/base/logger.js
const MAX_LOG_SIZE = 10 * 1024 * 1024; // 10MB
const LOG_BACKUPS = 5; // 保留5个备份文件配置文件位置:config/base/logger.js
module.exports = {
// 日志目录
LOG_DIR: "./logs",
ERROR_LOG_DIR: "./logs/error",
OUTPUT_LOG_DIR: "./logs/output",
// 默认日志级别
DEFAULT_LOG_LEVEL: "info",
// 文件配置
MAX_LOG_SIZE: 10 * 1024 * 1024, // 10MB
LOG_BACKUPS: 5, // 保留5个备份
// 性能监控
SLOW_REQUEST_THRESHOLD: 1000, // 1秒
};const MODULE_LOG_LEVELS = {
default: "info", // 默认级别
database: "warn", // 数据库模块
api: "info", // API模块
auth: "debug", // 认证模块(受全局限制)
cache: "warn", // 缓存模块
};const SENSITIZATION_CONFIG = {
enabled: true, // 全局脱敏开关
rules: [
{
enabled: true,
pattern: /"password":"([^"]*)"/g,
replace: '"password":"******"',
},
// ... 其他规则
],
};原因:
解决:
ls -la ./logschmod -R 755 ./logsdf -h原因:
解决:
原因:
解决:
SENSITIZATION_CONFIG.enabled 是否为 true原因:
解决:
方法:
tail -f ./logs/error/2025-12-10.logtail -f ./logs/output/2025-12-10.loggrep "用户创建" ./logs/output/2025-12-10.loggrep "correlation_id.*abc123" ./logs/output/2025-12-10.log日志是个好东西