Hyperf日志异常主因是配置不匹配:server name与exceptions.php中handler键名必须严格一致;需启用LineFormatter的include_stacktraces;协程下应手动注入correlation_id并显式传入上下文;确保logs目录可写且handler配置正确。

Hyperf服务启动或运行中出现异常却看不到详细日志,通常不是代码报错被隐藏,而是日志配置没对上、异常处理器没生效,或者协程上下文丢失导致日志写不进对应文件。重点不在“加日志”,而在“让已有日志机制真正起作用”。
确认 server name 与异常处理器键名严格一致
验证失败返回空 errors 字段、400 错误没堆栈、自定义异常处理器不触发——90% 是这里错了。
- 运行
php bin/hyperf.php start,看启动日志里[INFO] Server started: http://0.0.0.0:9501前面的name值(比如是api或admin) - 打开
config/autoload/server.php,找到 HTTP server 配置块,核对'name' => 'xxx'的值 - 打开
config/autoload/exceptions.php,检查handler数组的键名是否与上一步完全相同,大小写敏感、不能多空格 - 例如 server name 是
api,就必须写'api' => [Hyperf\Validation\ValidationExceptionHandler::class],写成'http'或'API'都无效
启用带堆栈的协程安全日志格式
协程环境下,堆栈默认不打印;用 LineFormatter 但没开开关,就只能看到一行“PHP Error”,找不到哪行代码出的问题。
- 修改
config/autoload/logger.php中 default channel 的formatter配置 - 确保
constructor第四个参数为true(include_stacktraces),第五个为true(allow_inline_line_breaks) - 不要依赖
$_SERVER['REQUEST_URI']这类全局变量记录上下文,它们在协程间不隔离,会导致日志串行 - 若需 trace_id,应在请求入口手动注入:
\Hyperf\Context\Context::set('correlation_id', $request->getAttribute('request_id'))
强制绑定协程 ID 和请求 ID 到每条日志
多请求并发时日志混在一起,看不出哪条属于当前请求?不是日志没打,是没标清楚归属。
- 在控制器方法开头或中间,显式传入上下文:
$this->logger->info('user login start', ['cid' => \Swoole\Coroutine::getCid(), 'rid' => $request->getAttribute('request_id') ?? 'unknown']); - 避免只写
$this->logger->info('user login start');—— 没 context 就等于没身份 - 如果用了自定义 Formatter,确保它从
\Hyperf\Context\Context::get()读取correlation_id,而不是尝试从$_SERVER取
检查日志目录权限与 handler 是否生效
日志文件为空、runtime/logs 下没生成 hyperf.log,大概率是路径不可写或 handler 配置错位。
- 确认
BASE_PATH . '/runtime/logs'目录存在且 Web 服务器用户(如 www-data)有写权限 - 不要把多个 handler 塞进同一个 channel 的
handlers数组里——Hyperf 只取第一个,其余静默忽略 - 要输出到多个目标(如文件 + stdout),应定义多个 channel(如
'default'和'console'),再分别调用$loggerFactory->get('console') - 若用
RotatingFileHandler,maxFiles必须显式传入 constructor,否则默认轮转 0 个旧文件,日志会不断追加不切分



















