Node系列 · ORM:log4js 日志记录

Node系列 · ORM:log4js 日志记录

生产环境不能用 console.log------它没法分级别、没法分类、没法按大小切分文件、没法自动清理。本章讲清楚 log4js 的核心概念和按环境配置的实战。

一、为什么不用 console.log

维度 console.log log4js
级别控制 ✅ trace / debug / info / warn / error / fatal
分类 ✅ category(按模块拆分日志)
输出目标 仅 stdout ✅ 控制台 / 文件 / 网络 / 数据库
文件切分 ✅ 按大小 / 日期
自动清理 log4js 自动管理
性能 阻塞 stdout 异步缓冲,不阻塞事件循环

::: tip

console.log 永远不是生产日志方案 。它没法分类、没法分级、还会在高并发下阻塞事件循环(stdout 同步写入)。

:::

二、log4js 三大核心概念

2.1 级别(level)

从低到高:

级别 用途
trace 最详细的调试信息(一般关闭)
debug 调试信息
info 正常运行日志
warn 警告(潜在问题)
error 错误(功能受影响)
fatal 致命(进程退出)

设置 level: 'warn' 后,只有 warn / error / fatal 会输出。

2.2 分类(category)

按模块 / 功能划分的日志命名空间:

javascript:log4js-basic.js 复制代码
log4js.getLogger('http');    // HTTP 请求日志
log4js.getLogger('db');      // 数据库日志
log4js.getLogger('user');    // 用户模块日志
log4js.getLogger('default'); // 默认日志(不分类时用)

每个 category 可以单独配置级别和输出目标。

2.3 输出源(appender)

日志写到哪里:

