php日志不能仅用error_log(),因易丢上下文、混线程、错乱输出;需按sapi环境配置输出目标,推荐monolog统一管理处理器与格式器,并注入请求id等上下文。

PHP 日志记录不是加个 error_log() 就完事,真正在生产环境或复杂请求链路里排查问题,靠裸打日志很容易漏上下文、混线程、丢关键字段,甚至拖慢响应。
用 error_log() 记日志时为什么总看不到内容?
最常见原因是没配对的错误报告级别或输出目标被重定向了。比如 CLI 模式下 error_log() 默认写到 stderr,但如果你用 php -f script.php > out.log 重定向 stdout,stderr(也就是日志)依然打在终端上,根本不会进 out.log。
- 确认当前 SAPI 环境:
php_sapi_name()是cli还是fpm,行为差异很大 - FPM 下默认
error_log配置项可能指向/var/log/php-fpm/www-error.log,而非你预期的文件 - 别依赖
display_errors = On—— 它只控制错误是否输出到页面,和error_log()写入无关 - 想写文件?显式传第三个参数:
error_log("msg", 3, "/tmp/myapp.log"),但要注意并发写入可能错乱
为什么 Monolog 是实际项目首选?
因为它的处理器(Handler)和格式器(Formatter)能解耦「日志内容」和「日志去向」,避免手写 fopen()+fwrite()+fclose() 的竞态和维护成本。
- 用
StreamHandler写文件,自动处理追加、权限、轮转(配合RotatingFileHandler) -
ConsoleHandler在 CLI 调试时高亮显示WARNING/ERROR级别 - 加
ProcessIdProcessor或WebProcessor,每条日志自动带pid、url、ip,不用每次手动拼 - 别直接 new
Logger:用Logger::pushProcessor()统一注入上下文,比如请求 ID,否则异步任务里容易串日志
var_dump() 和 debug_backtrace() 调试线上请求为什么危险?
它们会直接输出到响应体或错误流,一旦开启就可能暴露敏感信息(数据库密码、token)、破坏 JSON 格式、触发 headers already sent 错误,甚至让整个接口返回 500。
- 开发环境可用
ini_set('display_errors', '1')+error_reporting(E_ALL),但上线前必须关掉 -
var_dump()输出大数组时会卡住 FPM worker,尤其在 Xdebug 开启时更明显 - 想看调用栈?改用
error_log(print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true), 3, "/tmp/trace.log"),不走响应流 - 更好的做法:用
xdebug_info()确认 Xdebug 是否启用;用trigger_error("debug point", E_USER_NOTICE)配合自定义错误处理器捕获
真正难的不是记下日志,而是让每条日志自带可追溯的上下文、不干扰正常流程、且能在多进程/协程/队列场景下保持归属清晰——这些细节在 Monolog 配置里一个 processor 没加对,或者 log level 混用 DEBUG 和 INFO,就会让日志变成噪音源。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











