追踪最佳实践
本页提供了一些通用的追踪最佳实践。
Span 和资源属性
追踪由 span 构建,span 表示工作单元,例如对上游服务的调用或来自上游服务的响应。Span 主要由 span 和资源属性构成。Span 还具有层次结构,父 span 可以有子 span 或同级 span。
在下面的屏幕截图中,屏幕左侧 (1) 显示查询结果列表。屏幕右侧 (2) 列出了组成所选追踪的每个 span。
**Span 属性**是一对键/值对,为其 span 提供上下文。例如,如果 span 处理通过 HTTP 调用另一个服务,则属性可以包括 HTTP URL(例如作为 span 属性键 http.url
)和返回的 HTTP 状态码(作为 span 属性 http.status_code
)。Span 属性可以包含不同的非空类型。
与 span 属性不同,**资源属性**是一对键/值对,描述 span 如何收集的上下文。通常,这些属性描述创建 span 的进程。这可能是一组与 Kubernetes 集群相关的资源属性,在这种情况下,您可能会看到资源属性,例如:k8s.namespace
、k8s.container_name
和 k8s.cluster
。这些还可以包含用于对追踪中的 span 进行插桩的库信息,或任何其他基础设施信息。
更多信息请阅读 OpenTelemetry 规范中的 Attribute 和 Resource 部分。
Span 和资源属性的命名约定
OpenTelemetry 项目为属性定义了许多语义约定,这可以帮助您确定在 span 中包含哪些属性最重要。这些约定提供了描述不同类型实体的通用词汇,有助于确保您的数据一致且有意义。
命名属性时,使用一致的嵌套命名空间,以确保属性键对于查看追踪 span 的任何人来说都是显而易见的,并且通用属性可以由多个 span 共享。以上面的示例为例,属性前缀 http
是命名空间,url
和 status_code
是该命名空间内的键。属性也可以嵌套,例如 http.url.protocol
可以是 HTTP
或 HTTPS
,而 http.url.path
可以是 /api/v1/query
。
有关语义命名约定的更多详细信息,请参阅 OpenTelemetry 作者建议和 OpenTelemetry 语义约定文档。
一些第三方库提供自动化插桩,当包含在源代码库中时,会自动生成 span 和 span 属性。
有关为应用进行追踪插桩的更多信息,请参阅分布式追踪插桩文档。
Span 应该有多少个属性?
在 span 中包含多少属性取决于您。没有硬性规定。将属性数量保持在最低限度,因为每个属性都会增加追踪系统的开销。在 Grafana Cloud 中,这会导致更高的追踪成本。
只包含与 span 所代表的操作相关的属性。例如,如果您正在追踪 HTTP 请求,您可能包含请求方法、URL 和响应状态码等属性。
如果您不确定是否应包含某个属性,宁可保守一些,将其排除在外。如果以后需要,您总是可以添加额外的属性。
通常,请考虑以下指南
- 不要将指标或日志作为属性包含在您的 span 中。
- 不要使用冗余属性。
- 在确定要添加哪些属性时,请仅考虑应用程序的服务流以及在当前 span 上下文中的执行情况。
OpenTelemetry 项目没有指定 span 可以拥有的最大属性数量。然而,每个 span 的属性数量的默认限制是128 项,因此您需要调整该设置。对于属性值和名称的字符长度也有默认限制。
确定在哪里添加 span
进行插桩时,确定您需要在追踪中观察的最小工作单元,以确保其有价值,并避免过度(或不足)插桩。
为任何持续时间相对较长的工作创建新的 span,可以使追踪观察立即显示在处理进入您的应用或系统的请求时花费了大量时间的位置。
例如,为调用其他服务(无论是否已插桩)添加一个 span,可能需要未知的时间才能完成,因此能够分离这项工作可以显示服务何时花费了比预期更长的时间。
为循环中可能调用许多其他函数的工作片段添加一个 span 是一个很好的信号,可以显示该循环花费了多长时间(您可以添加一个 span 属性来计算循环运行的次数,以确定持续时间是否可接受)。然而,为该循环中的每个方法或函数调用添加一个 span 可能不合适,因为它可能会产生数百甚至数千个无用的 span。
Span 长度
尽管 span(以及根据定义,它们所属的追踪)的长度有一些(高)默认限制,但这些可以通过这些配置进行调整。包含大量 span 和/或长时间运行 span 的追踪可能会对其存储后的查询时间产生影响。Cloud Traces 用户应联系 Grafana 支持来修改覆盖设置。
对于长时间运行的 span 和追踪,了解其对请求影响的最佳方法是发送一些测试用例,查看性能表现并评估追踪大小。
从那里,您可以修改 Tempo 的配置或确定如何重新设计追踪的生成方式。
您可以考虑通过几种方式拆分 span
- 分解查询
- 例如,如果一个复杂的 SQL 查询包含多个操作(例如,使用联接、子查询或联合),考虑为每个重要操作创建单独的 span。
- 改进长时间运行 span 的粒度
- 对于长时间运行的操作,您可以为每个预定的执行时间间隔创建一个新的 span。
注意
这需要在您的应用程序代码中进行基于时间的跟踪,并且实现起来更复杂。
- 对于长时间运行的操作,您可以为每个预定的执行时间间隔创建一个新的 span。
- 使用 span 链接
- 如果数据流遇到瓶颈,导致对该数据的进一步操作可能会在稍后进行批量处理,则使用span 链接有助于将追踪限制在可接受的时间范围内,同时与其他处理相同数据的追踪共享上下文。这还可以提高追踪的可读性。