OpenTelemetry 是一个开源的可观测性框架,由云原生基金会(CNCF)托管。它是 OpenCensusOpenTracing 项目的合并。旨在为所有类型的可观测信号(如跟踪(Traces)指标(Metrics)日志(Logs))提供单一标准。

OpenTelemetry

OpenTelemetry [təˈlemətri]指定了如何收集可观测数据并将其发送到后端平台。通过提供通用的数据格式和 API, OpenTelemetry 使组织更容易共享和重用观测数据,从而与各种可观测性工具和平台集成。

OpenTelemetry 架构促进了灵活性互操作性可扩展性,使开发人员能够采用满足其特定需求和环境的可观测性实践。

Dapper

谷歌于2010年发表的Google Dapper,介绍了他们的分布式跟踪技术。

本文首先通过网络搜索举例。处理一个通用搜索查询可能需要数千台机器和刷多不同的服务,而用户对延迟很敏感,可能是某个子系统出现异常。但是工程师查看整体延迟只能知道可能存在问题,但是无法猜测那个服务有问题,也无法猜测为什么有问题。这里主要有下面几个问题:

  • 工程师可能不知道在使用哪个服务。新的服务和功能总是在快速变化。
  • 工程师不是每个内部服务的领域专家。每个服务都是由不同的团队构建和维护的。
  • 服务和机器可能多个人在同时使用,因此性能问题可能是另一个应用程序的行为。

上述场景对Dapper提出了两个基本要求:全面部署持续监控。即使系统的一小部分没有受到监控,追踪的基础设施可用性也会受到影响。而且通常情况下,异常或其他值得注意的系统行为很难或不可能重现。这两个要求产生了下面三个具体的设计目标:

  • 低开销:追踪系统对正在运行的服务性能影响应该可以忽略不计。 在一些高度优化的服务中,即使很小的监控开销也很容易引起注意,并可能迫使部署团队关闭追踪系统。
  • 应用程序级透明:程序员不需要知道追踪系统。 依赖于应用程序开发人员的积极协作才能运行的追踪基础设施是极其脆弱的,并且经常由于检测工具的错误或遗漏而被破坏,因此违反了普遍性的要求。 这在像我们这样快节奏的开发环境中尤为重要。
  • 可扩展性:它需要应对至少在未来几年内服务和集群规模的增长。

另一个设计目标是追踪数据在生成后可快速用于分析:最好在一分钟内

分布式跟踪

基本概念:

  • 追踪树(Trace Trees):叶子节点是每一个span,一棵树表示一个完整的请求过程。
  • 跨度(spans):最小的追踪单元。span 可以是远程过程调用(RPC)、数据库查询或进程内函数调用。

Dapper 追踪树中五个跨度 spans 之间的因果关系和时间关系

其中,每棵树都有一个唯一的TraceId,用于区分不同的Trace。边表示span之间的因果关系。

span拥有下面的属性:

  • Span ID
  • Parent ID
  • 开始时间和结束时间
  • RPC时间数据
  • 应用自定义标识数据annotations

没有父节点的Span是根Span (root span)。

OpenTelemetry类型

OpenTelemetry 支持不同的遥测数据类型:

  • OpenTelemetry Trace 表示跨多个组件和服务的请求或操作的执行路径。它们提供详细的时间和上下文信息,允许开发人员了解请求流并确定性能瓶颈。
  • OpenTelemetry Metrics 是对系统行为或资源利用率的定量测量。它们有助于监控和分析一段时间内的性能,并可用于警报、容量规划和趋势分析。
  • OpenTelemetry Logs 包含有关应用程序中发生的事件、错误和活动的结构化或非结构化文本信息。它们对于调试、审计和故障排除非常有用。

OpenTelemetry架构

术语表

  • OpenTelemetry API 是一个编程接口,您可以使用它来检测代码以收集遥测数据,如跟踪、指标和日志。

