要让Hyperf日志完整记录报错详情,需协同配置handler、formatter和上下文:启用LineFormatter的include_stacktraces与allowInlineLineBreaks;手动注入request_id并传入cid、rid等上下文;为error channel单独配置JsonFormatter;确保exceptions.php中handler键名与server.php中HTTP server name一致。

要让 Hyperf 日志完整记录程序报错详情(包括异常堆栈、请求上下文、协程 ID 等),不能只靠默认配置——关键在于 handler、formatter 和上下文传入三者协同生效。
确保异常堆栈被写入日志
默认 LineFormatter 会丢弃堆栈,需显式启用:
- 在
config/autoload/logger.php的 formatter 配置中,constructor 第四个参数设为true(即include_stacktraces => true) - 同时设第五个参数
allowInlineLineBreaks => true,避免堆栈被压缩成一行 - 若用自定义 formatter,继承
LineFormatter并重写format(),确保调用$record['context']['exception'] ?? null并格式化输出
绑定请求与协程上下文
否则多请求并发时日志混杂,无法定位具体哪次调用出错:
- 在中间件或控制器入口处,手动注入唯一标识:
\Hyperf\Context\Context::set('request_id', $request->getAttribute('request_id') ?: uniqid('req_')); - 在日志调用时,把关键上下文作为
context数组传入:$logger->error('DB query failed', ['sql' => $sql, 'cid' => \Swoole\Coroutine::getCid(), 'rid' => \Hyperf\Context\Context::get('request_id')]); - 避免使用全局变量(如
$_SERVER)读取请求信息,协程环境下不安全
结构化输出便于排查
纯文本日志查起来费劲,JSON 格式配合日志平台更高效:
- 为 error channel 单独配一个
JsonFormatter,constructor 中指定:'batchMode' => \Monolog\Formatter\JsonFormatter::BATCH_MODE_JSON和'appendNewline' => true - 业务代码中必须用数组传 context,而不是拼接字符串:
✅ 正确:$logger->error('user not found', ['user_id' => $uid, 'trace_id' => $traceId]);
❌ 错误:$logger->error("user not found user_id:{$uid}"); - 可在 formatter 中自动注入
time、level、channel、cid、rid等字段,无需每次手动传
验证异常是否真被记录
常见“没日志”其实是配置错位或 fallback 到 default:
- 检查
config/autoload/exceptions.php中 handler 键名,是否与server.php里 HTTP server 的name完全一致(大小写敏感) - 抛出异常后,确认日志文件路径(如
runtime/logs/error.log)存在且可写(chmod -R 777 runtime/logs) - 临时把 logger level 设为
DEBUG,并触发一个throw new RuntimeException('test'),观察是否写入堆栈


















