应替换为支持gzip压缩的Monolog RotatingFileHandler并关闭数据库debug开关。需安装monolog/monolog,注册自定义handler,启用gzip压缩,设置冷热分离逻辑,且必须关闭app_debug与database.debug以根治日志膨胀。

日志文件体积爆炸,thinkphp.log 单日超 500MB 怎么办
直接删或轮转不是根治办法——ThinkPHP 默认用 FileHandler 写纯文本,没压缩、没分层、没生命周期管理。关键在改写日志驱动,而不是调 setLogLevel 或改 max_files。
- 默认
FileHandler不支持 gzip,每次写入都是明文追加,重复字段(如时间戳、IP、trace_id)大量冗余 -
log.file_format里混着调试信息和 SQL 日志,生产环境根本不需要全量保留 - 冷数据(7 天前)仍占磁盘且被频繁扫描,影响
log:list和备份效率
替换为支持压缩的 RotatingFileHandler(需手动集成)
ThinkPHP 原生不带带压缩的轮转 handler,得用 monolog/monolog 的 RotatingFileHandler + 自定义 GzipProcessor 替换默认驱动。
- 安装:
composer require monolog/monolog,别用 TP 自带的think-log - 在
app/common.php或日志初始化处注册新 handler,注意关闭FileHandler的自动创建逻辑,否则会双写 -
RotatingFileHandler的$maxFiles参数是「保留多少个归档」,不是「单文件大小上限」;真正控制体积靠$filenameFormat+gzip后缀 - 示例关键行:
new RotatingFileHandler('runtime/log/app.log', 30, Logger::INFO, true, 0644, true)—— 最后一个true表示启用 gzip 压缩
冷热分离:把 7 天外日志自动迁到 archive/ 并压缩
Monolog 的轮转只管滚动,不管归档路径。要实现冷热分离,必须在日志关闭前钩住归档动作,用 rename() + gzencode() 搬移旧文件。
- 监听
Logger::close()或在App::after()中扫描runtime/log/*.log.1等旧文件 - 匹配正则
/\.log\.(\d+)$/,提取序号判断是否 ≥7;满足则gzencode(file_get_contents($old))写入runtime/log/archive/app_20240501.log.gz - 注意权限:Web 进程可能无权写
archive/目录,提前mkdir -m 755 runtime/log/archive - 别用
exec('gzip')—— 容器环境常禁用 shell,且跨平台不稳
SQL 日志和调试日志必须关掉,否则压缩也救不了
90% 的体积来自 sql 和 debug 级别日志,尤其开启 db.debug = true 后,每条查询都带完整 trace 和参数 dump。
立即学习“PHP免费学习笔记(深入)”;
- 生产环境务必确认
app_debug = false,且database.debug = false—— 这俩开关独立生效 -
log.level设为warning或error,别留info;info会记路由匹配、中间件执行等高频事件 - 如果真要查 SQL,用
Db::getLastSql()配合条件打点,而不是全局开日志 - 检查
config/log.php里有没有手写的'sql' => 'info'这类覆盖配置
压缩和分离能压掉 70% 存储,但前提是先砍掉日志源头发射量。最常被忽略的是数据库 debug 开关——它开着的时候,哪怕你把日志全塞进 .tar.zst,也没用。



















