Monolog 是 PHP 框架日志的底层引擎,框架通过 PSR-3 接口解耦并注入 Monolog 实例,由 Handler(如 StreamHandler、SlackWebhookHandler)执行具体日志操作,$context 必须为数组以支持结构化日志。

Monolog 是绝大多数 PHP 框架日志的底层引擎
你看到的 Log::info()、$logger->error() 或 Symfony 的 LoggerInterface 注入,背后几乎都跑着 Monolog。它不是框架“自己写的日志系统”,而是统一接入 PSR-3 接口后,用 Monolog 实例填充的——Laravel、Symfony、Slim、Zend Framework 等均如此。
关键点在于:框架只负责“装配”和“路由”,不负责“写文件”或“发 Slack”。真正干活的是 Monolog 的 Handler(比如 StreamHandler 写文件、SlackWebhookHandler 发消息),而框架通过配置把请求分发给对应 Handler。
- Monolog 本身不强制依赖任何框架,靠
LoggerInterface解耦业务代码 - 框架的“日志配置”(如 Laravel 的
config/logging.php)本质是告诉 Monolog:哪些Handler启用、按什么顺序执行、用哪个Formatter序列化 - 所有日志调用最终都会走到
Logger::log($level, $message, $context),然后由 Handler 链逐个处理
PSR-3 接口如何让框架和日志实现解耦
框架代码里从不 new Monolog,而是 type-hint Psr\Log\LoggerInterface。这意味着:
- 你可以把默认 Monolog 替换成其他 PSR-3 兼容实现(比如
php-pm/logger或自研轻量版),只要它实现了log()、info()等 8 个方法 -
$context参数必须是数组——这是结构化日志的基础,也是 ELK/Sentry 能提取user_id、request_id的前提 - 框架不关心日志是否落盘、是否加密、是否异步;它只管把
['user_id' => 123]传过去,剩下的交给 Handler
一旦违反这个契约(比如传对象进 $context),Monolog 会静默失败或抛出 InvalidArgumentException,而不是报错提示。
立即学习“PHP免费学习笔记(深入)”;
为什么框架日志有时“不写入文件”或“级别不生效”
常见问题基本不出在框架本身,而是配置链断裂:
- 没配对
level和channels:Laravel 中'level' => 'debug'是 channel 级别,但若该 channel 被 stack 包裹,实际生效的是 stack 的最低 level,不是单个 handler 的 - 路径权限错误:Monolog 的
StreamHandler默认不创建父目录,/var/log/myapp/app.log若/var/log/myapp/不存在,会静默失败(返回 false 且无异常) - 日志被 buffer 住:CLI 环境下
ob_end_flush()不触发,或fastcgi_finish_request()未调用,导致StreamHandler的 write 延迟到响应结束,而进程已退出 - 环境变量覆盖:Laravel 的
LOG_CHANNEL=stack若被 .env 误设为single,而singlechannel 的 path 指向不可写路径,日志就丢了
中间件里记录请求日志时,$context 容易漏掉什么
在 TP5/Laravel/Symfony 的日志中间件中,仅记录 $_SERVER['REQUEST_URI'] 和状态码远远不够。真实排障需要能关联请求全链路:
- 必须注入唯一
request_id(如bin2hex(random_bytes(16))),并确保它透传到后续所有日志、DB 查询、HTTP 调用 -
$_SERVER['REMOTE_ADDR']在 Nginx 反向代理后是 127.0.0.1,得取$_SERVER['HTTP_X_FORWARDED_FOR']并校验可信代理列表 - 不要直接 dump
$_POST或$_GET,敏感字段(密码、token)需显式过滤,否则日志变泄露源 - 响应体(
$response->getContent())体积大时别全记,可截取前 256 字节 + 标记 “truncated”
最常被忽略的是:中间件捕获的是“进入时”的请求,但错误可能发生在控制器之后。真要完整链路,得配合 register_shutdown_function() 或异常处理器补全日志。



















