TraceQL
TraceQL 受 PromQL 和 LogQL 的启发,是一种为 Tempo 中选择追踪而设计的查询语言。目前,TraceQL 查询可以基于以下内容选择追踪:
- Span 和资源属性、时间以及时长
- 基本聚合:
count()、avg()、min()、max()和sum()
阅读博文 认识 TraceQL,了解 TraceQL 及其功能的简介。
这里应该有一个视频,但由于某种原因没有。可能是我们输入的 ID 有误(抱歉!),也可能是 Vimeo 服务中断。如果是后者,我们预计他们很快会恢复正常。在此期间,请访问我们的博客!
在可能的情况下,TraceQL 语言使用与 PromQL 和 LogQL 类似的语法和语义。
查看 Tempo 发布说明,了解 TraceQL 的最新更新。
要求
TraceQL 需要 Parquet 列式格式,该格式默认启用。有关 Parquet 的信息,请参阅 Apache Parquet 后端文档。
使用 TraceQL 查询
您可以在 Tempo 数据源中使用 TraceQL 查询编辑器和查询构建器来构建查询并下钻到结果集。编辑器和构建器可在 Grafana Explore 的 Tempo 数据源中使用。

此外,您可以使用 Traces Drilldown 来调查您的追踪数据,而无需编写 TraceQL 查询。有关更多信息,请参阅 Traces Drilldown 文档。
流式查询结果
通过将结果流式传输到客户端,您可以在整个查询完成之前开始查看与查询匹配的追踪。
查询前端的 GRPC 流式 API 端点允许客户端从 Tempo 流式传输搜索结果。tempo-cli 也使用此流式端点。有关更多信息,请参阅 Tempo CLI 文档。
要在 Grafana 中使用流式传输,必须在 Tempo 中启用 stream_over_http_enabled: true。有关信息,请参阅 Tempo GRPC API。
构造 TraceQL 查询
在 TraceQL 中,查询是一个表达式,它一次对一个追踪进行求值。查询被构造为一组链式表达式,称为管道。管道中的每个表达式选择或丢弃要包含在结果集中的 spanset。例如:
{ span.http.status_code >= 200 && span.http.status_code < 300 } | count() > 2在此示例中,搜索将追踪范围缩小到以下 span:
http.status_code在200到299的范围内,并且- 一个追踪中匹配的 span 数量大于 2。
查询选择 span 集,并通过聚合器和条件的管道对其进行过滤。如果对于给定的追踪,此管道生成一个 spanset,则将其包含在查询结果中。
有关 TraceQL 指标查询的示例,请参阅 TraceQL 指标查询。
查找特定操作的追踪
假设您想查找特定操作的追踪,则应指定操作名称(span 属性 name)和包含此操作的服务名称(资源属性 service.name)以进行适当过滤。在下面的示例中,追踪是根据 resource.service.name 值 frontend 和 span name 值 POST /api/order 进行过滤的。
{resource.service.name = "frontend" && name = "POST /api/orders"}当将相同的 Grafana stack 用于多个环境(例如,production 和 staging)或具有共享相同名称但通过其命名空间区分的服务时,查询如下所示:
{
resource.service.namespace = "ecommerce" &&
resource.service.name = "frontend" &&
resource.deployment.environment = "production" &&
name = "POST /api/orders"
}查找具有特定结果的追踪
此示例查找操作 POST /api/orders 上所有包含出错 span 的追踪:
{
resource.service.name="frontend" &&
name = "POST /api/orders" &&
status = error
}此示例查找操作 POST /api/orders 上所有返回 HTTP 5xx 错误的追踪:
{
resource.service.name="frontend" &&
name = "POST /api/orders" &&
span.http.status_code >= 500
}查找具有特定行为的追踪
您可以使用查询对追踪的多个 span 进行过滤。此示例查找访问数据库的 GET /api/products/{id} 操作的所有追踪。这是一项方便的请求,用于识别缓存问题引起的数据库异常访问率。
{span.service.name="frontend" && name = "GET /api/products/{id}"} && {.db.system="postgresql"}查找经过 production 和 staging 实例的追踪
此示例查找经过 production 和 staging 实例的追踪。这是一项方便的请求,用于识别跨生产和非生产环境的配置错误和泄露。
{ resource.deployment.environment = "production" } && { resource.deployment.environment = "staging" }查找带有数组的追踪
TraceQL 自动查询数组中包含的数据。vParquet4 及更高版本支持数组。
如果 span.foo 是一个数组且包含值 bar,则此查询将找到它。
{ span.foo = "bar" }您可以使用正则表达式匹配数组的多个值 {span.http.request.header.Accept=~"application.*"},并使用 .* 正则表达式获取数组的所有值。
{span.http.request.header.Accept=~".*"}使用结构运算符
查找包含 frontend 服务,且该服务或下游服务包含设置了错误的 span 的追踪。
{ resource.service.name="frontend" } >> { status = error }查找所有以 productcatalogservice 结尾的叶子 span。
{ } !< { resource.service.name = "productcatalogservice" }查找 productcatalogservice 和 frontend 是否为兄弟。
{ resource.service.name = "productcatalogservice" } ~ { resource.service.name="frontend" }其他示例
查找 http 状态为 200 的服务,并列出 span 所属的服务名称以及返回的追踪。
{ span.http.status_code = 200 } | select(resource.service.name)查找任何设置了未指定范围的 deployment.environment 属性为 production 和 http.status_code 属性为 200 的追踪。
{ .deployment.environment = "production" && span.http.status_code = 200 }查找任何追踪,其中 span 设置了 deployment.environment 资源属性为 production,并且 span 具有 http.status_code 属性为 200。在前面的示例中,所有条件都必须在同一个 span 上为 true。这些条件可以在不同的 span 或同一个 span 上为 true。
{ resource.deployment.environment = "production" } && { span.http.status_code = 200 }查找任何追踪,其中任何 span 设置了 http.method 属性为 GET 和 status 属性为 ok,并且任何其他 span 设置了 http.method 属性为 DELETE,但没有设置 status 属性为 ok。
{ span.http.method = "GET" && status = ok } && { span.http.method = "DELETE" && status != ok }查找任何具有匹配正则表达式 prod-.* 的 deployment.environment 属性和设置了 http.status_code 属性为 200 的追踪。
{ resource.deployment.environment =~ "prod-.*" && span.http.status_code = 200 }选择 Span
在 TraceQL 中,花括号 {} 总是从可用的追踪中选择一组 span。花括号通常与条件配对,以减少获取的 span 数量。
TraceQL 区分两种类型的 span 数据:内在属性 (intrinsics),它们是 span 的基础;以及属性 (attributes),它们是可定制的键值对。您可以使用内在属性和属性来构建过滤器和选择 span。
内在字段对于范围来说是基础性的。内在字段是固有存在的,与开发者添加的其他键值对(属性)不同。
内在属性总是使用 <scope>: 表示。请参阅 内在属性表 了解所有当前的内在属性。
内在属性示例
{ span:name = "foo" }
{ event:name = "foo" }
{ trace:id = "1234" }
{ link:traceID = "1234" }自定义属性以 <scope>. 为前缀,例如 span.、resource.、link. 或 event。资源没有内在值。它只有自定义属性。
属性用点号 (.) 分隔,而内在字段使用冒号 (:)。trace 范围只是一个内在属性,在追踪级别没有任何自定义属性。
属性示例
{ span.foo = "bar" }
{ resource.foo = "bar" }
{ link.foo = "bar" }
{ event.foo = "bar" }内在字段
下表显示了当前可用的范围内在字段
| 字段 | 类型 | 定义 | 示例 |
|---|---|---|---|
span:status | 状态枚举 | 状态:error, ok, 或 unset | { span:status = ok } |
span:statusMessage | string | span 状态的可选文本描述 | { span:statusMessage = "Forbidden" } |
span:duration | 时长 | span 的结束时间 - 开始时间 | { span:duration > 100ms } |
span:name | string | 操作或 span 名称 | { span:name = "HTTP POST" } |
span:kind | 种类枚举 | 种类:server, client, producer, consumer, internal, unspecified | { span:kind = server } |
span:id | string | 使用十六进制字符串表示的 span ID | { span:id = "0000000000000001" } |
trace:duration | 时长 | 追踪中 span 的最大结束时间 - 最小开始时间 | { trace:duration > 100ms } |
trace:rootName | string | 如果存在,追踪中根 span 的名称 | { trace:rootName = "HTTP GET" } |
trace:rootService | string | 如果存在,追踪中根 span 的服务名称 | { trace:rootService = "gateway" } |
trace:id | string | 使用十六进制字符串表示的追踪 ID | { trace:id = "1234567890abcde" } |
event:name | string | 事件名称 | { event:name = "exception" } |
event:timeSinceStart | 时长 | 事件相对于 span 开始时间的时间 | { event:timeSinceStart > 2ms} |
link:spanID | string | 使用十六进制字符串表示的链接 span ID | { link:spanID = "0000000000000001" } |
link:traceID | string | 使用十六进制字符串表示的链接追踪 ID | { link:traceID = "1234567890abcde" } |
instrumentation:name | string | 仪表化范围名称 | { instrumentation:name = "grpc" } |
instrumentation:version | string | 仪表化范围版本 | { instrumentation:version = "1.0.0" } |
追踪级别内在属性 trace:duration、trace:rootName 和 trace:rootService 对于同一追踪中的所有 span 都是相同的。此外,这些内在属性性能显著更高,因为它们检查的数据比 span 级别内在属性少得多。应尽可能优先使用它们而非 span 级别内在属性。
有时您可能希望按追踪级别内在属性进行搜索。例如,使用 span:name 会查找追踪中 span 的名称。如果您希望按追踪名称 perf 进行搜索,请使用 trace:rootName 进行匹配。
此示例搜索所有名为 service-name 的 Kubernetes 集群,这些集群包含根名称包含 perf 的 span。
{ resource.k8s.cluster.name="service-name" && trace:rootName !~ ".*perf.*"}属性字段
TraceQL 支持这些不同的属性范围:span 属性、资源属性、事件属性、链接属性和仪表化范围属性。
通过在 Grafana UI 中展开 span,您可以看到其 span 属性(屏幕截图中的 1)和资源属性(屏幕截图中的 2)。

