首页  >  文章  >  后端开发  >  使用 OpenTelemetry 和 Signoz 掌握通过 Span Links 进行跟踪分析(实用指南)

使用 OpenTelemetry 和 Signoz 掌握通过 Span Links 进行跟踪分析(实用指南)

Barbara Streisand
Barbara Streisand原创
2024-10-24 03:23:31204浏览

本教程的目的

本教程的目的是为 OpenTelemetry 中的跨度链接提供实用且易于理解的指南。

它旨在帮助开发人员,特别是那些使用复杂和异步系统的开发人员,了解跨度链接是什么,它们与传统跟踪中的父子关系有何不同,以及为什么它们对于更好的跟踪关联很有价值。

在本指南结束时,您将获得有效使用跨度链接来跟踪分布式系统内交互所需的技能,从而提高可观察性和调试能力。

分布式追踪简介

过去,应用程序通常是整体式的,这意味着每个进程或功能都作为一个服务器上的单个单元执行。监控此类应用程序非常简单。

例如:如果出现问题,您可以查看该服务器的日志来识别问题。然而,微服务的兴起改变了这种简单性。

现在,现代应用程序通常由数十个甚至数百个协同工作的较小的独立服务组成。例如:当您使用移动应用程序下订单时,可能会有单独的服务来处理用户身份验证、处理付款、管理库存和发送确认电子邮件。

这些服务并不总是位于同一服务器上,甚至可以通过互联网进行通信,这增加了跟踪与应用程序交互时发生的情况的复杂性。

这就是分布式跟踪的用武之地。将分布式跟踪视为一种在单个请求经过复杂应用程序中的各种服务时跟踪单个请求的方法。它跟踪请求通过复杂系统的旅程。

在现代应用程序中,请求经常通过多个服务传输,每个服务运行在不同的机器上。分布式跟踪帮助我们可视化这一过程,从而更容易识别瓶颈和错误。

它就像一张侦探地图,将流程每个步骤之间的点连接起来,向您显示每个部分花费了多长时间以及出现问题的位置。当您查看跟踪时,您会看到请求如何通过不同服务移动的时间线,从而更容易识别速度减慢、错误或失败。

代码库

