thinkphp日志需配置max_files、json、logrotate等多维度策略,仅改path和level会导致磁盘爆满、脱敏缺失、结构化失败;必须结合系统级logrotate、敏感字段过滤、数据库存操作日志、全局异常捕获及cli/队列独立通道。

ThinkPHP 日志不是配完 log.php 就能安心睡觉的——生产环境里,日志不轮转会撑爆磁盘,不脱敏会泄露密码,不结构化会让审计查三天都找不到一条删除用户记录。
log.php 配置别只改 path 和 level
很多人只动这两项,结果日志文件按天生成却无限堆积,max_files 被忽略,daily 模式下 runtime/log 目录半年后塞满 200+ 个文件。更隐蔽的问题是 json 设为 true 后没配好时区或上下文字段,导致 ELK 解析失败。
-
max_files必须设值(如30),它控制的是「保留多少个日期文件」,不是总大小 - 多通道场景下,
channels里每个子项要显式声明type、path、level,不能依赖父级继承 -
json => true时,确保运行环境时区已通过date_default_timezone_set()统一,否则 Kibana 时间轴错乱 - 敏感字段过滤必须在格式化器里做,不是靠写日志时手动
unset—— 中间件统一处理才可靠
日志轮转必须用 logrotate,不能只靠框架内置
ThinkPHP 的 max_files 是软限制:它只在新日志写入时检查并删除旧文件,但若某天没请求,旧文件就卡着不动。真实线上环境必须用系统级 logrotate,否则凌晨三点磁盘告警不是偶然。
- 配置中必须含
copytruncate—— ThinkPHP 不支持SIGHUP重载日志句柄,截断是唯一安全方式 -
create 0755 www-data www-data权限要匹配 Web 进程用户,否则第二天日志写失败且无报错 - 测试命令用
sudo logrotate -f /etc/logrotate.d/your-app,别只看 cron 是否存在 - 高频写入服务(如支付回调)建议加
size 50M,避免单日志文件过大拖慢tail -f查看
操作日志必须进数据库,不能写文件
后台管理员行为日志如果还用 Log::info() 写到文件里,等于放弃所有可查性——你没法按「谁在什么时间删了哪个用户」筛选,也没法给审计人员导出 Excel。
- 表结构必须拆字段:
admin_id(非字符串)、module、controller、action、ip、params_json(JSON 类型或 text)、created_at - 中间件里获取
admin_id不能直接读 session,要用$auth->getUserID()或封装校验逻辑,否则未登录时写入空字符串导致索引失效 - 敏感操作(如
deleteUser)额外加is_sensitive = 1字段,避免审计时全表扫描 - 过滤参数用
array_filter($params, function($k) { return !in_array($k, ['password', 'token']); }, ARRAY_FILTER_USE_KEY),别漏掉client_secret等变体
错误监控不能只靠 Log::error()
框架层 Log::error() 只捕获你主动写的错误;PHP 致命错误、未捕获异常、SQL 报错这些,得靠 set_error_handler + set_exception_handler + Sentry 才算闭环。
- 全局异常处理器里,必须调
Log::record()写入结构化日志,同时调Sentry\captureException()上报,二者缺一不可 - SQL 错误单独配置
'sql' => true并设level为error,否则慢查询日志和报错日志混在一起,排查时互相干扰 - CLI 命令的日志要独立通道(如
cli),避免和 Web 请求日志混写,否则php think queue:work的报错会被当成用户请求错误 - 异步任务(队列)里的日志必须带
job_id上下文,否则重试三次失败后,你分不清是哪次执行出的问题
最常被跳过的其实是权限与清理:runtime/log 目录权限必须是 0750,且属主为 Web 进程用户;logrotate 配置里的 compress 开启后,要确认系统装了 gzip,否则轮转直接失败静默。这些细节不验证,上线后第一个满磁盘的永远是日志。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











