You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用morgan与rotating-file-stream时1d间隔日志轮转功能异常

问题根源

你遇到的日志文件名和内容日期不匹配、轮转不符合预期的问题,核心是时区不一致和文件名生成逻辑不规范两个原因导致的:

  1. 日志内容里的日期是morgan默认输出的UTC时间(你可以看到每条日志末尾的+0000标识),但你生成文件名时用date-fns的format方法默认读取服务器本地时区的日期,两者时区偏差会导致日期差1天
  2. 你自定义的logFilename函数没有接收rotating-file-stream传入的轮转时间参数,而是自行创建new Date()取当前时间,极端情况下会出现毫秒级的跨天偏差,也可能导致文件名和轮转时间不匹配

修复方案

修改后的完整代码如下:

const morgan = require('morgan');
const rfs = require('rotating-file-stream');
const path = require('path');
// 引入formatUTC代替默认的format,统一用UTC时区生成文件名
const { formatUTC } = require('date-fns');

// 接收rfs传入的轮转时间参数,用该时间生成对应文件名
function logFilename(time) {
  const targetTime = time || new Date();
  return `${formatUTC(targetTime, 'yyyy-MM-dd')}-access.log`;
}

const accessLogStream = rfs.createStream(logFilename, {
  interval: '1d',
  path: path.resolve(__dirname, '..', 'log'),
  // 强制按UTC时区的天边界轮转,和日志内容的时区对齐
  utc: true,
  // 开启严格边界模式,确保轮转只在天的起始时刻触发
  boundary: true
});

morgan.token('ip', (req) => req.headers['x-forwarded-for'] || req.connection.remoteAddress);

morgan.token('user', (req) => {
  if (req.user) return req.user;
  return '-';
});

module.exports = morgan(':ip ":user" [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"', { stream: accessLogStream });

验证逻辑

修改后你可以观察到:

  • UTC时间每天0点会自动触发轮转
  • 日志文件名的日期和文件内日志的[date[clf]]日期完全对应
  • 不会再出现跨天日志写入同一个旧文件的问题

内容的提问来源于stack exchange,提问作者felixleo22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 02:48:00