这是本教程的代码存储库:
[https://github.com/Noibisjunior/Span-Links-in-OpenTelemetry]

OpenTelemetry 在现代可观测性中的作用

OpenTelemetry 是实现这种可见性的关键角色。它是一个开源可观察性框架,允许开发人员从应用程序收集日志、指标和跟踪等数据。它作为一个工具集,用于捕获有关服务内部发生的情况的详细信息。

在现代可观测性的世界中,OpenTelemetry 可帮助您了解分布式应用程序的性能和运行状况。它就像一座桥梁,从各种服务收集数据并将其发送到 SigNoz 等工具,您可以在其中可视化正在发生的情况。这使得 OpenTelemetry 对于识别瓶颈、跟踪错误和确保应用程序顺利运行非常有价值。

通过将 OpenTelemetry 与分布式跟踪结合使用,您可以全面了解应用程序的行为方式,从而更轻松地诊断问题并改善用户体验。

Span 作为 OpenTelemetry 中跟踪构建块的重要性

随着软件,尤其是分布式系统变得越来越复杂,理解其内部工作原理成为一项具有挑战性的任务。这就是 OpenTelemetry 的跨度可以轻松解决挑战的地方。

什么是跨度?

跨度是 OpenTelemetry 跟踪系统中的基本工作单元。它是应用程序中发生的单个操作或事件。

它捕获该操作期间发生的情况、花费的时间以及任何相关详细信息,例如操作是否成功或失败。

例如,假设您的应用程序处理用户请求:

  • 当请求传入时,OpenTelemetry 会创建一个代表正在接收的请求的范围。
  • 如果请求随后触发数据库查询,则会创建另一个范围来表示该数据库交互。
  • 如果应用程序调用另一个服务,另一个范围会跟踪该服务。

Mastering Trace Analysis with Span Links using OpenTelemetry and Signoz (A Practical Guide)

跨度的关键属性:

  1. 名称:操作的描述性标签(例如“获取用户数据”)。
  2. 开始和结束时间戳:操作开始和结束的时间。
  3. 父跨度:发起此操作的跨度。
  4. 标签:附加元数据(例如 HTTP 状态代码、错误消息)。

Span 如何协同工作来创建跟踪

单独使用时,跨度很有用,但是当它们一起形成轨迹时,它们会更有效。

跟踪是跨度的集合,代表请求或操作流经系统时的整个过程。

让我们回到我们的用户请求示例:

当请求进入系统时,跟踪开始,并创建根跨度。当请求触发数据库查询时,数据库交互跨度链接到根跨度,表明它是同一进程的一部分。

用于调用其他服务的额外跨度被添加到跟踪中。通过查看此跟踪,您可以大致了解请求如何通过系统的不同部分。它不仅可以帮助您了解发生了什么,还可以帮助您了解应用程序的不同部分是如何连接的。

为什么跨度很重要?

  1. 查明问题:跨度可帮助您放大出现问题的位置。如果请求很慢,span 可以告诉您是否是数据库查询、网络调用或进程的其他部分导致了延迟。您可以看到哪个跨度花费的时间比预期更长,从而更容易找到瓶颈。

  2. 构建上下文:每个跨度都包含上下文信息,例如开始时间、结束时间和自定义标签(属性)。此数据可让您深入了解系统中特定时刻发生的情况,例如请求中涉及的特定用户 ID 或执行的查询。

  3. 创建关系:Span 彼此之间存在关系,通常采用父子结构。根跨度是父跨度,后续跨度是其子跨度。这一结构可帮助您了解事件发生的顺序以及它们如何相互依赖。这就像在您的应用程序中查看操作的家谱。

  4. 调试分布式系统:对于具有微服务的应用程序(其中不同的服务处理请求的不同部分),跨度尤其重要。它们可以帮助您跟踪在服务之间移动的请求,即使这些服务运行在不同的服务器或不同的数据中心中。这是理解服务之间复杂交互的关键。

了解 OpenTelemetry 中的跨度链接

什么是跨度链接?

在分布式系统的世界中,多个服务协同工作来处理用户请求,跟踪就像侦探的地图,它显示了请求在这些服务中移动时所采取的路径。这个旅程中的每一个活动称为一个跨度,一个完整的旅程称为一个踪迹。

传统上,跨度是使用父子关系连接的。将它们想象成一个家谱:父跨度启动一个流程(例如向另一个服务发出请求),子跨度代表由此发生的活动(例如处理请求的服务)。这是表示请求流的一种简单方法。

但是当两个跨度相关但它们并不完全适合父子层次结构时会发生什么?这就是跨度链接的用武之地。

跨度链接允许您连接两个相关但没有直接父子关系的跨度。它就像分布式系统中两个活动之间的“引用”或“捷径”。

例如,假设您有一个用户发出触发多个独立进程的请求,例如发送电子邮件和写入数据库。这些进程不是彼此的子活动;而是彼此的子活动。它们同时发生。使用跨度链接,您可以指示电子邮件发送跨度和数据库写入跨度与同一个初始用户请求相关,即使它们在父子概念中没有直接连接。

跨度链接与父子关系有何不同

亲子关系:这是一个简单的事件链。用户发送请求(父级),该请求触发在数据库(子级)中创建记录。如果没有父跨度,子跨度就不会存在,这使其成为直接结果。

跨度链接:这些更像是在某些上下文中相关的活动之间绘制虚线,但不遵循直接的操作链。它们提供了一种表达方式:“这些事情是相关的,尽管其中一个并没有直接导致另一个。”跨度链接非常适合表示相互作用但不严格分层的并行活动或事件。

跨度链接在复杂和异步系统中的重要性

跨度链接在复杂和异步系统中特别有价值,在这些系统中,事件流并不总是遵循清晰的父子路径。以下是一些实际使用场景;

异步工作流程:

想象一个从后台作业开始的用户请求(例如生成报告)。初始请求完成,但报告生成仍在后台继续。

通过跨度链接的实现,您可以将初始请求跨度与后台作业跨度相关联,即使它们不遵循直接的父子模式。

微服务通信:

在微服务架构中,服务通常以不严格分层的方式相互通信。

例如,用户操作可以触发多个服务来同时处理数据的不同部分。 Span 链接允许您跟踪这些独立和相关的 Span,作为更广泛的工作流程的一部分。

批处理:如果您正在处理批量数据,其中批次中的每个项目都会生成自己的范围,则可以使用范围链接将这些范围连接回原始批处理。

这样可以更轻松地跟踪批次的整个生命周期,并了解各个项目如何与主流程相关。

先决条件:使用 OpenTelemetry 和 Signoz 配置跨度链接所需的工具和库

  1. OpenTelemetry SDK:OpenTelemetry SDK(软件开发套件)是用于从应用程序收集可观测性数据(例如跟踪、指标和日志)的工具包。
  • 它充当代码和可观察性系统之间的桥梁,使收集有关应用程序运行方式的详细信息成为可能。

  • 将 OpenTelemetry 想象为一个“相机”,用于捕获应用程序操作的快照。通过将 SDK 集成到您的应用中,您可以放置​​此摄像头来记录幕后发生的事情。

  • 您需要使用应用程序的编程语言(例如 Python、Java、JavaScript)安装 SDK。

(2) SigNoz 设置:SigNoz 是一个开源可观察性工具,可让您可视化和分析通过 OpenTelemetry 收集的数据。

  • 将 SigNoz 视为“控制室”,您可以在其中查看 OpenTelemetry 设置捕获的镜头。您可以在这里清楚地了解应用程序中的跟踪和指标。

  • 您需要设置一个 SigNoz 实例,这涉及将其部署在本地计算机或服务器上,通常使用 Docker 或 Kubernetes。

  • SigNoz 有助于将原始数据转换为可视化效果,例如图形和图表,让您更轻松地了解应用程序内部发生的情况。

跟踪、跨度和检测代码的基本知识:

痕迹:

简单来说,跟踪就像用户或请求与应用程序交互时发生的情况的“故事”。它捕获由于该交互而发生的所有操作,从初始请求到可能涉及的所有服务和数据库。

想象一个用户单击您网站上的按钮。痕迹会记录接下来发生的每一步。

跨度:

跨度是跟踪故事中的“章节”。每个跨度代表作为跟踪的一部分发生的特定操作或任务。

例如,如果跟踪捕获了用户请求的整个过程,则跨度可以代表单个步骤,例如查询数据库或调用外部 API。

每个跨度都有开始和结束时间,为您提供有关每个步骤花费多长时间的精确详细信息。这使得更容易查明任何速度减慢或错误。

使用 OpenTelemetry 检测代码:

检测是向应用程序添加代码以收集可观测性数据的过程。通过使用 OpenTelemetry 检测您的代码,这通常涉及在您想要创建跟踪和跨度的位置添加几行代码。

例如,您可以检测数据库查询以查看需要多长时间,或检测用户登录过程以跟踪其性能。

OpenTelemetry SDK 提供可直接集成到代码中的库和函数,使这一切变得更容易。可以将其想象为将跟踪器连接到机器的各个部分以监控它们如何协同工作。

在 Python 中创建跨度链接:分步示例

让我们看一个 Python 中的基本示例。我们将使用 OpenTelemetry SDK 创建两个跨度并将它们链接在一起。

from opentelemetry import trace
from opentelemetry.trace import Link
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

# Set up the tracer provider and span exporter

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
trace.get_tracer_provider().add_span_processor(span_processor)

# Create the first span, simulating some work being done 

with tracer.start_as_current_span("span_one") as span_one:
    span_one.add_event("Processing order")
 order_id = "12345" # Imagine this as an order ID we're processing

# Create a second span with a link to the first span 

with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two:
        span_two.add_event("Updating order status")

# Simulate some additional work here

  print("Order ID: {order_id} has been updated.")

print("Tracing complete")

上述 Python 代码片段的说明

  • 设置跟踪器提供程序:
    上面的代码片段以跟踪器提供程序开始,它管理跨度的创建。

  • 这对于 OpenTelemetry 了解如何处理跨度至关重要。我们还配置了 SimpleSpanProcessor 和 ConsoleSpanExporter 以将跨度数据打印到控制台。这有助于我们了解正在创建的跨度类型以及它们是如何链接的
    .

(2) 创建第一个 Span (span_one):

使用tracer.start_as_current_span方法,我们创建一个名为span_one的span。这可以代表任何操作,例如处理订单。

在此范围内,我们添加一个事件处理顺序来指示在该特定时间点发生的情况。

我们还模拟了将在下一个跨度中使用的订单 ID (order_id = "12345")。

(3) 创建带有链接的第二个 Span (span_two):

在这里,我们启动了另一个名为 span_two 的跨度来表示不同但相关的操作,例如更新订单的状态。
注意 links 参数。我们使用 Link(span_one.get_span_context()) 在 span_two 和 span_one 之间创建链接。

这告诉 OpenTelemetry,“虽然这些操作不是父子关系,但它们是相关的。”

在span_two中,我们添加了另一个事件,更新订单状态,并模拟一些工作,例如更新数据库中的订单状态。

(4) 输出:

当您运行此代码时,您将在 ConsoleSpanExporter 的控制台中看到输出,其中显示两个跨度以及它们之间的链接。这有助于可视化这两个跨度在跟踪中如何相互关联。

需要注意的常见错误以及如何排除错误。

(1) 缺失的跨度上下文:

错误:如果您尝试在不调用 span_one.get_span_context() 的情况下创建链接,您将收到错误,因为 OpenTelemetry 需要有效的跨度上下文才能创建链接。

解决方案:始终确保在创建链接时传递跨度上下文。使用活动范围的 .get_span_context() 方法。

(2) 链接未开始或结束的 Span:

错误:如果您尝试创建指向尚未开始或已经结束的跨度的链接,您可能会遇到无法识别该链接的问题。

解决方案:创建链接时,确保您链接到的跨度处于活动状态。使用已经结束的跨度创建链接可能会导致跟踪显示方式出现意外行为。

(3) 性能考虑因素:

性能问题:链接太多跨度会增加跟踪数据的开销,导致高流量系统中的性能下降。

解决方案:有选择地使用链接。仅当存在需要可视化或分析的有意义的关系时,才会出现链接跨度。对于高流量环境,您可以使用 OpenTelemetry 的采样选项来减少捕获的跟踪数据量。

配置 SigNoz 以实现跨度链路可视化

在使用分布式系统时,了解系统不同部分如何通信至关重要。 OpenTelemetry 中的跨度链接 在连接可能没有直接父子关系的跟踪方面发挥着至关重要的作用,可以更清晰地了解请求如何流经您的服务。

Mastering Trace Analysis with Span Links using OpenTelemetry and Signoz (A Practical Guide)

为什么可视化跨度链接很重要

想象一下您的应用程序有一个支付服务,当支付成功时会触发通知服务。虽然这些服务交互,但它们可能不共享直接的父子关系。

跨度链接允许您关联这些交互,显示付款触发了通知。可视化这些链接可以帮助您更全面地了解独立服务如何实时关联。

通过设置 SigNoz 来可视化这些跨度链接,您可以更深入地了解应用程序的行为。

以下是如何配置 SigNoz 来捕获和查看 Span 链接

第 1 步:确保 SigNoz 已正确安装

  • 首先,请确保您已在本地环境或云设置中安装并运行 SigNoz。 SigNoz 可以使用 Docker 进行部署,以便于设置。
  • 如果您尚未执行此操作,请按照适用于您的操作系统的官方 SigNoz 安装指南 [https://signoz.io/docs/introduction]
  • 安装后,通过在 Web 浏览器中导航到 http://localhost:3301 来访问 SigNoz UI。您可以在此界面中配置设置并可视化跟踪数据,包括跨度链接。

第 2 步:配置 OpenTelemetry SDK 以包含您的 Span 链接

下一步是确保您的 OpenTelemetry SDK 配置为将跨度链接数据发送到 SigNoz。在应用程序的代码中,您需要添加跨度链接作为跟踪逻辑的一部分。

这是 Python 编程语言的代码片段:

from opentelemetry import trace
from opentelemetry.trace import Link
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

# Set up the tracer provider and span exporter

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
trace.get_tracer_provider().add_span_processor(span_processor)

# Create the first span, simulating some work being done 

with tracer.start_as_current_span("span_one") as span_one:
    span_one.add_event("Processing order")
 order_id = "12345" # Imagine this as an order ID we're processing

# Create a second span with a link to the first span 

with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two:
        span_two.add_event("Updating order status")

# Simulate some additional work here

  print("Order ID: {order_id} has been updated.")

print("Tracing complete")

上述Python代码片段的解释

我们首先配置 TracerProvider 来处理应用程序中的跟踪并设置跨度处理器。

OTLPSpanExporter 用于使用 OTLP 协议将跨度发送到 SigNoz 的后端。

如果您没有在本地运行 SigNoz,请将 http://localhost:4317 替换为适当的 SigNoz 端点。

其次,创建跨度和链接:

首先创建parent_span,代表一个初始操作(例如,用户请求)。我们使用 get_span_context() 提取parent_span的上下文,这允许我们将另一个span链接到它。

然后创建linked_span,并添加一个链接来引用parent_span的上下文。这意味着虽然 linked_span 不是 Parent_span 的直接子级,但它与之相关。

最后,将数据发送到 SigNoz:

使用BatchSpanProcessor处理span数据,确保span数据高效发送到SigNoz。

trace.get_tracer_provider().shutdown() 在最后调用,以确保在程序退出之前刷新并导出任何剩余的跨度。

第 3 步:更新 SigNoz 配置以跟踪数据

  • 为了确保 SigNoz 捕获跨度链接,您可能需要更改 SigNoz 收集器配置文件中的一些设置。
  • 收集器充当中间人,从OpenTelemetry接收跟踪数据并将其发送到SigNoz的后端。
  • 找到 OpenTelemetry Collector 配置文件,通常名为 otel-collector-config.yaml.
  • 添加或更新处理器和导出器部分,以确保正确转发跟踪数据。例如:
from opentelemetry import trace
from opentelemetry.trace import SpanKind, Link
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

# Set up the tracer provider and add a span processor

trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)

# Configure the exporter to send spans to SigNoz using the OTLP exporter

otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Create two spans, linking the second span to the context of the first

with tracer.start_as_current_span("parent_span") as parent_span:

# Simulate some logic for the parent_span
    print("Parent span is active")

# Get the context of the parent span
parent_context = parent_span.get_span_context()

# Create a linked span and add a link to the parent span's context

with tracer.start_as_current_span(
        "linked_span",
        links=[Link(parent_context)]
    ) as linked_span:

 # Simulate some logic for the linked_span
        print("Linked span is active")

# Ensure all spans are flushed before exiting the application

trace.get_tracer_provider().shutdown()

第 4 步:在 SigNoz 中可视化跨度链接

应用程序将带有跨度链接的跟踪数据发送到 SigNoz 后,您可以通过以下方式可视化这些链接:

  • 在 SigNoz UI 中打开跟踪资源管理器。
  • 搜索与您正在监控的服务相关的痕迹(例如支付服务和通知服务)。
  • 在跟踪详细信息视图中,您将看到跨度的图形表示,包括跨度之间的任何链接。链接的跨度将显示为不共享直接父子线的节点之间的附加连接。
  • 这种可视化可以帮助您了解请求如何流经系统,即使服务没有严格的层次关系。

第 5 步:调整视图以获得清晰度

为了获得完美的可视化效果,您需要注意以下几点:

  • 使用 SigNoz 中的过滤器将跟踪数据缩小到特定服务或时间段。
  • 如果您经常监控某些交互,请创建自定义仪表板来跟踪特定的跨度链接。
  • 在 SigNoz 中设置警报,以便在链接的跨度表明潜在问题(例如相关服务之间的延迟)时通知您。

后续步骤
在本教程中,我们学习了如何使用跨度链接来跟踪分布式系统内的交互

在下一个教程中,我们将学习使用 Span 链接的最佳实践和高级用例

以上是使用 OpenTelemetry 和 Signoz 掌握通过 Span Links 进行跟踪分析(实用指南)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn