daily驱动必须设'lock'=>false防文件锁争用、'permission'=>0664减chmod开销、formatter禁用Request::ip()等动态调用,并配'max_files'=>30防单文件过大。

直接配错 config/logging.php 里的 daily 驱动参数,会导致日志写入变慢、并发下文件锁争用、甚至部分请求卡住——这不是小概率事件,而是高并发 Laravel 应用上线后最常见的日志性能故障点。
daily 驱动必须显式关掉 lock
默认 daily 驱动启用 'lock' => true,每次写日志都调 flock() 加独占锁。50+ QPS 场景下,flock() 就成瓶颈,strace 能看到大量 F_SETLK 等待。
- 务必在对应 channel 配置里加
'lock' => false - 关锁后日志行可能交错(如两行合并成一行),但只要不依赖单行原子性(比如日志分析脚本不靠行号定位),这是可接受的权衡
- 若业务强依赖顺序,别硬扛文件锁,改用
stack+single配合syslog或外部服务
permission 设错会让日志写入变慢
Linux 下每次变更文件权限,内核都要走一遍 ACL 检查路径。permission => 0644 是安全但低效的,尤其当 storage/logs/ 目录属主和 Web 进程 UID 不一致时,每次写日志都会触发 chmod() 调用。
- 生产环境统一设为
'permission' => 0664 - 确保
storage/logs/目录属组可写:chgrp www-data storage/logs - 容器部署时,在
Dockerfile里加RUN chmod -R g+w storage/logs,避免运行时反复chmod - 绝对不要设
0777,会触发 SELinux/AppArmor 额外检查,反而更慢
formatter 里别调用 Request::ip() 这类动态方法
自定义 Formatter 类里,每条日志都执行 Request::ip() 或 Request::fullUrl(),等于在日志路径上塞了个数据库查询级开销——它要重建整个请求上下文,哪怕只是拿个 IP。
- IP 和 URL 这类字段,应在中间件里提前提取并存到
$request->attributes,formatter只读取已缓存值 - 时间格式用
'Y-m-d H:i:s.v'而非'c',后者触发额外时区计算 -
hostname、app name这种静态值,一定要用static属性缓存,别每次 new 实例都gethostname()
daily 的 max_files 和 days 必须一起配
'days' => 14 看似合理,但某天流量突增导致单日日志超 2GB,storage/logs/laravel-2026-05-12.log 就会变成磁盘 I/O 热点,tail -f 查日志、LogViewer 加载都卡顿。
- 必须补上
'max_files' => 30(最多保留 30 个日志文件) - 同时确认
'rotate' => true已开启(旧版 Laravel 需手动加),否则按大小轮转不生效 - 轮转只发生在新日志写入时:当天第一个
Log::error()才会检查并清理过期文件 - 确保
storage/logs/对 Web 用户可写,否则轮转静默失败
真正卡住线上服务的日志问题,往往不是配置没写全,而是 lock、permission、formatter 这三个地方同时踩坑——它们互相掩盖,单独看都不报错,合起来就让请求毛刺飙升。



















