16-SlowSqlMonitor82行的慢SQL监控不上APM、不配Skywalking82行代码解决哪些SQL慢的问题。阈值可配、双通道输出日志文件、参数值完整记录——这是元数据引擎自带的轻量监控。这篇拆完82行讲它和已发布那篇《103行代码搞定慢SQL检测》的关系。文章目录16-SlowSqlMonitor82行的慢SQL监控一、82行全貌二、埋点位置三处check调用三、配置项与输出格式四、文件通道的实现取舍五、和已发布《103行慢SQL检测》的关系六、它的边界源码browise-metadata/src/main/java/com/browise/ea/core/monitor/SlowSqlMonitor.java82行一、82行全貌publicclassSlowSqlMonitor{privatefinalEaConfigconfig;// 只依赖配置publicvoidcheck(Stringsql,ListStringparams,longelapsedMs){longthresholdconfig.getSlowSqlThreshold();if(threshold0)return;// ①零/负阈值禁用if(elapsedMsthreshold)return;// ②没超阈值跳过StringmsgformatSlowSql(sql,params,elapsedMs);log.warn(msg);// ③日志通道WARN级别StringlogFileconfig.getSlowSqlLogFile();if(logFile!null!logFile.isEmpty()){writeToFile(logFile,msg);// ④文件通道可选}}}四个行为禁用、跳过、日志告警、文件追加。没有线程、没有定时器、没有采样——纯同步调用谁执行SQL谁check。二、埋点位置三处check调用EaEngine里每个执行方法都在finally前的成功路径调check// executeQuery第06篇longstartSystem.currentTimeMillis();try{// ...executeQuery...slowSqlMonitor.check(builtSql.getSql(),builtSql.getParams(),System.currentTimeMillis()-start);successtrue;returnjson;}// executeUpdate —— 同样的模式// listCodes / codeData —— 内置SQL也监控计时起点在拿连接前——elapsedMs包含了连接获取SQL执行结果集遍历的全过程。连接池耗尽导致的慢会被记成慢SQL——这恰好是对的用户感知的慢就是全链路慢不管慢在哪一层。三、配置项与输出格式browise:metadata:slow-sql-threshold:500# 毫秒0或负禁用slow-sql-log-file:/logs/slow-sql.log# 可选告警输出格式[2026-07-15 10:23:45] slow sql detected, cost1234ms, threshold500ms SQL: select * from (select row_1.*, rownum as rownum_ from (select ... from SYS_USER u where 11 and u.PSN_NAME like %||?||%) row_1) row_ where ... params: [张]三个关键信息全带完整SQL拼好的文本、参数值params列表、耗时阈值对比。拿到这条日志可以直接丢进数据库客户端复现——不用猜是哪条SQL、什么参数慢。四、文件通道的实现取舍privatevoidwriteToFile(StringfilePath,Stringmsg){try(PrintWriterpwnewPrintWriter(newFileWriter(filePath,true))){pw.println(msg);}catch(IOExceptione){log.error(慢SQL日志写入失败: {},filePath,e);}}每次告警开一个FileWriter、写一条、关掉——不做缓冲、不做异步、不做文件轮转。这是刻意选择的最简实现慢SQL是低频事件阈值500ms一天可能几十条——不需要缓冲性能每次开关文件保证进程崩溃不丢日志——缓冲模式崩了缓冲区就没了写失败只log.error不抛——监控绝不能影响业务文件写不进去就只走日志通道如果慢SQL高频到文件IO成为问题——那问题不是监控是数据库已经病了该去看告警而不是改监控。五、和已发布《103行慢SQL检测》的关系之前发过一篇《不上APM103行代码搞定慢SQL检测超100毫秒自动入库》。两者的关系那篇的方案本篇SlowSqlMonitor层次MyBatis拦截器拦截所有Mapper调用EA引擎内嵌只管元数据SQL存储入库表——可查询统计日志文件/日志流目标平台级全系统SQL画像引擎级EA通道的自检阈值100ms固定可配置、可禁用两套并存MyBatis路径BaseEntity/Mapper走拦截器方案EA路径元数据SQL走内嵌监控——browise的两条数据通道各有自己的监控互不覆盖。中间件内置监控的意义引擎的用户不需要额外配置就获得基础可观测性——装配了metadata模块监控自动生效。六、它的边界没有统计聚合——只有单条告警没有最慢TOP10按sqlId聚合这类报表。要做画像得自己解析日志文件或迁移到入库方案。没有上下文——告警里没有哪个用户/哪个页面触发的。CurrentThread里的用户信息没接进来metadata模块不依赖platform模块拿不到CurrentUser——调用链上下文留给上层formbuilder的Controller层日志补充。没有告警升级——不会因为同一SQL连续慢就发通知。notify模块有这个能力但没接——82行的边界就是记录不决策。这些边界是healthy的——监控的第一步是看见82行把看见做到了零成本。后续的聚合、告警、画像建立在看得见的基础上按需加。✅ 亮点82行慢SQL监控的四个行为、埋点在成功路径的计时含义含连接获取的全链路耗时、每次开关文件的崩溃安全取舍、与MyBatis拦截器方案的分工关系。适合给中间件内嵌可观测性的人。扩展方向第57篇667个单测、第58篇18个bug修复记录。