跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

ThinkPHP环境监控方案_错误日志监控与异常提醒配置

ThinkPHP需配置log.php的level包含error/notice/alert、file路径为绝对路径、single设为false,并在入口注册register_shutdown_function捕获Fatal Error;同时将flush_interval设为1确保日志实时写入。 如何让ThinkPHP自动记录完整错误日志到指定文件 默认情况下,ThinkPHP在
APP_DEBUG = false
时只写
runtime/log/
下的日志,且不包含堆栈、请求参数等关键信息——这会导致线上问题排查困难。 必须手动配置日志驱动和级别: 在
config/log.php
中设置
'default' => 'file'
,并确保
'level' => ['error', 'notice', 'alert']
(不能只留
'error'
,否则
trigger_error()
类警告不会被捕获)
'file' => ['path' => '/var/log/thinkphp/']
要指向有写权限的绝对路径,相对路径在CLI模式下容易错位 务必关闭
'single' => true
(默认为
false
),否则每天日志会覆盖,丢掉异常时间线 捕获未被try-catch兜住的致命错误(Fatal Error) ThinkPHP内置的
think\exception\Handle
对
Fatal error
无能为力,因为PHP在解析或执行阶段崩溃时根本进不了框架生命周期。 需在入口文件
public/index.php
最顶部注册底层处理器: 立即学习 “ PHP免费学习笔记(深入) ”;
register_shutdown_function(function () { if ($error = error_get_last()) { if (in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { $log = date('Y-m-d H:i:s') . " FATAL: {$error['message']} in {$error['file']}:{$error['line']}\n"; file_put_contents('/var/log/thinkphp/fatal.log', $log, FILE_APPEND | LOCK_EX); } } });
注意:
error_get_last()
只能拿到最后一次错误,所以这个钩子必须放在所有其他
register_shutdown_function
之前;另外
E_ERROR
不包含
E_WARNING
,别误以为它能捕获所有报错。 异常触发企业微信/钉钉告警的最小可行配置 不要直接在
AppExceptionHandle
里发HTTP请求——框架尚未完成初始化,
Config
、
Log
可能不可用,且阻塞响应。 推荐用异步+队列方式落地: 在
app/exception/Handle.php
的
report()
方法里,只做轻量动作:
queue_push('alert', ['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()])
单独写一个
command/AlertSend
命令,用
curl
或
file_get_contents
调用钉钉机器人Webhook,超时设为
3s
,失败自动重试最多2次 避免在
render()
里发告警——那是渲染错误页面用的,用户还没看到页面就收到告警,体验奇怪 为什么
Log::error()
有时没写进文件,但
error_log()
却有 这是ThinkPHP日志缓冲机制导致的:默认启用
'flush_interval' => 10
,即每10条日志才刷一次磁盘。如果进程意外退出(如超时kill),最后几条就丢了。 线上环境建议: 把
'flush_interval' => 1
,牺牲一点性能换日志完整性 禁用
'json' => true
(默认
false
),JSON格式在日志切割或grep时反而难处理 确认
opcache.revalidate_freq
不为0,否则修改了
log.php
配置也不会生效 监控不是配完就完事,真正难的是让每一条
Fatal error
都留下痕迹,而不是靠重启后看有没有新日志来反推问题。

相关文章