默认日志驱动不支持SLS推送,因FileDriver和StdoutDriver仅支持本地输出,而SLS需HTTP POST、签名认证及JSON/Protobuf封装;须实现think\log\driver\Driver接口,直连SLS HTTP API,注意endpoint格式、权限配置、超时设置与本地fallback机制。

为什么默认日志驱动不支持SLS推送
ThinkPHP自带的 FileDriver 和 StdoutDriver 都只面向本地输出,没有网络传输能力;SLS需要HTTP POST + 签名认证 + Protobuf或JSON格式封装,必须自己实现 think\log\driver\Driver 接口。直接改写 FileDriver 是常见错误——它没预留远程发送钩子,硬塞 curl 会导致日志阻塞、超时崩溃、无重试。
如何实现一个轻量但可用的SLS Log驱动
核心是继承 think\log\driver\Driver,重写 save() 方法,用阿里云官方 PHP SDK(aliyun-openapi-php-sdk)太重,推荐直连 SLS HTTP API:构造带 x-log-apiversion、x-log-bodyrawsize、Authorization 头的 POST 请求。注意三点:
-
save()必须返回true,否则TP会认为写入失败并 fallback 到FileDriver - 日志内容需按 SLS 要求转成 JSON 数组,每条日志是独立对象,字段如
level、message、time、context(可选) - 务必设置
timeout(建议 ≤3s),失败时记录到本地临时文件(如runtime/log/sls_failed.log),避免丢日志
关键配置项怎么填才不报错
SLS 控制台里拿到的 endpoint、accessKeyId、accessKeySecret、project、logstore 这5个值,必须严格对应驱动类里的初始化参数。常见填错点:
-
endpoint不能带http://或https://前缀(SLS API 要求纯域名,如cn-shanghai.log.aliyuncs.com) -
project和logstore区分大小写,且必须已存在(TP不会自动创建) -
accessKeyId/accessKeySecret必须是RAM子账号密钥,主账号AK有安全风险,且SLS权限策略要显式授权log:PostLogStoreLogs
性能和稳定性要注意什么
同步调用 SLS API 会拖慢请求,尤其在高并发或网络抖动时。不要在 save() 里做长连接复用或批量攒批——TP 日志是单次 flush 触发,攒批得自己维护内存队列,复杂度陡增。更稳妥的做法:
立即学习“PHP免费学习笔记(深入)”;
- 用
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 1000)和CURLOPT_TIMEOUT_MS, 2500 - 失败时写入本地 fallback 文件,另起一个低频定时任务(如每分钟一次)用
file_get_contents()+curl补传 - 避免在 CLI 模式下启用该驱动(比如队列消费进程),SLS 的
Content-Length校验对空行敏感,CLI 输出容易混入不可见字符导致 400 错误
真正难的不是签名算法,而是处理网络分区下的日志保全——SLS 不保证 100% 投递成功,本地 fallback + 可追溯的失败日志路径,比“看起来推上去了”重要得多。


