OpenTelemetry API是OpenTelemetry项目的核心,它定义了一组抽象的接口和规范,用于记录应用程序性能数据、创建度量指标和传递上下文信息。这些接口和规范允许开发者编写自己的代码以收集、导出和处理性能数据。

  • OpenTelemetry SDK 是 OpenTelemetry API 的官方实现,用于处理和将收集的遥测数据导出到后端。

一个库和工具的集合,使开发人员能够对其应用程序进行检测并收集遥测数据以进行监控。

Otel SDK 提供了一个标准化和可扩展的框架,用于将 OpenTelemetry 集成到各种编程语言和环境中。

  • OpenTelemetry Instrumentation [ˌɪnstrəmenˈteɪʃn]是流行框架和库的插件,它们使用 OpenTelemetry API 来记录重要的操作,例如 HTTP 请求、DB 查询、日志、错误等等。

OpenTelemetry为常见的编程语言提供了监控和收集可遥测数据的库,支持的语言详见https://opentelemetry.io/docs/instrumentation/

三者的关系

OpenTelemetry API提供了灵活性和可扩展性,允许开发者自定义性能数据的收集和导出方式,OpenTelemetry SDK是OpenTelemetry项目的核心实现,提供了OpenTelemetry API的具体实现细节,而OpenTelemetry Instrumentation是一组用于自动化性能监控集成的库和插件

  • OpenTelemetry Collector 是应用程序和后端之间的代理。它接收遥测数据,对其进行转换,然后将数据导出到可以永久存储数据的后端。Collector 还可以作为一个代理,从被监视的系统中提取遥测数据,例如,OpenTelemetry Redis 或文件系统指标。

  • OTLP 是 SDK 和 Collector 使用的 OpenTelemetry 协议,用于将数据导出到后端或其他收集器。作为传输协议,OTLP 可以使用 gRPC (OTLP/gRPC) 或 HTTP (OTLP/HTTP)。

  • OpenTelemetry Backend 负责接收、存储和分析 OpenTelemetry 收集的遥测数据。它充当数据的中央存储库或处理管道,允许您聚合、查询、可视化并从应用程序生成的遥测数据中获得见解。

  • OTLPOpenTelemetry Protocol(OTLP)是一种开源的、与供应商无关的协议,用于从软件系统和应用程序收集、传输和导出遥测数据。

    OTLP 定义了在检测应用程序和后端系统之间交换的连接格式和数据结构。它指定了遥测数据的编码格式,包括指标、跟踪和日志的模式,以及在网络中传输这些数据的规则。

    OTLP 导出器允许将收集的遥测数据传输到后端进行处理和分析。

概览图

OpenTelemetry 架构旨在提供一种标准化的方法来收集、传输和处理来自应用程序和服务的遥测数据。它由几个关键组件组成,这些组件协同工作以实现分布式系统中的可观测性。

architecture

可观测性信号

OpenTelemetry 提供了一种捕获可观测性信号的标准化方法:

  • Metrics(指标) 表明存在问题。
  • Traces(跟踪) 会告诉你问题出在哪里。
  • Logs(日志) 可以帮助您找到根本原因。

OpenTelemetry Metrics 是帮助量化系统行为的定量指标。它们提供有关应用程序某些方面的当前状态或速率的信息,例如 CPU 使用情况、内存消耗或请求延迟。OpenTelemetry 允许您定义和记录自定义指标,以监视应用程序的性能和运行状况。

OpenTelemetry Traces 提供了请求在分布式系统中执行路径的详细记录。它们捕获单个操作及其关系的时间信息,使您能够了解请求流、确定瓶颈并解决性能问题。使用 OpenTelemetry,您可以对代码进行检测,以生成分布式跟踪并在服务之间进行关联。

OpenTelemetry Logs 是在应用程序执行期间发生的事件或消息的文本记录。它们帮助您理解应用程序行为、诊断问题和审计活动。OpenTelemetry 提供了一种机制,可以从应用程序中捕获结构化日志,并用上下文信息丰富它们。

指标

OpenTelemetry Metrics 是关于如何收集、聚合指标并将指标发送到OpenTelemetry APM 的标准,如Prometheus 等工具。

什么是指标

指标是代表系统运行状况和性能的数字数据点,例如 CPU 利用率、网络流量和数据库连接。

您可以使用指标来测量、监控和比较性能,例如,您可以测量服务器响应时间、内存利用率、错误率等。

Prometheus

prometheus指标可以用OpenTelemetry Collector收集和暴露prometheus指标。可以配置 OpenTelemetry Collector 接受 OpenTelemetry 数据,然后使用Prometheus 远程写入协议保存到到 Prometheus。

或者执行相反的操作,使用 OpenTelemetry Collector 提取 Prometheus 指标并将其使用OTLP导出到OpenTelemetry 后端

OpenTelemetry Collector本身可以充当Prometheus Server来抓取数据,收集并处理,然后重新暴露出来(exporter)。

OpenTelemetry Collector Prometheus Exporter

OpenTelemetry Collector Prometheus Exporter 是一个组件,允许将指标从OpenTelemetry Collector 暴露到Prometheus监控系统,也可以添加额外的标签和元数据。

从应用中暴露指标

通过使用OpenTelemetry Instruments,可以自动或者手动的将应用程序指标暴露出来。支持的类型有:

类型 属性 描述
Counter 同步 单调 用于描述加法非递减值
CounterObserver 异步 单调 Counter的异步版本
UpDownCounter 同步 可测量随时间增加或减少的附加值
UpDownCounterObserver 异步 UpDownCounter的异步版本
Histogram 同步 可根据记录的值生成直方图
GaugeObserver 异步 用于测量非相加值

具体用法参考各语言SDK实现,暴露出一个Prometheus指标端点即可。

跟踪

跟踪为我们提供了向应用程序发出请求时发生的情况的总体情况。无论您的应用程序是具有单个数据库的整体应用程序还是复杂的服务网格,跟踪对于了解请求在应用程序中采用的完整“路径”都至关重要。

分布式跟踪

分布式追踪允许您查看请求如何通过不同的服务和系统、每个操作的时间、发生时的任何日志和错误。

分布式追踪工具提供对系统行为的可见性,帮助识别性能问题,协助调试,并帮助确保分布式应用程序的可靠性和可伸缩性。

OpenTelemetry 跟踪在微服务架构的上下文中特别有价值,在微服务架构中,应用程序由多个独立的服务组成,共同工作以满足用户请求。

Spans

span表示一个工作/操作基本单元。一个Trace Tree由多个span组成。在OpenTelemetry中,span包含下面的信息:

比如:

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
30
31
32
{
"trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d",
"parent_id": "",
"span_id": "086e83747d0e381e",
"name": "/v1/sys/health",
"start_time": "2022-10-22 16:04:01.209458162 +0000 UTC",
"end_time": "2022-10-22 16:04:01.209514132 +0000 UTC",
"status_code": "STATUS_CODE_OK",
"status_message": "",
"attributes": {
"net.transport": "IP.TCP",
"net.peer.ip": "172.17.0.1",
"net.peer.port": "51820",
"net.host.ip": "10.177.2.152",
"net.host.port": "26040",
"http.method": "GET",
"http.target": "/v1/sys/health",
"http.server_name": "mortar-gateway",
"http.route": "/v1/sys/health",
"http.user_agent": "Consul Health Check",
"http.scheme": "http",
"http.host": "10.177.2.152:26040",
"http.flavor": "1.1"
},
"events": [
{
"name": "",
"message": "OK",
"timestamp": "2021-10-22 16:04:01.209512872 +0000 UTC"
}
]
}

span允许嵌套,表示父子操作。

上下文传播

上下文传播可确保相关上下文数据(例如跟踪 ID、跨度 ID 和其他元数据)在应用程序的不同服务和组件之间一致地传播。

