需实现自定义ES日志驱动:一、创建EsDriver类继承thinklogDriver,批量写入ES并降级本地;二、注册驱动并配置host等参数;三、可用Logstash代理转发;四、支持Cron批量导入历史日志;五、配置ILM策略管理索引生命周期。
如果您在ThinkPHP项目中希望将日志直接写入Elasticsearch而非本地文件,需绕过默认File驱动,通过实现自定义日志驱动完成。以下是具体配置与实现步骤:
一、创建继承thinklogDriver的ES日志驱动类
该方法通过实现ThinkPHP日志驱动接口,将日志结构化后批量推送至Elasticsearch,避免阻塞主请求流程,并具备失败静默与本地降级能力。
1、在
目录下新建
文件(确保符合PSR-4自动加载规范)。
2、声明命名空间并引入必要依赖:
、
。
立即学习
“
PHP免费学习笔记(深入)
”;
3、定义
类并继承
,在构造方法中初始化Elasticsearch客户端,传入
、
等配置。
4、重写
方法:遍历二维日志数组,按
+
成对组装bulk body;日期索引格式设为
。
5、调用
发送请求,成功返回
;捕获异常后写入本地
,仍返回
。
二、注册自定义日志驱动并启用
该方法通过修改框架日志配置,使ThinkPHP识别并使用新驱动,同时规避
问题。
1、确认
中已声明自动加载规则,例如:
。
2、执行
刷新自动加载映射。
3、在
中将
设为
,或使用闭包方式动态实例化。
4、提供必需配置项:
、
、
,确保超时短且重试可控。
5、验证驱动加载:在控制器中调用
,检查ES中
索引是否生成文档。
三、使用Logstash代理日志转发(替代直连驱动)
该方法解耦应用与ES依赖,利用Logstash作为中间件接收日志并写入ES,适用于无法安装PHP ES SDK或需统一日志治理的场景。
1、在ThinkPHP中配置日志类型为
,目标地址设为
(Logstash beats input端口)。
2、安装Filebeat并配置
,监控
,输出至Logstash。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
3、编写Logstash配置
,input使用
插件,filter用
解析ThinkPHP日志格式(如
),output指向ES集群。
4、确保ES中预置索引模板,匹配
索引名,定义
为keyword、
为text、
为date类型。
5、启动Filebeat与Logstash服务,确认ES中出现带
字段的新文档,且
包含完整日志上下文。
四、通过Cron+脚本批量导入历史日志文件
该方法适用于已有大量本地日志文件需迁移至ES的场景,不侵入应用代码,以离线方式完成数据同步。
1、编写PHP脚本
,读取
等文件内容。
2、按行解析日志,使用正则提取
、
、
、
字段,构建JSON文档数组。
3、调用Elasticsearch官方SDK的
方法,每50条打包一次,索引名按日期生成,如
。
4、设置脚本执行权限:
,并通过
添加每日凌晨执行任务:
。
5、运行脚本后检查ES响应结果,确认
且
数量与输入行数一致,无
错误。
五、配置Elasticsearch索引生命周期与滚动策略
该方法保障ES日志索引长期运行的稳定性与可维护性,防止磁盘爆满及查询性能衰减。
1、在ES中创建ILM策略
,定义
阶段保留7天、
阶段自动删除30天前索引。
2、创建索引模板
,匹配
,绑定上述ILM策略,并设置
、
(单节点开发环境)。
3、在ThinkPHP的ES驱动中,将索引名硬编码逻辑改为调用
动态生成,确保每日新建索引。
4、验证ILM生效:等待24小时后,执行
,确认
处于
阶段且
为
。
5、手动触发一次rollover测试:
,观察是否生成
新索引并迁移别名。
app/common/log/EsDriver.phpuse thinklogDriver;use ElasticsearchClientBuilder;EsDriverDriverhostportsave(array $log): boolindexdocumenttp-log-Y-m-d$this->client->bulk()trueruntime/log/es-fail.logtrueClassNotFoundExceptioncomposer.json"psr-4": {"app\common\log\": "app/common/log/"}composer dump-autoloadconfig/log.phptypeappcommonlogEsDriver'host' => '127.0.0.1:9200''timeout' => 1'retries' => 1Log::record('test', 'info')tp-log-YYYY-MM-DDsocket127.0.0.1:5044filebeat.ymlruntime/log/*.logphp-log.confbeatsgrok{date} [{time}] {level} {message}php-logs-*levelmessage@timestamp@timestamp_sourceimport_to_es.phpruntime/log/2026-04-*.logdatetimelevelmessagebulk()tp-log-2026-04-24chmod +x import_to_es.phpcrontab -e0 2 * * * /usr/bin/php /var/www/thinkphp/import_to_es.phperrors: falseitems400 Bad Requestthinkphp-log-policyhotdeletethinkphp-log-templatetp-log-*number_of_shards: 1number_of_replicas: 0date('Y-m-d')GET /_ilm/explaintp-log-2026-04-23hotactionrolloverPOST /tp-log-2026-04-24/_rollovertp-log-2026-04-24-000001