炬鲸 OBSERVE 的日志检索引擎直接复用 SQL 语法,支持字段自动提取、聚合统计与全文检索。本文介绍字段提取方式、常用查询写法、索引性能三原则与落地建议。
日志检索是排障的第一站。多数日志平台要么只支持关键词模糊匹配,要么逼你学一套自创的查询 DSL。炬鲸 OBSERVE 的检索引擎直接复用 SQL 语法——运维和开发不用再记一套新语法,上手成本接近零。本文把字段提取、查询写法和性能要点一次讲清楚。
SQL 是工程师的通用语言:DBA 会写,后端会写,运维也多少会写。自创 DSL 的问题在于语法不通用、资料少、换人接手要重新学;而 SQL 有几十年积累的教材、示例和社区问答,搜 GROUP BY 语法立刻能找到答案。
更重要的是,SQL 天然贴合日志的两类操作:过滤(WHERE)和聚合(GROUP BY)。日志排查九成场景就是"先过滤出相关记录,再按维度统计分布",SQL 一条语句就能表达清楚,不必拆分多个操作步骤。还有一个隐藏好处:查出来的结果可以直接接进 BI 或报表工具,不用再导一遍数据。
能写 SQL 的前提是日志被拆成了字段。炬鲸 OBSERVE 在采集阶段自动做三件事:
span.attributes.http.status_code;key=value 或 key: value 格式自动拆成字段,常见于 Nginx、HAProxy 这类访问日志;三种方式可以叠加:同一条日志里,JSON 部分走 JSON 解析,前缀部分走正则,互不冲突。例如给 2026-08-31 10:00:01 order-service ERROR [trace=abc123] payment timeout 配置正则 \[trace=(?P<trace_id>\w+)\],就能直接用 WHERE trace_id = 'abc123' 检索。字段提取在写入时完成,检索阶段不用重复解析,这也是查询能快到秒级的原因之一。
有了字段,就可以写查询。比如一条 Nginx 日志:
{"time":"2026-08-31T10:00:00Z","status":502,"upstream":"10.0.3.21:8080","latency_ms":1200}
你可以直接写:
SELECT count(*), upstream
FROM nginx_access
WHERE status = 502
AND time > now() - interval '1 hour'
GROUP BY upstream
ORDER BY count(*) DESC
LIMIT 20
这条查询回答了一个具体问题:"过去一小时,哪些上游实例返回了 502,各多少次。"status、upstream 都是自动提取的字段,无需预先定义 schema,也不用写字段映射。
全文检索同样保留:WHERE message LIKE '%timeout%' 或 WHERE message CONTAINS 'connection reset'。聚合函数覆盖 count、avg、max、min、percentile,可以直接算 P95、P99 延迟:
SELECT upstream, percentile(latency_ms, 99) AS p99
FROM nginx_access
WHERE time > now() - interval '15 minute'
GROUP BY upstream
SQL 检索最容易踩的坑是性能,写查询时注意三点:
WHERE time > ... 让引擎只扫相关分片。不带时间范围的查询会被引擎默认限制在最近 24 小时,并给出提示。request_id、trace_id 这种每个值只出现一次的字段分组,会产生海量分组,慢且无意义。先想清楚这个维度有没有聚合价值。status = 502 这类等值过滤缩小候选集,再做昂贵的正则匹配,查询优化器会自动处理顺序,但把正则写进 WHERE 仍比写在外层便宜。把常用排查语句存成"查询模板"团队共享。比如"过去 15 分钟错误率 Top 上游""某 trace 关联的所有日志""某服务慢请求分布",存成模板后值班同学点开即用,不必每次现写 SQL。模板建议配上清晰的命名和一句"何时用"的说明,新人翻模板列表就知道该点哪个。
检索只是第一步。查出的日志可以直接"下钻到 trace",也可以"基于结果创建告警"——把检索结果固化成告警条件,是从被动排障转向主动发现的关键一步。例如把 SELECT count(*) WHERE status >= 500 设成每 5 分钟跑一次、超过阈值就通知,等于给错误率装了一个持续的探针。