要让Hyperf异常拦截器输出完整报错栈,必须确保异常路由到正确处理器、日志格式启用堆栈记录、响应体显式包含trace信息三步到位:先核对server name与exceptions.php键名一致,再在handle()中用getTraceAsString()写入响应,最后配置LineFormatter的include_stacktraces为true。

要让Hyperf异常拦截器输出完整报错栈,关键不是“打开开关”,而是确保异常真正到达你定义的处理器、且日志格式支持堆栈渲染、响应体中显式包含堆栈信息——这三步缺一不可。
确认异常被正确路由到你的Handler
Hyperf按server name匹配异常处理器,不是按HTTP路径或类名。若你在config/autoload/server.php里把HTTP服务的'name' => 'api',却在exceptions.php里配了'http' => [...],那这个handler根本不会执行。
- 运行
php bin/hyperf.php start,看启动日志里Server started: http://0.0.0.0:9501前面的[INFO]行,记下实际name值(比如api) - 打开
config/autoload/exceptions.php,确保handler数组的键名与上一步完全一致、大小写敏感 - 检查
isValid()方法是否精准返回true:不要写return true;,应明确限定类型,例如return $throwable instanceof \App\Exception\BusinessException;
在handle()中主动注入堆栈信息
框架默认不把堆栈塞进响应体,需手动提取并序列化。别依赖$throwable->__toString(),它可能被重写或截断;要用$throwable->getTraceAsString()或debug_print_backtrace()配合捕获输出。
- 在
handle()方法内,构造响应数据时加入'trace' => $throwable->getTraceAsString() - 若需结构化堆栈(方便前端解析),可用
$throwable->getTrace()获取数组,再过滤敏感字段(如密码、token)后写入 - 注意:生产环境建议仅对特定角色(如dev/admin)返回完整堆栈,普通用户返回泛化错误提示
日志侧同步启用堆栈记录
即使响应里写了堆栈,如果日志里没留痕,排查时仍会断档。Monolog的LineFormatter默认关闭堆栈输出,必须显式开启。
- 修改
config/autoload/logger.php,找到'formatter' => Monolog\Formatter\LineFormatter::class配置块 - 在
'constructor'参数中,将第四个参数设为true(即include_stacktraces = true) - 第五个参数也设为
true(allow_inline_line_breaks = true),避免堆栈被压成一行无法阅读 - 协程环境下,记得用
\Hyperf\Context\Context::get('correlation_id')补全日志上下文,否则多请求堆栈会混在一起
响应有堆栈、日志有堆栈、且两者能通过correlation_id关联起来,才算真正闭环。不复杂但容易忽略。











