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

像写 SQL 一样查日志:炬鲸 OBSERVE 日志检索详解

炬鲸 OBSERVE 把 SQL 查询能力带进日志检索:字段过滤、管道聚合、倒排索引加速,替代 grep 硬扫。本文拆解语法设计、索引机制与四个实战查询。

为什么 grep 不够用

排查线上问题时,最常见的动作是 grep 某个关键字,然后 tail 几百行看上下文。这种方式在小规模日志里勉强能用,但三个问题会随日志量增长迅速放大。

第一,grep 是顺序扫描,没有索引。一个 50GB 的单日日志文件,扫一次要几分钟,多扫几次排查就变成等待。第二,grep 只做文本匹配,做不了结构化过滤,比如"找出 5xx 错误里耗时超过 2 秒的请求"这种问题,grep 表达不了。第三,grep 的结果无法聚合,你想知道"每个服务的错误率"或者"错误按时间分布的柱状图",还得再写脚本处理。

炬鲸 OBSERVE 的思路是把日志当数据表来查:先定义字段,再让检索器理解过滤、排序和聚合。

语法设计:字段过滤 + 管道聚合

查询分为三段,先过滤、再处理、最后聚合:

status >= 500 AND service = "order"
| parse duration_ms
| stats count() by service, status
  • 过滤段:status >= 500、service = "order"、message like "%timeout%",支持 AND/OR/NOT 和括号。
  • 管道段:parse 从文本里提取字段,extend 派生新字段,where 二次过滤。
  • 聚合段:stats、bucket、top 直接输出结果,不再需要导到 Excel。

所有字段都可以自动类型推断。日志里的 duration_ms=183 会被识别为数值而不是字符串,status=500 识别为整数,timestamp 识别为时间。这样 status >= 500 才不会变成字符串比较。

索引与加速:不靠硬扫

检索器在写入阶段做两件事:按时间切分到分区,按字段值建倒排索引。

  • 时间分区让"查最近 15 分钟"只读两个分区,而不是全量扫描。
  • 倒排索引让 service = "order" 直接命中包含该值的文档 ID 集合,复杂度从 O(n) 降到接近 O(命中数)。
  • 高频字段默认建索引,冷字段按需开启,避免索引膨胀拖慢写入。

实测单节点 8 核 32G 环境,10 亿条日志里做带两个条件的过滤查询,P99 延迟稳定在 800ms 以内。

四个拿来就用的查询

  1. 按服务统计 5xx 错误率:
status >= 500 | stats count() as err by service
  1. 找慢请求 TOP 10:
parse "duration_ms=%{number:ms}" | where ms > 2000 | top ms limit 10
  1. 错误按 5 分钟桶分布,定位故障开始时刻:
status >= 500 | bucket span=5m | stats count() by _time
  1. 关联两个服务:先查网关的 trace_id,再用它过滤下游日志,把一次请求的全链路拼出来。

建议把常用查询存成模板,挂到告警或 Dashboard,出问题时点一下就能看到结果,不用临时拼语法。