属性字段派生自 span 并且可以定制。进程和 span 属性类型 由属性本身定义,而内在字段具有内置类型。您可以引用 span 或 span 资源的动态属性(也称为标签)。
查询中的属性以 span、resource、event 或 link 范围开头。例如,根据您想要查询的内容,可以使用 span.http 或 resource.namespace。这提供了显著的性能优势,因为 Tempo 只扫描您感兴趣的数据。
要查找使用 GET HTTP 方法的追踪,您的查询可以如下所示
{ span.http.method = "GET" }有关属性和资源的更多信息,请参阅 OpenTelemetry Resource SDK。
示例
查找经过 production 环境的追踪
{ resource.deployment.environment = "production" }查找连接到 Postgres 或 MySQL 数据库的任何数据库连接字符串
{ span.db.system =~ "postgresql|mysql" }您可以使用 event 范围来查询 span 中发生的事件。span 事件是 span 持续期间的一个独特时间点。虽然 span 有助于构建服务的结构层级,但 span 事件可以提供更深层次的粒度,帮助您更快地调试应用程序并保持最佳性能。要了解如何使用 span 事件,请阅读 什么是 Span 事件? 博文。
您可以在 span 事件中查询异常
{ event.exception.message =~ ".*something went wrong.*" }如果您已为 span 链接对追踪进行仪表化,则可以使用 link 范围查询链接数据。span 链接将一个 span 与一个或多个具有因果关系的其他 span 相关联。有关 span 链接的更多信息,请参阅 Open Telemetry 项目中的 Span 链接文档。
您可以在链接中搜索属性
{ link.opentracing.ref_type = "child_of" }仪表化范围允许您查询 仪表化范围 字段,以便您可以根据追踪的仪表化位置和方式进行过滤和探索。此范围的主要用途是根据生成数据的各种库和客户端查询追踪数据。
查找仪表化范围编程语言
{ instrumentation.language = "java" }查找为给定服务生成仪表化的库
{ resource.service.name = "foo" } | rate() by (instrumentation:name)Tempo 2.7 发布视频 从 30 秒开始演示和解释了 instrumentation 范围。
无范围属性字段
如果您不确定请求的属性是否存在于 span 或资源上,则属性可以没有范围。如果可能,请使用范围属性而不是无范围属性。范围属性提供更快的查询结果。
例如,查找设置为 critical 的 sla 属性的追踪:
{ .sla = "critical" }带引号的属性名称
属性名称可能包含终端字符,例如点号 (.)。要搜索包含终端字符的 span 属性,可以使用带引号的属性语法。将带引号的属性用双引号括起来,例如,"示例一"。双引号之间的所有字符都被视为属性名称的一部分。
示例
要查找属性名称为 attribute name with space 的 span,请使用以下查询:
{ ."attribute name with space" = "value" }您可以将带引号的属性语法与非带引号的属性语法一起使用,以下是有效的 TraceQL 查询:
{ span.attribute."attribute name with space" = "value" }注意
目前,仅支持
\"和\\转义序列。
比较运算符
比较运算符用于测试表达式中的值。
已实现的比较运算符包括:
=(等于)!=(不等于)>(大于)>=(大于或等于)<(小于)<=(小于或等于)=~(正则表达式匹配)!~(正则表达式不匹配)
TraceQL 使用 Golang 正则表达式。像 https://regex101.com/ 这样的在线正则表达式测试网站方便用于验证 TraceQL 查询中使用的正则表达式。所有正则表达式都被视为完全锚定的。
正则表达式在两端都被锚定。这种锚定使查询更快,并与 PromQL 的行为相匹配,PromQL 中的正则表达式也是完全锚定的。
未锚定的查询,例如:{ span.foo =~ “bar” } 现在被视为:{ span.foo =~ “^bar$” }。
如果您在 Grafana 仪表盘中使用带有正则表达式的 TraceQL,并且希望获得未锚定的行为,请更新查询以使用未锚定版本,例如 { span.foo =~ “.bar.”}。
例如,查找 span 中 http.status_code 属性大于 400 但小于等于 500 的所有追踪:
{ span.http.status_code >= 400 && span.http.status_code < 500 }这对于字符串类型的 http.status_code 值也同样适用,使用词典排序:
{ span.http.status_code >= "400" }查找 http.method 属性为 GET 或 DELETE 的所有追踪:
{ span.http.method =~ "DELETE|GET" }查找 any_attribute 不为 nil 或 span 中存在 any_attribute 的所有追踪:
{ .any_attribute != nil }字段表达式
字段还可以以各种方式组合,以允许更灵活的搜索条件。字段表达式是多个字段的组合,它们定义了必须匹配的所有条件才能返回结果。
示例
查找具有 success http.status_code 代码的追踪
{ span.http.status_code >= 200 && span.http.status_code < 300 }查找使用了 DELETE HTTP 方法且内在 span 状态不是 OK 的追踪:
{ span.http.method = "DELETE" && status != ok }两个表达式都要求在同一个 span 上所有条件都为 true。一对 {} 内的整个表达式必须在单个 span 上计算为 true,才能将其包含在结果集中。
在上面的示例中,如果一个 span 包含设置为 DELETE 的 .http.method 属性,并且该 span 也包含设置为 ok 的 status 属性,则该追踪将不包含在返回结果中。
组合 Spansets
Spanset 运算符允许您从追踪中选择不同的 span 集,然后在它们之间进行判断。
逻辑
这些 spanset 运算符在 span 集之间执行逻辑检查。
{condA} && {condB}- 与运算符 (&&) 检查两个条件是否都找到了匹配项。{condA} || {condB}- 或运算符 (||) 检查任一条件是否找到了匹配项。
例如,查找经过两个特定 cloud.region 的追踪:
{ resource.cloud.region = "us-east-1" } && { resource.cloud.region = "us-west-1" }注意上一个示例与此示例之间的区别:
{ resource.cloud.region = "us-east-1" && resource.cloud.region = "us-west-1" }第二个表达式不返回任何追踪,因为单个 span 不可能同时将 resource.cloud.region 属性设置为两个区域值。
结构
这些 spanset 运算符查看追踪的结构以及 span 之间的关系。结构运算符总是返回运算符右侧的匹配项。
{condA} >> {condB}- 后代运算符 (>>) 查找与{condA}匹配的 span 的后代 span 中与{condB}匹配的 span。{condA} << {condB}- 祖先运算符 (<<) 查找与{condA}匹配的 span 的祖先 span 中与{condB}匹配的 span。{condA} > {condB}- 子运算符 (>) 查找与{condA}匹配的父 span 的直接子 span 中与{condB}匹配的 span。{condA} < {condB}- 父运算符 (<) 查找与{condA}匹配的子 span 的直接父 span 中与{condB}匹配的 span。{condA} ~ {condB}- 兄弟运算符 (~) 查看与{condB}匹配的 span,这些 span 至少有一个与{condA}匹配的兄弟。
例如,查找特定 HTTP API 与特定数据库交互的追踪:
{ span.http.url = "/path/of/api" } >> { span.db.name = "db-shard-001" }联合结构
这些 spanset 运算符查看追踪的结构以及 span 之间的关系。这些运算符的独特之处在于它们返回与运算符两侧都匹配的 span。
{condA} &>> {condB}- 后代运算符 (>>) 查找与{condA}匹配的 span 的后代 span 中与{condB}匹配的 span。{condA} &<< {condB}- 祖先运算符 (<<) 查找与{condA}匹配的 span 的祖先 span 中与{condB}匹配的 span。{condA} &> {condB}- 子运算符 (>) 查找与{condA}匹配的父 span 的直接子 span 中与{condB}匹配的 span。{condA} &< {condB}- 父运算符 (<) 查找与{condA}匹配的子 span 的直接父 span 中与{condB}匹配的 span。{condA} &~ {condB}- 兄弟运算符 (~) 查看与{condB}匹配的 span,这些 span 至少有一个与{condA}匹配的兄弟。
例如,在一个查询中获取失败的端点 AND 所有后代失败的 span:
{ span.http.url = "/path/of/api" && status = error } &>> { status = error }实验性结构
这些 spanset 运算符查看追踪的结构以及 span 之间的关系。这些运算符被标记为实验性,因为有时会返回误报。但是,这些运算符可能非常有用(请参阅以下示例)。
{condA} !>> {condB}- 非后代运算符 (!>>) 查找与{condA}匹配的父 span 的非后代 span 中与{condB}匹配的 span。{condA} !<< {condB}- 非祖先运算符 (!<<) 查找与{condA}匹配的子 span 的非祖先 span 中与{condB}匹配的 span。{condA} !> {condB}- 非子运算符 (!>) 查找与{condA}匹配的父 span 的非直接子 span 中与{condB}匹配的 span。{condA} !< {condB}- 非父运算符 (!<) 查找与{condA}匹配的子 span 的非直接父 span 中与{condB}匹配的 span。{condA} !~ {condB}- 非兄弟运算符 (!~) 查看与{condB}匹配的 span,这些 span 没有至少一个与{condA}匹配的兄弟。
阅读 Tempo 2.3 博客文章 获取更多示例和详细信息。
例如,查找服务“foo”中包含叶子 span 的追踪:
{ } !< { resource.service.name = "foo" }查找一系列级联错误中最后一个错误的 span:
{ status = error } !< { status = error }聚合器
到目前为止,所有示例查询表达式都涉及单个 span。您可以使用聚合函数来询问有关一组 span 的问题。目前包括:
count- spanset 中 span 的数量。avg- spanset 中给定数字属性或内在属性的平均值。max- spanset 中给定数字属性或内在属性的最大值。min- spanset 中给定数字属性或内在属性的最小值。sum- spanset 中给定数字属性或内在属性的总和。
聚合函数允许您对匹配的结果执行操作,以进一步优化返回的追踪。有关未来计划工作的更多信息,请参阅TraceQL 工作原理。
例如,查找总 span 数量大于 10 的追踪:
count() > 10查找追踪中 span 的平均时长大于 20ms 的追踪:
avg(duration) > 20ms例如,查找具有 3 个以上 http.status_code 属性值为 200 的 span 的追踪:
{ span.http.status_code = 200 } | count() > 3查找制造的属性 bytesProcessed 总计超过 1 GB 的 span:
{ } | sum(span.bytesProcessed) > 1000000000分组
TraceQL 支持分组管道运算符,可用于按任意属性进行分组。这对于查找具有多个错误的服务非常有用:
{ status = error } | by(resource.service.name) | count() > 1算术运算
TraceQL 支持在您的查询中进行任意算术运算。这对于使查询更易于理解很有用:
{ span.http.request_content_length > 10 * 1024 * 1024 }或您想到的任何其他内容。
选择
TraceQL 可以从 span 中选择任意字段。这种性能尤其高,因为只有在满足所有其他条件后才检索选定的字段。
{ status=error } | select(span.http.status_code, span.http.url)实验性 TraceQL 指标
TraceQL 指标是实验性的,但很容易上手。有关更多信息,请参阅TraceQL 指标文档。
您还可以使用 TraceQL 指标查询。有关详细信息,请参阅TraceQL 指标查询。


