必须在swoole server实例化后、start()前用set()配置绝对路径log_file和swoole_log_warning/error级log_level,worker日志需按pid隔离,禁用error_log()避免流冲突,并由应用层实现按天轮转。

要在Swoole服务中稳定输出可排查、不丢失、不混杂的运行日志,必须避开log_file硬编码、log_level误设、worker日志竞争这三类高频错误,尤其不能在Server实例化后再配置日志参数。
设置基础日志路径与级别
在new Swoole\Http\Server或Swoole\Server之后、start()之前调用set()方法配置log_file和log_level。
log_file必须指定绝对路径,且PHP进程对该路径有写权限,例如:'log_file' => '/var/log/swoole/app.log'。
log_level需设为SWOOLE_LOG_WARNING或SWOOLE_LOG_ERROR,【若仍设为默认的SWOOLE_LOG_DEBUG或0,INFO/NOTICE级日志将大量刷屏,掩盖真正异常】。
这一步操作起来很简单,直接把数组传进set()就行,但顺序错一点——比如写在start()之后——整个配置就完全失效。
隔离Worker进程日志文件
默认所有Worker共用一个log_file,高并发下极易因文件锁导致日志截断、覆盖或错行。
方法一:在onWorkerStart回调中动态拼接PID生成独立日志路径
使用getmypid()获取当前Worker真实进程ID,拼入log_file值,例如:'log_file' => '/var/log/swoole/worker_'.getmypid().'.log'。
方法二:仅适用于SWOOLE_PROCESS模式;SWOOLE_BASE模式无独立Worker进程,此法无效,强行使用会导致全部日志写入同一文件。
注意:绝不可用date('His')等时间戳命名,秒级重复会覆盖前一条日志,关键报错直接消失。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
禁用error_log()避免日志流冲突
Docker或CLI环境下,Swoole日志与PHP原生error_log()默认都往stderr写,两条日志流会穿插交错,一条完整请求链可能被切成三段,无法对齐上下文。
第一步:全局禁用error_log(),改用Swoole\Logger::info()或Swoole\Coroutine\Log::warning()输出。
第二步:若必须保留error_log()调用,先在onWorkerStart中执行ini_set('error_log', '/tmp/worker_'.getmypid().'_error.log')重定向目标文件。
【error_log()不受log_level控制,哪怕log_level=5(ERROR),error_log('debug')仍会原样输出】。
按天轮转日志并自动清理
Swoole自身不支持日志切分,需手动实现按日期生成新文件+旧文件归档。
① 启动时读取当前日期,构造当日日志路径:$date = date('Y-m-d'); $logPath = "/var/log/swoole/{$date}.log";
② 每次写入前检查文件名是否仍为当天,否则关闭旧文件句柄、打开新文件句柄(可用fopen + stream_set_write_buffer控制缓冲)。
③ 配合系统logrotate或crontab每日凌晨压缩3天前日志:find /var/log/swoole -name "*.log" -mtime +3 -exec gzip {} \;
这一步不能依赖Swoole内置机制,必须由应用层主动判断日期变更并切换文件句柄,否则所有日志会持续追加到同一个文件,体积失控。