OpenTemetry 在进程内的函数之间传播上下文(进程内传播),甚至从一个服务传播到另一个服务(分布式传播)。

进程内传播可以是隐式的或显式的,具体取决于您使用的编程语言。隐式传播是通过将活动上下文存储在线程局部变量(Java、Python、Ruby、NodeJS)中自动完成的。显式传播需要将活动上下文作为参数从一个函数显式传递到另一个函数 (Go)。

对于分布式上下文传播,OpenTelemetry 支持多种定义如何序列化和传递上下文数据的协议:

  • W3C 跟踪上下文traceparent头中,例如traceparent=00-84b54e9330faae5350f0dd8673c98146-279fa73bc935cc05-01.
  • B3 Zipkin以 开头的标头x-b3-,例如X-B3-TraceId.

W3C 跟踪上下文是默认启用的推荐传播器。

日志

OpenTelemetry Logs 允许以能够与其他可观测信号进行关联和更好集成的方式记录和收集日志。

日志对于了解应用程序行为、诊断问题和监控系统运行状况至关重要。虽然分布式跟踪和指标可以提供有关系统性能的相关信息,但日志可以提供有关特定事件、错误和应用程序行为的详细上下文和信息。

OpenTelemetry 提供了一个日志记录 API,允许您检测应用程序并生成结构化日志。OpenTelemetry Logging API 旨在与其他遥测数据(例如指标和跟踪)配合使用,以提供统一的可观测性解决方案。

不同类型的日志

OpenTelemetry 支持从应用程序或系统内的各种来源捕获日志。根据日志的生成和收集方式,日志可以分为 3 类。

系统和基础设施日志

系统日志提供有关系统操作、性能和安全性的宝贵信息。系统日志通常由系统内的各个组件生成,包括操作系统、应用程序、网络设备和服务器。

系统日志是在主机级别写入的,具有预定义的格式和内容,无法轻易更改。系统日志不包含有关跟踪上下文的信息。

比如内核日志,系统服务日志。

已存在应用日志

第一方日志由内部应用程序生成,记录特定的应用程序事件、错误和用户活动。这些日志对于应用程序调试和故障排除很有用。

通常,开发人员可以修改这些应用程序以更改日志的写入方式以及包含的信息。例如,要将日志与跟踪关联起来,开发人员可以手动将跟踪上下文添加到每个日志语句中,或者使用日志库的插件自动执行此操作。

例如,要传播上下文并将日志记录与跨度关联,您可以在日志消息中使用以下属性:

  • trace_id对于 TraceId,十六进制编码。
  • span_id对于 SpanId,十六进制编码。
  • trace_flags对于跟踪标志,根据 W3C 跟踪标志格式进行格式化。

例如:

1
request failed trace_id=958180131ddde684c1dbda1aeacf51d3 span_id=0cf859e4f7510204
新项目日志

开始新项目时,您可以遵循 OpenTelemetry 的建议和最佳实践,了解如何使用自动检测或配置日志记录库以使用 OpenTelemetry 日志附加程序来发出日志。

OpenTelemetry 的日志 API 允许开发人员对其应用程序进行检测,以生成可以由日志记录后端或日志管理系统收集和处理的结构化日志。日志 API 提供了一种将附加上下文信息附加到日志的方法,例如标签、属性或元数据。

使用 Logger API 记录不同严重级别的事件或消息,例如debuginfowarningerror等。您还可以将其他属性或上下文附加到日志以提供更多信息。

OpenTelemetry 还提供了一种标准化方法来跨分布式系统传播日志中的上下文。这确保了一致地捕获和保留相关的执行上下文,即使日志是由系统的不同组件生成的。

OpenTelemetry 日志数据模型允许将TraceIdSpanId直接包含在LogRecords.

总结

通过OpenTelemetry,我们可以在分布式环境中,跨语言,对服务的可遥测数据(Traces, Metrics, Logs)进行标准化的,统一的定义,埋点,收集,处理和存储,降低实施可观测性的成本。