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

像写 SQL 一样查日志:炬鲸 OBSERVE 的日志检索引擎

炬鲸 OBSERVE 内置类 SQL 检索语法,配合采集端 Pipeline 字段解析与倒排索引,在十亿级日志上实现秒级聚合查询。本文介绍语法用法、字段来源与查询性能优化建议。

为什么还用正则翻日志

运维排查线上问题,一半时间耗在找日志上。grep 大文件、翻正则、等滚动刷新——这些操作在几百台机器、每天几十亿条日志面前基本失效。日志平台的核心价值不是"存得下",而是"查得快、查得准"。

炬鲸 OBSERVE 的日志检索没有走传统的关键词加过滤条件路线,而是直接内置了一套类 SQL 的查询语法。你不需要记住某个平台私有的 DSL,会用 SQL 就能上手。对熟悉 MySQL 或 ClickHouse 的工程师来说,学习成本几乎为零。

类 SQL 语法长什么样

以 Nginx 访问日志为例,一条结构化日志包含 status、upstream_time、request_uri 等字段。按状态码统计最近一小时:

SELECT status, count(*) AS cnt
FROM nginx_access
WHERE time >= now() - interval '1 hour'
GROUP BY status
ORDER BY cnt DESC

再比如找出响应最慢的 20 个接口:

SELECT request_uri, max(upstream_time) AS slowest
FROM nginx_access
WHERE upstream_time > 2
GROUP BY request_uri
ORDER BY slowest DESC
LIMIT 20

语法覆盖了 SELECT、WHERE、GROUP BY、ORDER BY、LIMIT,以及 count、sum、avg、max、min、percentile 等聚合函数。要算接口耗时的 P99,直接写 percentile(upstream_time, 99) 即可,不用把数据拉到本地再算。

子查询和 JOIN 也已上线。跨日志流做关联分析时,可以像这样把访问日志和业务日志按请求 ID 关联:

SELECT a.request_id, b.user_id, a.upstream_time
FROM nginx_access a
JOIN app_log b ON a.request_id = b.request_id
WHERE a.status >= 500
  AND a.time >= now() - interval '10 minute'

字段怎么来

SQL 能查的前提是字段结构化。炬鲸 OBSERVE 在采集端内置了 Pipeline 解析器,支持 JSON、正则、分隔符、key-value 四种解析方式。以 Go 服务为例,配置一行采集规则即可把 stdout 的 JSON 日志拆成独立字段:

input:
  tail:
    paths: ["/var/log/app/*.log"]
pipeline:
  - json:
      source: message
  - geoip:
      source: remote_ip

解析后的字段进入倒排索引,同时保留原始 message,方便回看上下文。字段类型(string、number、ip、boolean)会自动推断:"200" 这类字符串会被识别为 number,"10.0.0.1" 识别为 ip,这样数值字段才能参与排序和聚合,IP 字段才能按网段过滤。类型推断错了也没关系,在字段管理页可以手动覆盖某个字段的类型。

和 grep、ES DSL 比,差别在哪

习惯 grep 的工程师第一次用会不习惯两件事:一是结果默认按时间倒序,而不是按文件里的出现顺序;二是查询有超时限制(默认 30 秒),一条 LIKE '%x%' 的裸查询在十亿级数据上会被直接拦下来。这不是限制,是保护——它逼着你在查询前先想清楚时间范围和关键词。

如果之前用的是 Elasticsearch 的 Query DSL,迁移成本也很低。OBSERVE 的查询面板支持"SQL 模式"和"可视化模式"一键切换:不会写 SQL 就点选字段和条件,面板自动生成 SQL,生成的 SQL 还能复制出来贴到告警规则里复用。

查询性能的几个关键点

为了让 SQL 在十亿级日志上仍能秒级返回,检索层做了三件事:按时间分片(bucket)的列式存储、字段级倒排索引、以及查询计划下推到分片。实际使用中,一个小时的日志按 status 聚合,P95 延迟在 1 秒以内。

几个实践建议:

  • WHERE 条件里优先带时间范围,能显著缩小扫描区间;
  • 避免 LIKE '%keyword%' 这种前缀通配,改用倒排索引支持的关键词匹配;
  • 聚合查询尽量限定在单日志流,跨流 JOIN 会触发更重的计算;
  • 高频检索字段(如 request_id、user_id)建议开启"字段索引加速",写入会多花一点资源,查询能快一个数量级;
  • 固定刷新周期的大屏,把时间范围固化在收藏查询里,别让它跟着全局时间选择器漂移。

这套检索引擎同时给告警和链路两个模块复用,你在告警规则里写的过滤表达式,和检索语法是一致的,不用学两套东西。