在Laravel5.5自定义日志文件中记录SQL语句
为什么这样搞?
公司项目繁杂且各项目连接同一数据库,时常因慢查询问题导致我们PHP组的接口响应超时(也有可能是我们自己程序的问题)。为了排除由哪些SQL执行引起的慢查询问题,我们要隔三差五跟运维部门同事要来慢查询日志进行对比分析。最近一直在想,Laravel中有无办法将Eloquent转换成原生SQL并记录下来?直到看了这个帖子才渐渐有了些思路。因为线上运行的服务都配套做了Error Track
(异常捕获),原理是将每个接口返回的错误码全部记录到日志文件中,把日志文件按半小时分割,每隔半小时Error Track
服务就会进行日志分析,若日志里存在错误码,则会发邮件和短信报警。现在有办法在日志文件里记录原生SQL了,接下来就该考虑如何把SQL记录到新的文件里从而不影响异常捕获程序正常运行。
自定义日志文件
最近刚理解了trait
,所以这里试着用用,反正也不花钱。
在app
目录下新建目录Traits
,在Traits
里新建文件CustomLogger.php
,内容如下:
1 | <?php |
定义这样一个自定义日志性状,支持自定义日志文件名称、日志保存路径及保留时长。哪里需要就可以记哪里了。用法见下文。
监听SQL执行事件
参照文档可知,在AppServiceProvider.php
中的boot方法中添加如下代码即可监听。
1 | DB::listen(function ($query) { |
现在修改一下匿名方法,把监听到的SQL记录到自定义日志文件里。
1 | use CustomLogger; |
stackoverflow上有个帖子说PHP中只有类、接口、方法和常量受命名空间影响,定义trait不需要命名空间,但试了下并不行。所以在AppServiceProvider
文件里还需要use App\Traits\CustomLogger;
。
补充
项目使用Laravel5.1开发,使用如上步骤报错。以下是5.1版本使用方法:
1 | use CustomLogger; |
第二次补充
目前修改后的项目已进入测试阶段,在测试环境查看日志文件里的SQL语句,一坨一坨的。为了以后能精确分析出那些执行时间长的SQL是请求哪些接口出现的,应该在每条SQL语句后标识一下接口名称。非常简单,使用Laravel的Request
门面获取到uri即可。修改代码如下:
1 | use Illuminate\Support\Facades\Request; |
可以通过[execute_time=1.24ms][uri=login]
这两个标识来过滤日志。比如要查看登录接口执行时间是50毫秒的SQL
1 | grep 'execute_time=50.*' | grep 'uri=login' illuminate.query-2017-09-08.log |