OpenTelemetry 收集器提供了强大的功能,可以在遥测数据到达可观测性工具之前对其进行丰富和优化。在这篇博文中,我们将探讨如何利用收集器在 Elastic 可观测性中创建更有意义的事务名称,从而显著增强监控数据的价值。
考虑以下场景:您有一个事务,标签简单地为 “HTTP GET”,平均响应时间为 5 毫秒。但是,这个通用标签掩盖了各种不同的操作 — 支付处理、用户登录以及向购物车添加商品。这 5 毫秒的平均值是否真正代表了这些不同操作的性能?显然不是。
发生的另一个问题是,span 跟踪会混杂在一起,因此登录 span 和图像服务 span 都成为同一个桶的一部分,这使得在 Elastic 中进行延迟相关性分析变得困难。
我们将重点介绍一种使用收集器的属性和转换处理器的特定技术,从 HTTP URL 中提取有意义的信息,并使用它来创建更具描述性的 span 名称。这种方法不仅提高了指标的准确性,而且还增强了您快速识别和解决微服务架构中性能问题的能力。
通过结合使用这些处理器,我们可以快速解决事务名称过于通用的问题,创建更细粒度、信息更丰富的标识符,从而准确了解服务的性能。
但是,采用这种技术时必须谨慎。虽然更详细的事务名称可以显著提高可观测性,但也可能导致意想不到的挑战:基数爆炸。在深入研究实现细节时,我们还将讨论如何在粒度和可管理性之间取得适当的平衡,确保我们的解决方案增强而不是压倒我们的可观测性堆栈。
在以下各节中,我们将逐步介绍配置步骤,解释每个处理器如何为我们的目标做出贡献,并重点介绍避免诸如基数问题等潜在陷阱的最佳实践。无论您是 OpenTelemetry 的新手,还是希望优化现有的设置,本指南都将帮助您从遥测数据中解锁更有意义的见解。
先决条件和配置
如果您计划跟随本博客,以下是我们用于设置配置的一些组件和详细信息
- 确保您在 Elastic Cloud 上有一个帐户和一个已部署的堆栈(请参阅此处的说明)。
- 我还在我的环境中使用 OpenTelemetry 演示,这对于跟进非常重要,因为此演示存在我想解决的特定问题。您应该克隆存储库并按照此处的说明来启动并运行它。我建议使用 Kubernetes,我将在我的 AWS EKS(Elastic Kubernetes Service)环境中执行此操作。
OpenTelemetry 演示
OpenTelemetry 演示是一个全面的、基于微服务的应用程序,旨在展示 OpenTelemetry 仪器的功能和最佳实践。它模拟了一个电子商务平台,其中包含各种服务,如前端、购物车、结账和支付处理。此演示是开发人员和希望采用 OpenTelemetry 的组织的一个很好的学习工具和参考实现。
演示应用程序在其互连的服务中生成跟踪、指标和日志,演示了 OpenTelemetry 如何为复杂的分布式系统提供深度可见性。它对于尝试不同的收集、处理和可视化技术特别有用,使其成为探索可观测性概念和像 OpenTelemetry 收集器这样的工具的理想场所。
通过使用真实的场景和常见的架构模式,OpenTelemetry 演示可以帮助用户了解如何在他们自己的应用程序中有效地实施可观测性,以及如何利用数据进行性能优化和故障排除。
一旦您拥有 Elastic Cloud 实例并启动 OpenTelemetry 演示,您应该在 Elastic 服务地图页面上看到如下内容
导航到跟踪页面将为您提供以下设置。
如您所见,这里有一些非常广泛的事务名称,如 HTTP GET,并且如所示,这些平均值对于您服务中的特定业务功能来说不会非常准确。
那么,让我们使用 OpenTelemetry 收集器来解决这个问题。
OpenTelemetry 收集器
OpenTelemetry 收集器是 OpenTelemetry 生态系统中的一个重要组件,它充当一种与供应商无关的方式来接收、处理和导出遥测数据。它充当一个集中的可观测性管道,可以从各种来源收集跟踪、指标和日志,然后将这些数据转换并路由到多个后端系统。
收集器的灵活架构允许通过各种接收器、处理器和导出器轻松配置和扩展,您可以在此处进行探索。我个人发现浏览 “contrib” 存档对于找到我以前不知道的技术非常有用。这使得 OpenTelemetry 收集器成为希望标准化其可观测性数据管道、减少开销并与不同的监控和分析平台无缝集成的组织的宝贵工具。
让我们回到我们的问题,我们如何将 Elastic 使用的事务名称更改为更有用的名称,以便我们的 HTTP GET 转换为类似 payment-service/login 的名称?我们做的第一件事是获取完整的 http url,并考虑哪些部分与我们的事务相关。查看 span 详细信息,我们看到了一个 url
my-otel-demo-frontendproxy:8080/api/recommendations?productIds=&sessionId=45a9f3a4-39d8-47ed-bf16-01e6e81c80bc¤cyCode=
现在,显然我们不希望创建映射到每个会话 ID 的事务名称,这会导致我们之前讨论过的基数爆炸。然而,诸如 URL 的前两部分“api/recommendations”之类的东西看起来正是我们需要的。
属性处理器
OpenTelemetry 收集器为我们提供了一个有用的工具这里。属性处理器可以帮助我们提取 URL 的一部分,以便稍后在我们的可观测性管道中使用。要做到这一点非常简单,我们只需构建一个如下所示的正则表达式。现在我应该提到,我不是自己生成这个正则表达式的,而是使用 LLM 为我做的,永远不要再害怕正则表达式了!
attributes:
actions:
- key: http.url
action: extract
pattern: '^(?P<short_url>https?://[^/]+(?:/[^/]+)*)(?:/(?P<url_truncated_path>[^/?]+/[^/?]+))(?:\?|/?$)'
这个配置为我们完成了一些繁重的工作,所以让我们分解一下
- 我们正在使用属性处理器,这非常适合操作 Span 属性。
- 我们正在定位传入 Span 的 http.url 属性。
- extract 操作告诉处理器使用我们的正则表达式模式提取 URL 的特定部分。
现在,关于那个正则表达式 - 它旨在提取两个关键信息
- short_url:它捕获协议、域名以及可选的第一个路径段。例如,在“https://example.com/api/users/profile”中,它将捕获“https://example.com/api”。
- url_truncated_path:它会捕捉接下来的两个路径段(如果存在)。在我们的示例中,它将提取 “users/profile”。
为什么这很有用?嗯,它允许我们根据 URL 结构创建更具体的事务名称,而无需包含可能导致基数爆炸的过于具体的详细信息。例如,我们避免捕获唯一的 ID 或查询参数,这些参数会为每个请求创建一个新的事务名称。
因此,如果我们有一个像“https://example.com/api/users/profile?id=123”这样的 URL,我们提取的
现在值得一提的是,如果您没有想要用于命名事务的属性,那么值得查看 SDK 或 Agent 的选项。例如,Java 自动检测 Otel Agent 具有以下选项,用于捕获请求和响应标头。如果 URL 不够用,那么您可以随后使用此数据来命名您的事务!
在接下来的步骤中,我们将看到如何使用提取的信息来创建更有意义的 Span 名称,从而在我们的可观测性数据中提供更好的粒度,而不会使我们的系统不堪重负。请记住,我们的目标是增强我们的可见性,而不是淹没在过于具体的指标的海洋中!
转换处理器
现在我们已经提取了 URL 的相关部分,是时候充分利用这些信息了。进入转换处理器 - 我们在 OpenTelemetry 收集器管道中的下一个强大工具。
转换处理器允许我们修改遥测数据的各个方面,包括 Span 名称。这是我们将使用的配置
transform:
trace_statements:
- context: span
statements:
- set(name, attributes["url_truncated_path"])
让我们分解一下
- 我们正在使用转换处理器,这使我们可以对 Span 进行细粒度控制。
- 我们专注于trace_statements,因为我们想修改我们的 Trace Span。
- 的context: span告诉处理器将这些更改应用于每个单独的 Span。
- 我们的语句是奇迹发生的地方:我们将 Span 的名称设置为url_truncated_path我们之前提取的属性的值。
这在实践中意味着什么?还记得我们之前的示例 URL “https://example.com/api/users/profile?id=123”吗?现在,我们不会使用像“HTTP GET”这样的通用 Span 名称,而是会拥有一个信息量更大的名称:“users/profile”。
这种转换带来了几个好处
- 提高可读性:一眼就能看出正在访问应用程序的哪个部分。
- 更好的聚合:您可以轻松地对类似请求进行分组和分析,例如对用户配置文件的所有操作。
- 平衡的基数:我们足够具体以有用,但又不会太具体以至于为每个唯一的 URL 创建一个新的 Span 名称。
通过将我们之前完成的属性提取与此转换相结合,我们创建了一个强大的系统来生成有意义的 Span 名称。这种方法使我们能够深入了解应用程序的行为,而不会有基数爆炸的风险。
将它们整合在一起
OpenTelemetry 收集器的最终配置如下,请记住,这需要进入 opentelemetry-demo/kubernetes/elastic-helm/configmap-deployment.yaml 中,并通过 kubectl apply -f configmap-deployment.yaml 应用
---
apiVersion: v1
kind: ConfigMap
metadata:
name: elastic-otelcol-agent
namespace: default
labels:
app.kubernetes.io/name: otelcol
data:
relay: |
connectors:
spanmetrics: {}
exporters:
debug: {}
otlp/elastic:
endpoint: ${env:ELASTIC_APM_ENDPOINT}
compression: none
headers:
Authorization: Bearer ${ELASTIC_APM_SECRET_TOKEN}
extensions:
processors:
batch: {}
resource:
attributes:
- key: deployment.environment
value: "opentelemetry-demo"
action: upsert
attributes:
actions:
- key: http.url
action: extract
pattern: '^(?P<short_url>https?://[^/]+(?:/[^/]+)*)(?:/(?P<url_truncated_path>[^/?]+/[^/?]+))(?:\?|/?$)'
transform:
trace_statements:
- context: span
statements:
- set(name, attributes["url_truncated_path"])
receivers:
httpcheck/frontendproxy:
targets:
- endpoint: http://example-frontendproxy:8080
otlp:
protocols:
grpc:
endpoint: ${env:MY_POD_IP}:4317
http:
cors:
allowed_origins:
- http://*
- https://*
endpoint: ${env:MY_POD_IP}:4318
service:
extensions:
pipelines:
logs:
exporters:
- debug
- otlp/elastic
processors:
- batch
- resource
- attributes
- transform
receivers:
- otlp
metrics:
exporters:
- otlp/elastic
- debug
processors:
- batch
- resource
receivers:
- httpcheck/frontendproxy
- otlp
- spanmetrics
traces:
exporters:
- otlp/elastic
- debug
- spanmetrics
processors:
- batch
- resource
- attributes
- transform
receivers:
- otlp
telemetry:
metrics:
address: ${env:MY_POD_IP}:8888
您会注意到,我们通过在收集器配置底部的 pipelines 中的 traces 部分添加我们的富集和转换,将所有内容联系在一起。这是我们可观测性管道的定义,将我们讨论的所有部分整合在一起,以创建更有意义和可操作的遥测数据。
通过实施此配置,您正在朝着更具洞察力的可观测性迈出重要一步。您不仅仅是在收集数据;您还在改进数据,以提供对应用程序性能的清晰、可操作的见解,请查看下面的最终结果!
准备好将您的可观测性提升到一个新的水平了吗?
将 OpenTelemetry 与 Elastic Observability 一起实施,为理解和优化您的应用程序开启了一个充满可能性的世界。但这仅仅是个开始!要进一步增强您的可观测性之旅,请查看这些宝贵的资源
- 使用 Elastic Observability 中的 OpenTelemetry 进行基础设施监控
- 探索更多 OpenTelemetry 内容
- 使用 OTel Operator 注入 Java Agent
- 什么是 OpenTelemetry?
我们鼓励您深入研究,尝试这些配置,并了解它们如何转换您的可观测性数据。请记住,关键是在细节和可管理性之间找到适当的平衡。
您是否在您的可观测性管道中实施了类似的策略?我们很乐意听到您的经验和见解。请在下面的评论中分享您的想法,或在我们的社区论坛上与我们联系。
请继续关注本系列的第 2 部分,我们将探讨一种用于收集更多数据的高级技术,该技术可以通过使用 Java 插件收集 Span 名称、Baggage 和指标数据来帮助您获得更精细的粒度,而无需任何代码。