基于OpenTelemetry建设可观测性 Part 2 探测

aca11da596280bb33796cfa80a59c535.jpeg

泽注:这是一个系列,共分成6部分,这是第2部分。翻译自:https://trstringer.com/otel-part2-instrumentation/

这是整个系列博客的第二部分。在上一部分,我们介绍了OpenTelemetry是由什么组成的。本文将更准确的讨论OTel是如何收集遥测数据并追踪数据的。

手工探测(Manual instrumentation)

当我们讨论“探测”,我们实际在讨论收集追踪数据这个行为。有两种方法实现收集:手工和自动(下文会讨论)。正如这个小标题所写,手工探测指的是我们明确地告诉软件要暴露哪些数据。这被认为是更高级和定制的遥测。手工和自动的探测各有各的作用。我们接下来会讲到。

OpenTelemetry将追踪(trace)定义一个特定的请求在代码库中完整调用路径(可能涉及多个服务)。一个追踪包括一个或多个跨度(span),是一个特定请求操作的实例。一个跨度会连接一个父跨度。如果一个跨度是一个调用链的第一个跨度,那么它的父夸度的值将全是0.

注: 本文的样例应用由Go和一些Python语言实现。我将使用Go代码作为主要语言展示,但是同样的原则在OTel支持的其它语言中也是适用的。

我们可以通过API向现有的追踪添加跨度(或开始一个新的追踪)。对于Golang来说,这意味着我们将使用go.opentelemetry.io/otel模块,它将包括我们开始添加手动探测所需的所有包。我们可以通过调用全局追踪器提供者(tracer provider)来创建一个跨度:

import "go.opentelemetry.io/otel"

// ... other code ...

ctx, span := otel.Tracer("my-telemetry-library").Start(r.Context(), "get_user_cart")
defer span.End()

这里有几件事情需要注意。首先,我们通过首次检索全局追踪器提供者来创建一个新的跨度。我们将在下一篇博文中更深入地讨论什么是追踪器提供者,追踪器提供者是SDK的一个工件,负责决定从进程的哪里,以及如何从进程中获取遥测数据。

你可以通过调用otel.Tracer,或者通过传递追踪器提供者来使用全局追踪器提供者。这个示例应用程序依赖于全局追踪器提供者。当我们调用otel.Tracer时,我们传入探测名称(instrumentation name),探测名称通常是探测本身的库名。对于我的应用程序,探测名称设置为 "github.com/trstringer/otel-shopping-cart"。

一旦我们有了跟踪器提供者,我们就调用'Start',并传给它两个参数:上下文(context)和跨度(span)。上下文可以是创建的(例如context.background()),也可以是从之前的父级上下文中传递过来(本例中我使用的是HTTP请求上下文)。跨度的名字可以是任何字符串,但在这个项目中,我已经标准化地使用了用下划线分隔的描述标识符。

Start 的返回值是上下文,我们可以使用它传递一些内容给需要处理其他上下文相关操作(例如创建子跨度)的调用路径和跨度对象本身。首先,正如你在这个例子中看到的,是调用defer span.End(),这样我们就可以把这个跨度标记为完成。我们还可以通过"span"对象来增加跨度属性。

还值得注意的是,跨度是用来嵌套的。当一个跨度开始时,通常会调用到另一个代码路径,该路径也会启动另一个跨度。这就是跨度的嵌套关系,准确地说明了请求所经过的代码路径。

属性(Attributes)

在处理调用追踪链时,我们通常希望向追踪链中增加一些相关信息,以便我们在观测该系统时,能回答可能发生的问题。通过增加高质量的信息,我们可以实现这一点。以下代码展示了向跨度增加信息:

span.SetAttributes(attribute.String("user.name", userName))

我们创建了一个字符串属性user.name,并设置了一个值。让我们来看一下这个属性在跨度中是如何被记录的:

Span #4
    Trace ID       : d6b58718e2d607f2a881e55200b387d5
    Parent ID      : ef6c51753d66f227
    ID             : 95dcb2657f5bca91
    Name           : get_user_cart
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-08-07 16:37:51.184919236 +0000 UTC
    End time       : 2022-08-07 16:37:51.231164398 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Attributes:
     -> user.name: STRING(tlasagna)

太棒了。现在get_user_cart跨度包含了 user.name属性。Jaeger上的追踪链路也展示了:

2dd43448a0d711aac0a0f553e0c8fe51.png
image.png

事件(Events)

很多时候,您会想要记录跨度期间发生的一些文本或事件。比如与特定请求相关的日志记录。您可以通过调用 span.AddEvent 来做到这一点:

span.AddEvent(
    "Successfully retrieved rows from database",
    trace.WithAttributes(attribute.Int("row.count", rowCount)),
)

当事件被记录下来,它会被增加到跨度中。当你也可以通过增加属性的方式增加事件信息,如下跨度:

Span #1
    Trace ID       : 2d77674bf5bee80afcaf0df064f961ed
    Parent ID      : 5989852864910844
    ID             : f47e44dd5e23f016
    Name           : db_get_cart
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-08-07 18:37:39.167046809 +0000 UTC
    End time       : 2022-08-07 18:37:39.168098188 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Events:
SpanEvent #0
     -> Name: Successfully retrieved rows from database
     -> Timestamp: 2022-08-07 18:37:39.16803511 +0000 UTC
     -> DroppedAttributesCount: 0
     -> Attributes:
         -> row.count: INT(2)
f850f3e650e663acdc89e11443cace15.png
span event

自动探测(Automatic instrumentation)

前面的例子展示了当手工记录一个跨度时,如何有意图和明确的实现。不过,OpenTelemetry真正强大的功能之一是对自动探测的广泛支持。什么时候自动探测会有帮助?这里有几种情况:

  • • OTel 新手,只想尽快看到遥测数据展示;

  • • 尝试在现有的遗留代码库上引入 OTel;

  • • 自动探测的“默认”数据暂时已经足够,不需要任何特定遥测数据的组件或服务。

在我的购物车程序中,我在Python服务(价格服务)中使用了自动探测了两样东西:

  • • Flask服务

  • • MySQL连接

from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.mysql import MySQLInstrumentor

app = Flask(__name__)

FlaskInstrumentor().instrument_app(app)
MySQLInstrumentor().instrument()

自动探测的疯狂在于,这样就可以了!现在你得到了关于Flask的路由数据,以及MySQL的查询数据,而不需要任何额外工作和代码。以下是自动探测到Flask的跨度:

fdacbe8393287831f109a0cb7a6e3cae.png
Flask span

可以从中看出大量与请求相关的信息,如 http.targetnet.peer.iphttp.method等。

自动探测出来的MySQL相关的信息也很有用:

2b6ff4293a37eccf2272aaa954c768b7.png
mysql

这很棒。零代码更改就可以自动获得的一个重要信息:查询耗时。最重要的是,我可以看到运行的查询和谁运行的它。耗时长的查询的信息非常有助于排查应用程序数据库端的故障。这些好处只来自于那一行代码所实现的MySQL自动探测。

总结

探测(Instrumentation)是OpenTelemetry的核心,即我们该如何收集遥测数据,无论选择手工探测,还是通过现在的自动化探测库进行自动探测。在下一篇博客中,我们将看到OTel SDK如何处理数据。

本系列列表:

猜你喜欢

转载自blog.csdn.net/apl359/article/details/129774829