插件窝 干货文章 Node.js日志轮转策略如何设置

Node.js日志轮转策略如何设置

日志 轮转 const logrotate 103    来源:    2025-05-07

Node.js 日志轮转策略设置指南

日志轮转是管理应用程序日志的重要策略,可以防止日志文件无限增长占用磁盘空间。以下是几种在Node.js中实现日志轮转的方法:

1. 使用logrotate(Linux系统)

对于生产环境,推荐使用系统级的logrotate工具:

# /etc/logrotate.d/your-node-app
/path/to/your/node/app/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 root root
    sharedscripts
    postrotate
        kill -USR2 `cat /path/to/your/node/app.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

2. 使用Node.js日志库内置轮转功能

winston日志库

const winston = require('winston');
const { createLogger, format, transports } = winston;

const logger = createLogger({
  format: format.combine(
    format.timestamp(),
    format.json()
  ),
  transports: [
    new transports.File({
      filename: 'application.log',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      tailable: true
    })
  ]
});

log4js日志库

const log4js = require('log4js');

log4js.configure({
  appenders: {
    file: {
      type: 'file',
      filename: 'application.log',
      maxLogSize: 10485760, // 10MB
      backups: 5, // 保留5个备份
      compress: true // 压缩旧日志
    }
  },
  categories: {
    default: { appenders: ['file'], level: 'info' }
  }
});

const logger = log4js.getLogger();

3. 使用PM2的日志管理

如果你使用PM2管理Node.js进程:

# 安装PM2日志轮转模块
pm2 install pm2-logrotate

# 配置轮转参数
pm2 set pm2-logrotate:max_size 10M  # 单个日志文件最大10MB
pm2 set pm2-logrotate:retain 30     # 保留30个日志文件
pm2 set pm2-logrotate:compress true # 压缩旧日志
pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # 每天午夜轮转

4. 自定义轮转脚本

如果需要更精细的控制,可以编写自定义轮转脚本:

const fs = require('fs');
const path = require('path');
const zlib = require('zlib');

function rotateLog(logPath, maxFiles = 5) {
  const logDir = path.dirname(logPath);
  const logBase = path.basename(logPath, '.log');

  // 压缩当前日志文件
  if (fs.existsSync(logPath)) {
    const date = new Date().toISOString().replace(/[:.]/g, '-');
    const compressedPath = path.join(logDir, `${logBase}-${date}.log.gz`);

    const input = fs.createReadStream(logPath);
    const output = fs.createWriteStream(compressedPath);
    const compress = zlib.createGzip();

    input.pipe(compress).pipe(output).on('finish', () => {
      fs.unlinkSync(logPath);
      cleanupOldLogs(logDir, logBase, maxFiles);
    });
  }
}

function cleanupOldLogs(logDir, logBase, maxFiles) {
  fs.readdir(logDir, (err, files) => {
    if (err) return;

    const logFiles = files
      .filter(file => file.startsWith(logBase) && file.endsWith('.gz'))
      .sort()
      .reverse();

    logFiles.slice(maxFiles).forEach(file => {
      fs.unlinkSync(path.join(logDir, file));
    });
  });
}

// 每天午夜执行轮转
setInterval(() => {
  const now = new Date();
  if (now.getHours() === 0 && now.getMinutes() === 0) {
    rotateLog('/var/log/myapp/application.log', 7);
  }
}, 60000); // 每分钟检查一次

最佳实践建议

  1. 日志级别分离:将不同级别的日志(error、info、debug)分开存储
  2. 合理设置轮转大小:根据应用日志量和磁盘空间设置适当的大小
  3. 保留足够的历史日志:通常保留7-30天的日志
  4. 考虑日志压缩:可以显著节省磁盘空间
  5. 监控日志增长:设置警报以防日志异常增长

选择哪种方法取决于你的具体需求、部署环境和运维策略。生产环境通常推荐结合系统工具(如logrotate)和应用程序级日志管理。