Monolog不能直接捕获E_ERROR或ParseError,需通过set_error_handler和set_exception_handler手动桥接;生产环境应优先选用RotatingFileHandler并注意刷盘可靠性。

Monolog不能直接捕获E_ERROR或ParseError
Monolog本身不处理PHP解析错误、致命错误(E_ERROR)、E_PARSE 或未捕获的异常。它只接收你主动调用 $logger->error() 这类方法传入的日志,或者你手动把 set_error_handler / set_exception_handler 的输出转发给它。想让Monolog“记录所有错误”,必须自己搭桥——不是配个Handler就完事。
用set_error_handler把警告/通知转给Monolog
这个函数能捕获 E_WARNING、E_NOTICE、E_USER_WARNING 等可恢复错误,但默认不带上下文变量快照。要让它真正有用:
- 必须在入口文件最顶部注册,比如
public/index.php开头就调用set_error_handler() - 第二个参数要显式传入错误掩码,例如
set_error_handler($handler, E_ALL & ~E_DEPRECATED),否则$errcontext为空 - 别在 handler 里调用
trigger_error()或抛异常,否则可能递归崩溃 - 返回
true屏蔽原生错误输出,避免敏感路径泄露到页面 - 示例中把
$errfile路径脱敏(如用basename()替换绝对路径),再传给$logger->warning()
用set_exception_handler把未捕获异常喂给Monolog
PHP 7+ 的 TypeError、ParseError、FatalError 都是 Error 类的子类,属于异常体系,set_exception_handler 能捕获它们。关键点:
-
set_exception_handler和set_error_handler可共存,互不影响 - 不要在 handler 里再
throw新异常,否则脚本立即终止,Monolog来不及写日志 - 建议统一用
$logger->critical()或$logger->emergency()记录,体现严重性 - 记得提取
$e->getTraceAsString()和$e->getFile() . ':' . $e->getLine(),这些对定位问题比错误消息本身还重要
StreamHandler + RotatingFileHandler选哪个?
生产环境别无脑用 StreamHandler 往单个文件狂写,容易撑爆磁盘或拖慢IO。实际选择看场景:
立即学习“PHP免费学习笔记(深入)”;
- 日志量小、调试用:用
StreamHandler,指定Logger::DEBUG级别,配合LineFormatter查得快 - 线上服务:优先选
RotatingFileHandler,自动按天或按大小轮转,保留最近7天日志即可 - 高并发写入(如API网关):考虑加
BufferHandler缓冲,避免每条日志都触发磁盘IO - 注意
RotatingFileHandler的$maxFiles参数是总保留份数,不是每天一份;轮转逻辑依赖文件修改时间,NFS等共享存储可能不准
最难搞的从来不是怎么写进文件,而是怎么确保错误发生时那条日志真被刷进磁盘——RotatingFileHandler 默认不 fflush(),极端情况下进程崩溃可能导致最后几条日志丢失。如果业务对错误追溯要求极高,得手动在 close() 前加 stream_get_contents() 强制刷盘,但这会牺牲性能。



















