Hyperf日志问题根源在于配置路径错误、目录不可写、上下文缺失;需确保logger.php路径正确、runtime/logs可写、日志调用时传入cid/rid等上下文字段。

Hyperf 文件日志存储配置出问题,常表现为日志不写入、文件为空、多协程日志混杂、或启动时报权限错误——这些问题看似零散,根源其实集中在三处:配置路径不对、目录不可写、上下文缺失。
日志文件路径配置错误
Hyperf 日志配置必须放在 config/autoload/logger.php,不是 logging.php 或其他名字。该文件需返回一个数组,顶层键是 channel 名(如 'default'),每个 channel 独立定义 handler、formatter 和 processors。
常见错配:
- 把多个 handler 塞进同一个 channel 的
handlers数组里,结果只生效第一个 - 用
__DIR__拼接日志路径,实际应统一用BASE_PATH . '/runtime/logs/hyperf.log' -
RotatingFileHandler忘记在 constructor 中显式传maxFiles,导致旧日志不轮转(默认保留 0 个)
runtime/logs 目录无写权限
Swoole 进程用户(非 root,通常是 www-data 或 nobody)必须对 runtime/、runtime/logs/ 有读写权限。
典型表现:日志静默失败(无报错,但文件始终为空)。
修复方式:
- 部署时执行
chmod -R 755 runtime/ storage/ - 容器环境需在 Dockerfile 中明确设置用户或
RUN chown -R www-data:www-data /path/to/project/runtime - 避免用 root 启动
composer install,否则 vendor 和 runtime 下部分文件属主为 root,worker 进程无法覆盖
日志内容混乱、找不到请求轨迹
协程环境下,不注入上下文会导致不同请求日志挤在同一行、堆栈丢失、无法关联 request_id。
关键操作:
- 打印日志时必须传 context 数组:
$logger->info('user login', ['uid' => 1001, 'action' => 'login']),而非拼字符串 - 在 controller 入口手动注入协程标识:
Context::set('correlation_id', $request->getAttribute('request_id') ?? uniqid('req_')) - 日志 formatter 启用堆栈:
LineFormatter构造时第四个参数设为true(include_stacktraces),第五个设为true(allow_inline_line_breaks) - 直接在 info() 中带协程 ID:
['cid' => Coroutine::getCid(), 'rid' => $request->getAttribute('request_id')]
基本上就这些。


















