炬鲸 OBSERVE 把 SQL 查询能力带进日志检索:字段过滤、管道聚合、倒排索引加速,替代 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 才不会变成字符串比较。
检索器在写入阶段做两件事:按时间切分到分区,按字段值建倒排索引。
service = "order" 直接命中包含该值的文档 ID 集合,复杂度从 O(n) 降到接近 O(命中数)。实测单节点 8 核 32G 环境,10 亿条日志里做带两个条件的过滤查询,P99 延迟稳定在 800ms 以内。
status >= 500 | stats count() as err by service
parse "duration_ms=%{number:ms}" | where ms > 2000 | top ms limit 10
status >= 500 | bucket span=5m | stats count() by _time
建议把常用查询存成模板,挂到告警或 Dashboard,出问题时点一下就能看到结果,不用临时拼语法。