Laraver SQL日志 服务开发
Laravel 项目运行中,有时候需要查看sql语句,分析sql运行的耗时,sql语句的复杂程度分析等等
总之,sql的执行在项目中,非常关键,接下来将说明在laravel 中 配置一个sql日志记录服务。
开发思路:
- 使用 Laravel 事件系统监听 QueryExecuted 事件
- 通过监听服务,将监听到的sql信息记录到日志文件
代码开发
1. 日志通道配置一个记录sql的日志通道
文件:config/logging.php
'channels' => ['sqllog' => ['driver' => 'daily','path' => storage_path('logs/sql.log'),'level' => 'debug','days' => 7,'permission' => 0664,],
];
通道名称 sqllog,驱动程序 daily , path是路径,level 为等级,days 保留7天,permission 为文件权限
2.事件系统配置监听事件
文件:app/Providers/EventServiceProvider.php
protected $listen = [QueryExecuted::class => [LogDBQuery::class,],];
-
QueryExecuted::class是 Laravel 数据库系统中的一个核心事件,也是 Laravel 数据库层最基础也是最有用的事件之一,其在数据库完成查询后触发。- 触发的时机:
- SELECT 查询
- INSERT/UPDATE/DELETE 操作
- 事务操作(BEGIN, COMMIT, ROLLBACK)
- 存储过程调用
- 事件对象包含的信息
- public string $sql; // 执行的SQL语句(带占位符)
- public array $bindings; // 绑定的参数值
- public float $time; // 执行时间(毫秒)
- public string $connectionName; // 使用的连接名称(如’mysql’)
- public object $connection; // 数据库连接实例
- 触发的时机:
-
LogDBQuery::class 是自己开发一个监听服务类
3.监听服务开放
目录:app/Listeners,创建类 LogDBQuery.php
<?phpnamespace App\Listeners;use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;class LogDBQuery
{// 慢查询阈值(毫秒)protected const SLOW_QUERY_THRESHOLD = 500;/*** 处理查询事件*/public function handle(QueryExecuted $event): void{// 只在本地和测试环境记录if(!App::environment(['local', 'testing'])){return;}// 随机抽取 10% 的查询日志if(random_int(1, 100) > 10){return;}$context = $this->buildLogContext($event);if($event->time > self::SLOW_QUERY_THRESHOLD){Log::channel('sqllog')->warning("Slow query detected", $context);}else{Log::channel('sqllog')->debug("Query executed", $context);}}/*** 格式化 SQL 语句*/protected function formatSql(string $sql, array $bindings): string{if(empty($bindings)){return $sql;}$escapedBindings = array_map(fn($value) => $this->escapeBinding($value), $bindings);return Str::replaceArray('?', $escapedBindings, $sql);}/*** 转义绑定参数*/protected function escapeBinding(mixed $value): string{if(is_null($value)){return 'NULL';}if(is_bool($value)){return $value ? '1' : '0';}if(is_numeric($value)){return (string)$value;}return "'" . addslashes((string)$value) . "'";}/*** 构建日志上下文*/protected function buildLogContext(QueryExecuted $event): array{return ['sql' => $this->formatSql($event->sql, $event->bindings),'time' => $event->time . 'ms','connection' => $event->connectionName,'bindings' => $event->bindings,'raw_sql' => $event->sql,];}
}
监听类执行流程
1事件触发 → 2. 框架查找监听器 → 3. 实例化监听器 → 4. 调用 handle()
代码解释:
-
SLOW_QUERY_THRESHOLD添加一个慢查询的阈值,如果查询时间大于阈值,则是慢查询 -
handle自动执行:
- 当非生产环境,则执行
if(!App::environment(['local', 'testing'])){return;}
- 随机抽查 10%的日志记录
if(random_int(1, 100) > 10){return;}
- 构建日志上下文数组,记录sql的语句,时间,连接等信息
protected function buildLogContext(QueryExecuted $event): array{return ['sql' => $this->formatSql($event->sql, $event->bindings),'time' => $event->time . 'ms','connection' => $event->connectionName,'bindings' => $event->bindings,'raw_sql' => $event->sql,];}
- 检测是否是慢查询,记录不同级别的日志,提高日志的可观察性
if($event->time > self::SLOW_QUERY_THRESHOLD){Log::channel('sqllog')->warning("慢查询SQL", $context);}else{Log::channel('sqllog')->debug("执行SQL", $context);}
完成上述构建,测试一下:
[2025-03-31 14:10:26] local.DEBUG: 执行SQL {"sql":"select count(*) as aggregate from `project_info` where `project_info`.`deleted_at` is null","time":"24.21ms","connection":"mysql","bindings":[],"raw_sql":"select count(*) as aggregate from `project_info` where `project_info`.`deleted_at` is null"}
[2025-03-31 14:10:26] local.DEBUG: 执行SQL {"sql":"select * from `project_info` where `project_info`.`deleted_at` is null order by `id` desc limit 10 offset 0","time":"24.77ms","connection":"mysql","bindings":[],"raw_sql":"select * from `project_info` where `project_info`.`deleted_at` is null order by `id` desc limit 10 offset 0"}
在实际项目中,还可以进行后续的扩展,例如 排除哪个连接 connectionName 不记录,那个 sql 不记录等等。
注意事项:
生产环境慎用:频繁查询的应用中,监听所有查询可能影响性能- 抽查监控:可以
只记录部分查询
知识点总结:
- 日志通道配置
- EventServiceProvider 事件服务类
- QueryExecuted::class 数据库核心类
- Listeners 监听器类的开发
- 执行流程:事件触发 → 2. 框架查找监听器 → 3. 实例化监听器 → 4. 调用 handle()
相关文章:
Laraver SQL日志 服务开发
Laravel 项目运行中,有时候需要查看sql语句,分析sql运行的耗时,sql语句的复杂程度分析等等 总之,sql的执行在项目中,非常关键,接下来将说明在laravel 中 配置一个sql日志记录服务。 开发思路:…...
NG-ZORRO中tree组件的getCheckedNodeList怎么使用
在 NG-ZORRO(Ant Design for Angular) 的 Tree 组件 中,getCheckedNodeList 方法用于获取当前选中的节点列表(包括半选状态节点)。以下是具体用法和示例: 基本用法 首先,确保你已通过 ViewChil…...
win10之mysql server 8.0.41安装
一 mysql server 下载 官网下载地址页面 https://dev.mysql.com/downloads/mysql/二 免装版使用步骤 1 解压 下载完成后,解压文件夹,如下所示: 2 执行安装命令 D:\soft\mysql\mysql-8.0.41-winx64\mysql-8.0.41-winx64\bin>mysqld --install Service successfully in…...
蓝桥杯专项复习——二分
目录 二分查找、二分答案基础知识 二分查找模版 【模版题】数的范围 借教室 二分查找、二分答案基础知识 二分查找模版 【模版题】数的范围 输入样例 6 3 1 2 2 3 3 4 3 4 5输出样例 3 4 5 5 -1 -1 思路: 对应两个模版,起始位置是对应第一个模版…...
oracle中java类的使用
方式一: 编写一个简单的java类 vi OracleJavaDemo.java public class OracleJavaDemo { public static String processData(String input) { return "Processed: " input; } } 编译 javac OracleJavaDemo.java 生成OracleJavaDemo…...
高并发内存池(一):项目介绍和Thread Cache实现
前言:本文将要介绍的高并发内存池,它的原型是Google的⼀个开源项⽬tcmalloc,全称Thread-Caching Malloc,近一个月我将以学习为目的来模拟实现一个精简版的高并发内存池,并对核心技术分块进行精细剖析,分享在…...
MySQL与Redis数据一致性保障方案详解
前言 在现代分布式系统中,MySQL和Redis的结合使用非常普遍。MySQL作为关系型数据库负责持久化存储,而Redis则作为高性能缓存层提升系统的响应速度。然而,在这种架构下,如何保证MySQL与Redis之间的数据一致性是一个重要的挑战。本…...
“钉耙编程”2025春季联赛(2)题解(更新中)
1001 学位运算导致的 1002 学历史导致的 // Problem: 学历史导致的 // Contest: HDOJ // URL: https://acm.hdu.edu.cn/contest/problem?cid1151&pid1002 // Memory Limit: 524288 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org)#include …...
C#高级:启动、中止一个指定路径的exe程序
一、启动一个exe class Program {static void Main(string[] args){string exePath "D:\测试\Test.exe";// 修改为你要运行的exe路径StartProcess(exePath);}private static bool StartProcess(string exePath){// 创建一个 ProcessStartInfo 对象来配置进程启动参…...
【NumPy】1. 前言安装
0.前言 需要具备[[Python]]基础 定义: NumPy 通常与 [[SciPy]](Scientific Python)和 [[Matplotlib]](绘图库)一起使用, 这种组合广泛用于替代 [[MatLab]],是一个强大的科学计算环境,有助于我…...
双向链表的理解
背景 代码中经常会出现双向链表,对于双向链表的插入和删除有对应的API函数接口,但直观的图表更容易理解,所以本文会对rt-thread内核代码中提供的双向链表的一些API函数操作进行绘图,方便后续随时查看。 代码块 rt-thread中提供…...
基于Spring Boot的家庭理财系统app的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
【测试】每日3道面试题 3/31
长期更新,建议关注收藏点赞。 单元测试策略有哪些,主要内容。 白盒测试黑盒测试基于异常和边界的测试 主要内容:测试用例设计、执行、结果分析、自动化beta测试和alpha测试主要区别 主要区别:测试环境测试者 alphabeta时间先后测…...
Go 语言常见错误
代码及工程组织 1、意外的变量隐藏 示例代码: package mainimport ("fmt" )var FunTester "全局变量 FunTester"func main() {FunTester : "局部变量 FunTester"fmt.Println(FunTester) }func showGlobal() {fmt.Println(FunTest…...
216. 组合总和 III 回溯
目录 问题描述 解决思路 关键点 代码实现 代码解析 1. 初始化结果和路径 2. 深度优先搜索(DFS) 3. 遍历候选数字 4. 递归与回溯 示例分析 复杂度与优化 回溯算法三部曲 1. 路径选择:记录当前路径 2. 递归探索:进入下…...
【Python 算法】动态规划
本博客笔记内容来源于灵神,视频链接如下:https://www.bilibili.com/video/BV16Y411v7Y6?vd_source7414087e971fef9431117e44d8ba61a7&spm_id_from333.788.player.switch 01背包 计算了f[i1],f[i]就没用了,相当于每时每刻只有…...
nginx的自定义错误页面
正常访问一个不存在的页面是会报404这个错误 我们可以自定义错误页面 error_page 404 /40x.html 然后调用location 最后创建文件 写入你想写的内容 最后实验成功 注意在nginx的配置文件里,注意在加分号 在写完配置时...
制作service列表并打印出来
制作service列表并打印出来 在Linux中,服务(Service)是指常驻在内存中的进程,这些进程通常监听某个端口,等待其他程序的请求。服务也被称为守护进程(Daemon),它们提供了系统所需的各…...
UML 4+1 视图:搭建软件架构的 “万能拼图”
UML 41 视图是一种全面描述软件架构的方法,以下为你详细介绍各个视图: 1.逻辑视图(Logical View) 概述:逻辑视图主要用于展现系统的功能架构,它聚焦于系统提供的功能以及这些功能的逻辑组织方式ÿ…...
tkinter 库(设计图形界面系统)
几何管理的应用 # tkinter 库 是Python的标准GUI库,提供了创建图形用户界面的功能。 tkinter是一个跨平台的GUI库,支持Windows、macOS和Linux等操作系统。它是Python的标准库之一,无需额外安装。 #tkinter.Entry 是 Tkinter 的输入框控件类&…...
WordPress汉主题
WordPress汉主题wphan.com(以下简称WP汉主题)是一个专注于WordPress中文主题与插件开发的专业团队。该团队致力于为中文用户提供高质量的WordPress主题和插件资源,帮助用户轻松创建专业且吸引人的网站。 WP汉主题提供多种功能丰富的WordPress主题,涵盖博…...
在线文档协作工具选型必看:14款产品对比
本文将深入对比14款在线文档协作工具:PingCode; 2. Worktile; 3. 语雀; 4. 金山文档; 5. WPS云文档; 6. Google Docs; 7. 轻雀文档; 8. Microsoft 365 Online; 9. 明道云文档等。 在数字化办公日益普及的今天,企业对高效协同的需求不断升级,在…...
分布式计算Ray框架面试题及参考答案
目录 简述 Ray 的架构设计核心组件及其协作流程 全局控制存储(GCS)在 Ray 中的作用是什么?如何实现高可用性? 对比 Ray 的任务(Task)与 Actor 模型,说明各自适用场景 解释 Ray 的 Object Store 如何实现跨节点数据共享与零拷贝传输 Ray 的分布式调度器如何实现毫秒级…...
Java虚拟机JVM知识点(持续更新)
JVM内存模型 介绍下内存模型 根据JDK8的规范,我们的JVM内存模型可以拆分为:程序计数器、Java虚拟机栈、堆、元空间、本地方法栈,还有一部分叫直接内存,属于操作系统的本地内存,也是可以直接操作的。 详细解释一下 程…...
【计算机网络】HTTP与HTTPS
文章目录 1. HTTP定义2. HTTP交互3. HTTP报文格式3.1 抓包工具-fiddler3.2 抓包操作3.3 报文格式3.3.1 请求报文3.3.2 响应报文 4. URL5. 请求头中的方法6. GET和POST的区别7. HTTP报头7.1 Host7.2 Content_Length7.3 Content_Type7.4 User-Agent(UA)7.5 Referer7.6 Cookie 8 状…...
数据结构:树的5种存储方案详解(C语言完整实现)
数据结构中的树结构常用来存储逻辑关系为 "一对多" 的数据。树结构可以细分为两类,分别是二叉树和非二叉树(普通树),存储它们的方案是不一样的: 二叉树的存储方案有 2 种,既可以用顺序表存储二叉…...
【蓝桥杯】 枚举和模拟练习题
系列文章目录 蓝桥杯例题 枚举和模拟 文章目录 系列文章目录前言一、好数: 题目参考:核心思想:代码实现: 二、艺术与篮球: 题目参考:核心思想:代码实现: 总结 前言 今天距离蓝桥杯还有13天&…...
WebGL图形编程实战【3】:矩阵操控 × 从二维到三维的跨越
上一篇文章:WebGL图形编程实战【2】:动态着色 纹理贴图技术揭秘 仓库地址:github…、gitee… 矩阵操控 矩阵变换 回到前面关于平移缩放、旋转的例子当中,我们是通过改变传递进去的xy的值来改变的。 在进行基础变换的时候&…...
如何把数据从SQLite迁移到PostgreSQL
## 如何把数据从SQLite迁移到PostgreSQL 文章目录 1、DB-Engines 中的SQLite 和 PostgreSQL2、SQLite安装和测试2.1、编译安装SQLite2.2、数据测试 3、Postgresql安装和测试3.1、编译安装postgresql3.2、测试 4、pgloader安装5、数据迁移和验证5.1、准备参数文件5.2、数据迁移…...
Qt使用QGraphicsView绘制线路图————附带详细实现代码
文章目录 0 效果1 核心1.1 简单示例1.1.1 解读 1.2 创建用户交互1.2.1 完整示例 1.3 创建图形元1.3.1 绘制直线1.3.2 绘制贝塞尔曲线1.3.3 绘制图片 1.4 移动的小车 2 使用自定义视图类参考 0 效果 视图中包含线路、道岔、信号灯、火车。 下图为站点信号灯: 下图…...
