← 返回文章列表
产品动态 4 分钟阅读 炬鲸团队

用 SQL 检索日志:像查数据库一样排查线上问题

关键词检索解决不了聚合分析。炬鲸 OBSERVE 内置类 SQL 语法,支持 SELECT、WHERE、GROUP BY 与管道处理,字段自动解析、无需预建索引。本文用几个实战查询演示如何定位慢接口与异常会话。

日志平台的检索框,大多数团队还在拿它做关键词过滤。查"最近几分钟有没有报错"没问题,但一旦要回答"哪个接口最慢""某个用户这次操作到底经过了哪些服务",关键词检索就力不从心了。

炬鲸 OBSERVE 在日志检索里内置了一套类 SQL 语法,支持 SELECT、WHERE、GROUP BY、ORDER BY 和管道处理。字段会从日志里自动解析,不需要提前建索引,也不用为每种日志格式单独写正则。

从三条查询开始

最简单的过滤,查最近 5 分钟所有 5xx 错误:

SELECT * FROM logs
WHERE status >= 500
  AND time > now() - 5m

按接口聚合,找出过去一小时最慢的 10 个接口:

SELECT api, count(*) AS cnt, p95(latency) AS p95
FROM logs
WHERE time > now() - 1h
GROUP BY api
ORDER BY p95 DESC
LIMIT 10

p95() 是内置聚合函数;latency 来自日志里自动解析出的数值字段。只要日志里打印了 latency=182 这类键值对,平台会把它转成数值列,可以直接参与聚合,单位统一为毫秒。

再比如定位某个用户的完整操作路径:

SELECT trace_id, min(time) AS start_ts, max(time) AS end_ts
FROM logs
WHERE user_id = 'u_88213'
  AND time > now() - 30m
GROUP BY trace_id
ORDER BY start_ts

管道语法:边查边缩小范围

和一次性写完整条 SQL 不同,管道语法适合排查时逐层逼近。用 | 串联多个操作,上一步的输出是下一步的输入:

FROM logs
| WHERE status >= 400
| SELECT api, status, count(*) GROUP BY api, status
| ORDER BY count(*) DESC
| LIMIT 20

排查时可以随时删掉后面的步骤先看中间结果,不用一开始就想清楚最终答案长什么样。

字段提取:把非结构化日志变成可查询的列

不是所有日志都是 JSON。假设 Nginx 访问日志是这样的:

192.168.1.10 - - [13/Sep/2026:10:02:11] "POST /api/order 200" 0.182

用提取表达式把关键段拆成字段:

FROM logs
| PARSE 'ip - - [date] "method path status" latency'

之后就能直接 WHERE latency > 1 或按 path 分组统计。提取规则可以保存为模板,同格式日志自动套用,全团队共用一套口径,避免每个人各写各的正则。

落地建议

  • 高频查询保存成"视图",告警规则直接引用视图,保证排查口径和告警口径一致。
  • 聚合结果可一键转成图表挂到仪表盘,值班先看大盘再下钻到明细。
  • 字段名统一用英文下划线,和代码里打印的键保持一致,减少二次映射和沟通成本。
  • 检索默认命中热数据层,更早的数据在归档层,查询时显式指定时间范围即可跨层检索,无需手工切换。