RotatingFileHandler未按天切分是因为默认按大小轮转,需显式设maxFileSize=0、配置filenameFormat含{date}、指定maxFiles三者缺一不可,否则{date}无效导致假轮转。

RotatingFileHandler 为什么没按天切分
Hyperf 的 RotatingFileHandler 默认按文件大小轮转,不是按日期。如果你在 logger.php 里只改了 filenameFormat 加上 {date},但没禁用大小限制,就会出现「文件名带日期、内容却混在旧文件里」的假轮转现象。
根本原因是:maxFileSize 没被显式设为 0 或删掉。只要这个值存在(哪怕设成 1024),Handler 就优先按大小切,完全忽略 {date} 占位符。
- 检查
config/autoload/logger.php中对应 channel 的handler配置项,确认没有'maxFileSize' => ...这一行 - 若存在,直接删除;或显式写成
'maxFileSize' => 0 -
filename字段只能是基础路径(如BASE_PATH . '/runtime/logs/access.log'),不能含{date}—— 那是filenameFormat的事
按天切分必须配齐的三个参数
只换 Handler 类型不够,RotatingFileHandler 的行为由三个配置联合决定:日期模板、保留数量、是否关闭大小触发。缺一不可。
-
'class' => Monolog\Handler\RotatingFileHandler::class:必须写全命名空间,拼错就 fallback 到 StreamHandler -
'filenameFormat' => 'access-{date}.log':{date} 会被自动替换为Y-m-d格式,例如access-2026-10-19.log -
'maxFiles' => 30:表示最多保留 30 个日期文件,超出的自动unlink;注意这不是「30 天」,而是「30 个文件」
多通道日志切分失效的常见原因
Hyperf 日志工厂通过 $loggerFactory->get('access', 'access') 获取 logger,第一个参数是 channel 名(用于上下文标识),第二个参数才是配置键名。两者不一致,就会 fallback 到 default 配置,导致切分逻辑完全不生效。
- 定义了
'channels' => ['access' => [...]],就必须用get('access', 'access') - 不能写成
get('access', 'file')或get('file', 'access') - 如果想复用同一套 handler 配置但输出到不同路径,应复制整个 channel 配置块,改
filename和filenameFormat,不要共用键名
Kratos 项目里怎么接入 RotatingFileHandler
Kratos 自身不内置 RotatingFileHandler,它依赖 Monolog。你得手动把 Hyperf 的日志方案迁进来,但要注意初始化时机和 Logger 实例绑定方式。
- 在
cmd/xxx/main.go初始化 App 前,先调用log.SetLogger()注入自定义 Logger 实例 - 构造
Monolog\Handler\RotatingFileHandler时,传入的$filename必须是不含{date}的基础路径 - 确保
RotatingFileHandler的$maxFiles和$fileNameFormat参数在构造时正确传入,不是靠 config 数组后期覆盖 - 别用
log.With()包装后再传给 RotatingFileHandler —— 它只接受原始LoggerInterface,包装后类型不匹配会 panic
maxFileSize 必须消失或为 0,且 filenameFormat 必须显式声明——这两项不满足,{date} 就只是个摆设。**











