1 什么是OpenTelemtry
OpenTelemetry,也称为 OTel,是一个供应商中立的开源可观测性框架 用于检测、生成、收集和导出遥测数据,例如跟踪(trace)、指标(metric)和日志(log)等signal(信号)。OpenTelemetry 是一个可观测性框架和工具包,旨在创建和管理遥测数据,例如跟踪、指标和日志。至关重要的是,OpenTelemetry 是供应商和 与工具无关,这意味着它可以与各种可观测性一起使用
1.1 什么是可观测性?
可观测性是指通过检查系统的内部输出来了解系统内部状态的能力。在软件的上下文中,这意味着能够理解 通过检查系统的遥测数据来检查系统的内部状态,其中遥测数据包括跟踪、指标和日志。
要使系统可观察,必须对其进行检测。也就是说,代码必须发出跟踪、指标或日志。然后,必须将检测的数据发送到可观测性后端
1.2 主要的OTel组件
OpenTelemetry由以下几个主要组件组成:
- A specification for all components(所有组件的规范)
- A standard protocol that defines the shape of telemetry data(定义遥测数据结构的标准协议)
- Semantic conventions that define a standard naming scheme for common telemetry data types(语义约定定义了通用遥测数据类型的标准命名方案)
- APIs that define how to generate telemetry data
- [Language SDKs][https://opentelemetry.io/docs/languages/] that implement the specification, APIs, and export of telemetry data(实现遥测数据规范、api和导出的语言sdk)
- A library ecosystem that implements instrumentation for common libraries and frameworks(一个为通用库和框架实现插装的库生态系统)
- Automatic instrumentation components that generate telemetry data without requiring code changes
- The OpenTelemetry Collector, a proxy that receives, processes, and exports telemetry data(OpenTelemetry收集器,一个接收、处理和导出遥测数据的代理)
- Various other tools, such as the OpenTelemetry Operator for Kubernetes, OpenTelemetry Helm Charts, and community assets for FaaS
2 OpenTelemtry的概念
2.1 Span(跨度)
跨度(span)表示一工作或者操作单元.它跟踪一个请求在造成特定操作,描绘了当时执行该操作发生的事情。范围包含名称、与时间相关的数据、结构化日志消息和其他元数据(即属性),以提供有关其跟踪的操作的信息
2.2 trace
distributed trace也可以直接称为trace,它记录请求(由应用程序或最终用户发起)在通过多服务架构(如微服务和无服务器应用程序)传播时所采取的路径。
如果不进行跟踪,很难确定分布式系统中性能问题的原因。它提高了应用程序或系统健康状况的可见性,并让我们调试难以在本地重现的行为。跟踪对于分布式系统来说是必不可少的,因为分布式系统通常存在不确定性问题,或者过于复杂而无法在本地重现。
一个跟踪由一个或者多个Spans组成,第一个span是root跨度。每个根跨度代表一个从开始到结束的请求。父级下面的span提供了请求期间发生的事情(或者组成请求的步骤)的更深入的上下文。
2.3 上下文
通过上下文传播,信号(teace)可以关联彼此之间,无论它们在哪里生成。尽管不限于跟踪,但它允许跟踪建立关于任意分布在进程和网络边界的服务的系统的因果信息。
我们通过两个子概念来定义上下文传播:上下文和传播。
2.3.1 上下文(context)
上下文是一个对象,它包含发送和接收服务(或执行单元)将一个信号与另一个信号相关联的信息。
例如,如果服务A调用服务B,那么服务A的一个span,其ID在上下文中,将被用作服务B创建的下一个span的父span。在上下文中的trace ID也将被用于服务B创建的下一个span,这表明该span与服务A的span属于同一个trace的一部分
2.3.2 传播Propagation
传播是在服务和进程之间移动上下文的机制。它序列化或反序列化上下文对象,并提供相关信息,以便从一个服务传播到另一个服务。传播通常由插装库处理,并且对用户是透明的,但是在需要手动传播上下文的情况下,可以使用传播api。
OpenTelemetry维护了几个官方传播器(propagators)。默认传播程序使用W3C TraceContext规范指定的标头
2.4 signal(信号)
OpenTelemetry的目的是收集、处理和导出信号。信号是系统输出,描述了平台上运行的操作系统和应用程序的底层活动。信号可以是你想要在特定时间点测量的东西,比如温度或内存使用情况,也可以是你想要跟踪的分布式系统组件中的事件。您可以将不同的信号组合在一起,以观察同一件技术在不同角度下的内部工作情况。
OpenTelemetry目前支持跟踪(trace)、度量(metrics)、日志(log)和baggage。事件是一种特定类型的日志,配置文件由配置文件工作组负责处理。
2.4.1 Traces
跟踪让我们了解了向应用程序发出请求时会发生什么。无论你的应用是带有单一数据库的单体应用,还是复杂的服务网格,跟踪对于理解请求在应用中接受的完整“路径”都是至关重要的。
让我们通过三个span工作单元来探索这一点:
hello span:
这是根span,表示整个操作的开始和结束。注意,它有一个trace_id字段表示跟踪,但没有parent_id。这就是为什么你知道它是根span。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{
"name": "hello",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x051581bf3cb55c13"
},
"parent_id": null,
"start_time": "2022-04-29T18:52:58.114201Z",
"end_time": "2022-04-29T18:52:58.114687Z",
"attributes": {
"http.route": "some_route1"
},
"events": [
{
"name": "Guten Tag!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
}
]
}hello-greetings span:
这个span封装了一些特定的任务,比如发送问候语,它的父级是hello span。注意,它与根span共享相同的trace_id,表明它是同一个跟踪的一部分。此外,它还有一个parent_id,与hello span的span_id匹配。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29{
"name": "hello-greetings",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x5fb397be34d26b51"
},
"parent_id": "0x051581bf3cb55c13",
"start_time": "2022-04-29T18:52:58.114304Z",
"end_time": "2022-04-29T22:52:58.114561Z",
"attributes": {
"http.route": "some_route2"
},
"events": [
{
"name": "hey there!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
},
{
"name": "bye now!",
"timestamp": "2022-04-29T18:52:58.114585Z",
"attributes": {
"event_attributes": 1
}
}
]
}hello-salutations span:
这个span表示跟踪中的第三个操作,和前一个一样,它是hello span的一个子元素。这也使它成为hello-greetings序列的兄弟。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{
"name": "hello-salutations",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x93564f51e1abe1c2"
},
"parent_id": "0x051581bf3cb55c13",
"start_time": "2022-04-29T18:52:58.114492Z",
"end_time": "2022-04-29T18:52:58.114631Z",
"attributes": {
"http.route": "some_route3"
},
"events": [
{
"name": "hey there!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
}
]
}
这三个JSON块共享相同的trace_id, parent_id字段表示层次结构。这就是一个Trace!
您要注意的另一件事是,每个Span看起来像结构化日志。那是因为它就是这样!一种理解跟踪的方式是,它们是结构化日志的集合,包含上下文、相关性、层次结构等。然而,这些“结构化日志”可以来自不同的进程、服务、虚拟机、数据中心等。这就是允许跟踪表示任何系统的端到端视图的原因。
为了理解OpenTelemetry中的跟踪是如何工作的,让我们看看将在检测我们的代码中发挥作用的组件列表:
Tracer provider :跟踪器提供者(有时称为TracerProvider)是跟踪程序的工厂。在大多数应用程序中,跟踪程序提供者初始化一次,其生命周期与应用程序的生命周期相匹配。跟踪器提供者初始化还包括资源和导出器初始化。这通常是OpenTelemetry跟踪的第一步。在某些语言sdk中,全局跟踪器提供程序已经为你初始化了
Tracer(跟踪器):跟踪者创建的span包含关于给定操作发生的更多信息,例如服务中的请求。跟踪器是从跟踪器提供程序创建的
Trace Exporters(跟踪导出器):跟踪导出器将跟踪发送给消费者。该使用者可以是调试和开发时的标准输出、OpenTelemetry收集器或您选择的任何开源或供应商后端
Context Propagation(上下文传播):上下文传播是支持分布式跟踪的核心概念。通过上下文传播,span可以相互关联并组装成一个trace,而不管span是在哪里生成的。要了解有关此主题的更多信息,请参阅关于上下文传播的概念页
- Span:span表示一个工作或操作单元。一个或多个span构成trace。在OpenTelemetry中,它们包含以下信息:
- Name
- Parent span ID (empty for root spans)
- Start and End Timestamps
- Span Context
- Attributes(属性)
- Span Events
- Span Links
- Span Status
1 | // |
2.4.2 Metrics
度量是对运行时捕获的服务的度量。捕获测量数据的时刻称为度量事件(metrics event),它不仅包括测量数据本身,还包括捕获测量数据的时间和相关的元数据。
应用程序和请求度量是可用性和性能的重要指标。自定义指标可以洞察可用性指标如何影响用户体验或业务。收集到的数据可用于警报中断或触发调度决策,以在高需求时自动扩展部署。
为了理解OpenTelemetry中的指标是如何工作的,让我们来看一组在检测我们的代码中发挥作用的组件。
Meter Provider: 一个仪表供应商(有时称为MeterProvider)是一个仪表工厂。在大多数应用程序中,仪表提供者初始化一次,其生命周期与应用程序的生命周期相匹配。仪表提供者初始化还包括资源和出口商初始化。这通常是OpenTelemetry测量的第一步。在某些语言sdk中,已经为您初始化了全局Meter提供者
Meter(计量器): 计量器创建度量工具,在运行时捕获关于服务的度量。计量器(meter)是由Meter Provider创建的
Metric Exporter:指标导出者将指标数据发送给消费者。此使用者可以是开发期间用于调试的标准输出、OpenTelemetry收集器或您选择的任何开源或供应商后端
- Metric Instruments:在OTel中,测量结果由度量工具给出,度量工具由一下元素完整定义
- Name
- Kind
- Unit (optional)
- Description (optional) >名称、单元和描述是由开发人员选择的,或者通过常见的语义约定(如请求和过程度量)定义的。
测量工具类型可以有:
- 计数器(Counter):随着时间累积的值——你可以把它想象成汽车上的里程表;它只会一直上升。
- 异步计数器(Asynchronous Counter):与计数器相同,但每次导出时收集一次。如果你不能访问连续的增量,只能访问聚合值,则可以使用。
- UpDownCounter(向上计数器):随着时间累积的值,也可以再次下降。一个例子可以是队列长度,它会随着队列中工作项的数量而增加或减少。
- 异步UpDownCounter:与UpDownCounter相同,但每次导出时收集一次。如果用户无法访问连续的更改,只能访问聚合的值(例如,当前队列的大小),则可以使用此选项。
- 测量仪器(Gauge):读取时测量当前值。车辆的燃油表就是一个例子。测量仪器是异步的。
- 直方图(Histogram):客户端值的聚合,例如请求延迟。如果你对值统计感兴趣,直方图是一个不错的选择。例如:有多少请求耗时少于1秒
2.4.3 logs
日志是带有时间戳的文本记录,可以是结构化的(推荐),也可以是非结构化的,包含元数据。在所有遥测信号中,日志是最大的遗产。大多数编程语言都有内置的日志功能或知名的、广泛使用的日志库。虽然日志是一个独立的数据源,但它们也可以附加到span上。在OpenTelemetry中,任何不属于分布式跟踪(trace)或度量(metrics)的数据都是日志。例如,事件是一种特定类型的日志。日志通常包含详细的调试/诊断信息,例如操作的输入、操作的结果和支持该操作的任何元数据。
对于跟踪和度量,OpenTelemetry采用全新的设计方法,指定一个新的API,并在多个语言sdk中提供该API的完整实现。
OpenTelemetry处理日志的方法是不同的。因为现有的日志解决方案在语言和操作生态系统中广泛存在,OpenTelemetry充当了这些日志、跟踪和度量信号以及其他OpenTelemetry组件之间的“桥梁”。事实上,由于这个原因,日志API被称为“日志桥API”。
logs规范中有关于这一理念的更多细节。
为了理解OpenTelemetry中的日志记录是如何工作的,让我们看看将在检测我们的代码中发挥作用的组件列表:
log Appender: 作为应用程序开发人员,您不应该直接调用日志的Appender API,因为它是为日志库作者提供的用于构建日志appender / bridges的API。相反,您只需使用您首选的日志库并将其配置为使用日志appender(或日志桥接器),它能够将日志发送到OpenTelemetry LogRecordExporter中。
logger provider: LoggerProvider(有时称为LoggerProvider)是Logger的工厂。在大多数情况下,Logger Provider只初始化一次,其生命周期与应用的生命周期相匹配。日志提供者初始化还包括资源和导出器初始化
logger: Logger创建日志记录。记录器是从日志提供程序创建的
logger exporter:将日志记录发送给消费者。该使用者可以是调试和开发时的标准输出、OpenTelemetry收集器或您选择的任何开源或供应商后端
- Log Record: 日志记录表示对事件的记录。在OpenTelemetry中,日志记录包含两种字段:
- 指定类型和含义的命名顶级字段
- 任意值和类型的Resource和attributes字段