appender 类型 输出目标
console 控制台 stdout / stderr
file 单个文件
dateFile 按日期切分(如 app.2024-08-15.log
fileSync 同步写文件(启动期用)
tcp 远程日志服务器
gelf Graylog 扩展日志格式

每个 appender 还可指定 layout(输出格式):

layout 格式
pattern 自定义模板字符串
colored 带 ANSI 颜色(开发用)
json JSON 格式(机器解析)

三、安装与基础使用

bash 复制代码
npm install log4js
javascript:log4js-basic.js 复制代码
const log4js = require('log4js');

log4js.configure({
  appenders: { console: { type: 'console' } },
  categories: { default: { appenders: ['console'], level: 'info' } },
});

const logger = log4js.getLogger();

logger.info('服务启动');
logger.warn('配置项缺失');
logger.error('请求失败', err);
bash 复制代码
$ node app.js
[2024-08-15T14:30:00.000] [INFO] default - 服务启动

四、按环境配置

4.1 配置代码

javascript:log4js-config.js 复制代码
const path = require('path');
const log4js = require('log4js');

const isDev = process.env.NODE_ENV !== 'production';

log4js.configure({
  appenders: {
    // 控制台:开发期彩色
    consoleOut: {
      type: 'console',
      layout: { type: 'colored' },
    },
    // 按日期切分文件
    appFile: {
      type: 'dateFile',
      filename: path.join('logs', 'app.log'),
      pattern: 'yyyy-MM-dd',
      // 文件名格式:app.2024-08-15.log
      compress: true,
    },
    // 错误单独一个文件
    errorFile: {
      type: 'file',
      filename: path.join('logs', 'error.log'),
      // 旧文件超 10MB 自动备份
      maxLogSize: 10 * 1024 * 1024,
      backups: 5,
    },
  },
  categories: {
    default: {
      appenders: isDev ? ['consoleOut'] : ['appFile', 'errorFile'],
      level: isDev ? 'debug' : 'info',
    },
    http: {
      appenders: ['appFile'],
      level: 'info',
    },
    db: {
      appenders: ['appFile'],
      level: 'warn',
    },
  },
});

module.exports = log4js;

4.2 各级别模块用不同 logger

javascript:use-categories.js 复制代码
const log4js = require('log4js');

const httpLogger = log4js.getLogger('http');
const dbLogger = log4js.getLogger('db');

httpLogger.info('GET /api/users 200');
dbLogger.warn('慢查询:耗时 1200ms');

五、Express 中间件

log4js 提供 Express 中间件自动记录请求:

javascript:express-middleware.js 复制代码
const log4js = require('log4js');
const express = require('express');

const app = express();

// 自动记录每个 HTTP 请求
app.use(log4js.connectLogger(log4js.getLogger('http'), {
  level: 'auto',                    // 5xx → error,4xx → warn,其他 → info
  format: (req, res, format) => format(
    ':remote-addr - :method :url :status :res[content-length] - :response-time ms'
  ),
}));

app.get('/api/users', (req, res) => {
  res.json({ users: [] });
});

输出示例:

复制代码
[INFO] http - 127.0.0.1 - GET /api/users 200 42 - 12 ms
[ERROR] http - 127.0.0.1 - POST /api/users 500 89 - 234 ms

六、关闭与刷新

javascript:shutdown.js 复制代码
// 应用退出前优雅关闭
process.on('SIGTERM', () => {
  log4js.shutdown(() => {
    console.log('日志系统已关闭');
    process.exit(0);
  });
});

shutdown() 等待所有缓冲日志写完再回调------避免最后几条日志丢失。

七、配置模板

javascript:log4js-template.js 复制代码
// config/log4js.js
const path = require('path');
const log4js = require('log4js');

const LOG_DIR = path.resolve(__dirname, '../logs');
const isDev = process.env.NODE_ENV !== 'production';

log4js.configure({
  appenders: {
    // 开发期:控制台彩色输出
    devConsole: {
      type: 'console',
      layout: { type: 'colored' },
    },
    // 生产期:分文件 + 错误单独
    prodAll: {
      type: 'dateFile',
      filename: path.join(LOG_DIR, 'app.log'),
      pattern: 'yyyy-MM-dd',
      compress: true,
    },
    prodError: {
      type: 'levelFilter',
      // level: 'error' 之后的级别都写这个文件
      appender: {
        type: 'file',
        filename: path.join(LOG_DIR, 'error.log'),
        maxLogSize: 10 * 1024 * 1024,
        backups: 5,
      },
      level: 'error',
    },
  },
  categories: {
    default: {
      appenders: isDev ? ['devConsole'] : ['prodAll', 'prodError'],
      level: isDev ? 'debug' : 'info',
    },
    http: {
      appenders: isDev ? ['devConsole'] : ['prodAll'],
      level: 'info',
    },
    db: {
      appenders: isDev ? ['devConsole'] : ['prodAll'],
      level: 'warn',
    },
  },
});

module.exports = log4js;

八、最佳实践

场景 推荐
开发期 控制台 + level: 'debug'
生产期 文件 + 错误单独 + level: 'info'
HTTP 请求 connectLogger 自动记录
慢查询 / 错误 单独 category + level: 'warn'
敏感字段 日志前脱敏(密码、token、手机号中间四位)
应用退出 log4js.shutdown 刷写缓冲
文件清理 dateFile + compress: true 自动管理

::: warning

永远不要把密码、token、完整手机号、身份证号写日志。即使是错误日志,也要先脱敏:

javascript:log4js-template.js 复制代码
logger.info('登录失败', { email: user.email, ip: req.ip });
// ❌ logger.info('登录失败', { password });  // 永远不要

:::

九、与其他日志库对比

风格 性能 适合
log4js 配置式 中(同步阻塞风险用 stream 解决) 传统项目 / 文件输出
pino JSON 输出 极快(异步) 性能敏感 / 日志聚合
winston 配置式 老牌项目
bunyan JSON 输出 微服务 / 日志聚合

::: tip

新项目推荐 pino ------JSON 输出 + 异步 = 不阻塞事件循环 + 易聚合到 ELK / Loki。但 log4js 在国内中小项目里依然主流,本文按 log4js 展开。

:::

十、小结

  • 生产环境永远用日志库,不用 console.log
  • 三大核心:level(级别)/ category(分类)/ appender(输出源)
  • dateFile appender 按日期切分日志;file + maxLogSize 按大小
  • 按环境配置:开发期控制台 + debug;生产期文件 + info
  • Express 用 connectLogger 自动记录请求日志
  • 敏感字段永远不写日志(密码、token 等)
  • 应用退出前 log4js.shutdown() 刷写缓冲
相关推荐
李昊哲小课32 分钟前
Spring Boot 4 旅游主题实战教程 阶段四:缓存与底层进阶
spring boot·redis·缓存·性能优化·log4j·旅游·性能
秋秋小事7 小时前
node 导入与导出
node.js
秋秋小事8 小时前
node event模块
node.js
晴天168 小时前
Node.js 中 `npm install` 命令分析-Day30
前端·npm·node.js
晴天168 小时前
VS Code `launch.json` 指南(Node.js版)-Day30
node.js·json
李昊哲小课1 天前
SpringBoot4 云端咖啡站 阶段五:交付与进阶
人工智能·spring boot·大模型·log4j·智能体
空の鱼1 天前
Mac 上 Node 版本管理(brew + nvm 共存方案)
macos·node.js
请你吃div1 天前
Node 后端项目 Docker 自动部署教程(GitHub + 宝塔 + Self-hosted Runner)
后端·docker·node.js
泠曦れいひ1 天前
在当前项目中安装Vite
前端框架·npm·node.js