4. Tempo查询语言基础:TraceQL语法入门、Span选择器、属性过滤、时间范围
TraceQL 是 Grafana Tempo 原生的结构化查询语言,专为 Trace 数据设计。与 PromQL(指标)或 LogQL(日志)不同,TraceQL 直接操作 Span 的结构化属性,允许你通过 Span 选择器、属性过滤和时间范围精确锁定目标 Trace,从而大幅缩短 MTTR 复盘口径的查询时间。
4.1 TraceQL 核心语法结构
TraceQL 的查询由三个基本组件构成:Span 选择器、属性过滤器和管道操作。其基础语法模式如下:
{ span.selector } | attribute_filter | pipeline_operation
| 组件 | 说明 | 示例 |
|---|---|---|
| Span 选择器 | 用花括号 {} 包裹,定义要匹配的 Span 集合 |
{ span.http.method = "GET" } |
| 属性过滤器 | 在管道符 | 后使用,进一步缩小结果范围 |
| span.http.status_code >= 500 |
| 管道操作 | 对结果进行聚合、计数或取最新 Trace | | count() 或 | latest(10) |
{} 选择器缩小到错误 Span,再通过管道过滤出高延迟或异常状态码的 Trace,避免扫描全量数据。
4.2 Span 选择器详解
Span 选择器是 TraceQL 的入口,决定了查询的起点。它支持按 Span 名称、服务名称、Span 状态和资源属性进行匹配。
4.2.1 基础选择器语法
{ span.service.name = "checkout-service" }
{ span.name = "HTTP POST /api/order" }
{ span.status = error }
4.2.2 选择器操作符
| 操作符 | 含义 | 示例 |
|---|---|---|
= |
精确匹配 | { span.http.method = "POST" } |
!= |
不等于 | { span.http.method != "GET" } |
=~ |
正则匹配 | { span.name =~ ".*/order.*" } |
!~ |
正则不匹配 | { span.name !~ "health.*" } |
> / < |
数值比较 | { span.duration > 2s } |
=~ 和 !~ 会显著增加查询开销。在 MTTR 复盘场景中,尽量使用精确匹配 = 或数值范围过滤,避免在大量 Span 上执行正则。
4.3 属性过滤与管道操作
属性过滤在管道符 | 之后使用,可以对选择器结果进行二次筛选。管道操作则用于聚合和排序。
4.3.1 常用属性过滤
{ span.service.name = "payment-service" }
| span.http.status_code >= 500
| span.duration > 1s
上述查询的含义:先选择 payment-service 的所有 Span,再过滤出 HTTP 状态码 >= 500 且持续时间超过 1 秒的 Span。
4.3.2 管道聚合操作
| 操作 | 说明 | MTTR 场景用途 |
|---|---|---|
count() |
统计匹配的 Span 数量 | 快速评估错误 Span 的爆发量 |
avg() |
计算数值属性的平均值 | 计算错误 Span 的平均延迟 |
latest(N) |
返回最近的 N 条 Trace | 获取最新违约 Trace 用于复盘 |
by() |
按属性分组聚合 | 按服务或状态码分组统计错误 |
4.3.3 分组聚合示例
{ span.status = error }
| count() by(span.service.name)
该查询返回每个服务中错误 Span 的数量,帮助快速定位哪个服务是 SLO 违约的“重灾区”。
4.4 时间范围与 TraceQL 结合
TraceQL 查询必须与时间范围配合使用。Tempo 支持两种时间范围指定方式:查询参数和相对时间语法。
4.4.1 查询参数方式(Grafana UI)
在 Grafana Explore 中,通过顶部时间选择器设置时间范围,TraceQL 查询会自动应用该范围。例如选择 Last 15 minutes,则查询只扫描最近 15 分钟的 Span 数据。
4.4.2 相对时间语法(API / 脚本)
在 Tempo API 或自动化脚本中,使用 start 和 end 参数指定 Unix 时间戳(纳秒精度):
start=1728000000000000
end=1728086400000000
4.4.3 MTTR 复盘中的时间范围策略
| 复盘阶段 | 推荐时间范围 | 说明 |
|---|---|---|
| 实时告警确认 | Last 5 minutes | 快速确认当前是否正在发生违约 |
| 根因定位 | Last 1 hour | 覆盖告警触发前后的完整上下文 |
| MTTR 复盘 | 违约时间点 ± 30 min | 精确聚焦违约窗口,减少无关数据干扰 |
| 趋势分析 | Last 24 hours | 观察错误模式的周期性或渐进性变化 |
4.5 TraceQL 查询流程架构
下图展示了从 TraceQL 查询输入到最终 Trace 结果返回的完整数据流,帮助理解各组件在查询链路中的角色。
4.6 实战:MTTR 复盘口径查询示例
假设某 SLO 违约发生在 2025-06-01 14:30 UTC,目标服务为 order-service,错误类型为 HTTP 500。以下 TraceQL 查询用于快速定位根因 Trace:
{ span.service.name = "order-service" && span.http.status_code >= 500 }
| span.duration > 2s
| latest(20)
该查询的含义:
- 选择器:匹配
order-service中所有 HTTP 状态码 >= 500 的 Span - 过滤:只保留持续时间超过 2 秒的 Span(排除瞬时错误)
- 管道:返回最近的 20 条完整 Trace,用于人工复盘
4.7 常见错误与避坑指南
| 错误模式 | 错误示例 | 正确写法 | 说明 |
|---|---|---|---|
| 选择器内缺少花括号 | span.service.name = "x" |
{ span.service.name = "x" } |
选择器必须用 {} 包裹 |
| 属性名拼写错误 | { span.http.method = "POST" } |
{ span.http.method = "POST" } |
注意属性名区分大小写 |
| 时间范围过大 | 查询未指定时间范围 | 设置 ±30 分钟窗口 | 全量扫描会导致超时或高成本 |
| 管道顺序错误 | | count() | span.duration > 1s |
| span.duration > 1s | count() |
过滤必须在聚合之前 |
4.8 TraceQL 与 PromQL 对比
理解 TraceQL 与 PromQL 的差异,有助于 SRE 团队在指标和 Trace 之间建立统一的排查思维。