当 OpenTelemetry 遇上阿里云 Prometheus

news2024/11/23 15:52:32

作者:逸陵

背景

在云原生可观测蓬勃发展的当下,想必大家对 OpenTelemetry & Prometheus 并不是太陌生。OpenTelemetry 是 CNCF(Cloud Native Computing Foundation)旗下的开源项目,它的目标是在云原生时代成为应用性能监控领域的事实标准,它提供了一套统一的 API 和 SDK,用于生成、收集和处理分布式系统的遥测数据。总而言之,OpenTelemetry 是一套观察性的标准,具有语言无关性,支持各种编程语言和框架,并可与多种观察平台集成。

而 Prometheus 作为目前最受欢迎的开源监控系统,并且已经被 Kubernetes、Envoy 等广泛使用的云原生项目所采用。虽然 Prometheus 的查询语言十分强大,但是其数据格式还是 Prometheus 自己定义的。因此,它只能与 Prometheus 服务器集成,不能与其他系统集成。

而 OpenTelemetry 承诺在 Trace、Log 和 Metric 之间创建一个统一标准,所以它的数据格式是统一的,并具有足够的灵活性与交互性,同时完全兼容 Prometheus,所以吸引越来越多的开发运维人员使用 OpenTelemetry 在承载 Trace & Log 同时将其用于 Metric 的统计,与 Prometheus 生态进行结合,实现更好的观测监控。

图片

本文以构建系统可观测(重点为指标监控体系)为切入点,对比 OpenTelemetry 与 Prometheus 的相同与差异,粗浅的谈下个人选择的一些观点与看法;后重点介绍如何将应用的 OpenTelemetry 指标接入 Prometheus 及背后原理,最后介绍阿里云可观测监控 Prometheus 版拥抱 OpenTelemetry 及相关落地实践案例,希望能更好的帮助读者更好的理解 OpenTelemetry 及与 Prometheus 的生态融合。

站在 OpenTelemetry 与 Prometheus 的十字路口

如果你作为研发运维人员在进行系统观测时,特别是构建指标监控体系时,会有很多困惑,到底选择 OpenTelemetry 还是 Prometheus。在回答这个问题之前我们首先需要明确的了解 OpenTelemetry 与 Prometheus 的同异。

图片

而在对比之前,我们还是有必要对 OpenTelemetry 的指标模型进行深入的介绍。

2.1 OpenTelemetry 指标模型介绍

OpenTelemetry 将指标分解为三个交互模型,事件模型、Timeseries 模型以及指标(Metric)流模型。其中事件模型表示仪器如何报告指标数据;Timeseries 模型表示后端如何存储指标数据;指标(Metric)流模型定义 OpenTelemetry 协议 (OTLP),表示如何在事件模型和时间序列存储之间操作和传输指标数据流。

2.1.1 事件模型

事件模型是数据记录发生的地方,它的基础由 Instruments [ 1] 组成,Instruments 用于通过事件记录可观测数据。然后,这些原始事件在发送到其他系统之前以某种方式进行转换。OpenTelemetry 指标的设计使得使用相同的 Instruments 和事件使用不同的方式来生成 metric 指标流。

图片

尽管观测事件可以直接报告给后端,但实际上这是不可行的,因为可观测系统中使用的数据量巨大,并且可用于遥测收集目的的网络/CPU 资源有限,最好的例子是直方图指标,其中原始事件以压缩格式而不是单个时间序列记录。

注意:上图显示了一个 Instrument 如何将事件转换为多种类型的指标流。

2.1.2 时间序列模型

在 low-level 指标数据模型中,时间序列是由多个元数据属性组成的实体定义:

  • 指标名称
  • 属性(维度)
  • 点的值类型(整数、浮点数等)
  • 测量单位

每个时间序列的原始数据都是有序的(时间戳,值)点,其值类型如下:

  • Counter
  • Gauge
  • Histogram
  • Exponential Histogram
2.1.3 OpenTelemetry 协议数据模型

OpenTelemetry 协议(OTLP)数据模型由 Metric 数据流组成,这些流又由度量数据点组成,指标数据流可以直接转换为时间序列。指标流被分组为单独的指标对象,通过以下方式标识:

  • 原始 Resource 属性
  • Instrumentation Scope(例如 instrumentation lib 名称、版本)
  • 指标流的 name

包括 name 在内,Metric 对象由以下属性定义:

  • 数据点类型(例如 Sum、Gauge、Histogram、ExponentialHistogram、Summary)
  • 指标流的单位(unit)
  • 指标流的描述(description)
  • 内部数据点属性(如果适用):AggregationTemporality、Monotonic

数据点类型、单位和内在属性被认为是识别性的,而描述字段本质上不具备识别性。特定点的外在属性不被视为识别;这些包括但不限于:

  • 直方图(Histogram)数据点的桶边界
  • 指数直方图(ExponentialHistogram)数据点的大小或桶数量

Metric 对象包含不同流,由 Attributes 标识。在各个流中,点由一个或者两个时间戳标识,详细信息因数据点类型而异。

2.1.4 点类型介绍
2.1.4.1 Sum

OTLP 中的 Sums [ 2] 由以下部分组成:

  1. 增量(delta)或累积(cumulative)的 Aggregation Temporality。2. 一个表示 Sum 是否单调(monotonic [ 3] )的标志。
  • 对于增量单调(delta monotonic) Sums,这意味着读者应该期望非负值
  • 对于累积单调(cumulative monotonic) Sums,这意味着读者应该期望不小于先前值的值

一组数据点,每个数据点包含:

  • 一组独立的属性名称-值对
  • 计算 Sum 的时间窗口
  • (可选)一组 examplars [ 4]

当聚合时间性为"delta"时,我们期望度量流的时间窗口没有重叠,如下图所示:

图片

而当与聚合时间性为"cumulative"的时候,我们期望报告自“开始”以来的全部总和(其中通常开始意味着进程/应用程序启动)。

图片

在各种用例中,使用 Delta 与累积聚合之间存在各种权衡,例如:

  • 检测进程重新启动
  • 计算 rate
  • 基于推与拉的指标报告

OTLP 支持这两种模型,并允许 API、SDK 和用户在其各自的场景中确定最佳的折衷方案。

2.1.4.2 Gauge

OTLP 中的 Gauge [ 5] 表示给定时间的采样值。Gauge 流包括一组数据点,每个数据点包含:

  • 一组独立的属性名称-值对
  • 采样值(例如当前 CPU 温度)
  • 对值进行采样时的时间戳(time_unix_nano)
  • (可选)时间戳(start_time_unix_nano),它最能代表可以记录测量的第一个可能时刻,这通常设置为指标收集系统启动时的时间戳
  • (可选)一组 examplars

在 OTLP 中,Gauge 流中的点表示给定时间窗口的最后采样事件。

图片

在此示例中,我们可以看到我们使用 Gauge 采样的基础时间序列,虽然事件模型可以在给定的指标报告间隔内多次采样,但通过 OTLP 在指标流中仅报告最后一个值。

Gauge 不提供聚合语义,而是在执行时间对齐或调整分辨率等操作时使用“最后一个样本值”。可以通过转换为直方图或其他度量类型来聚合 Gauge。这些操作默认情况下不执行,需要用户直接配置。

2.1.4.3 Histogram

Histogram [ 6] 度量数据点以压缩格式传达大量记录的测量结果。直方图将一组事件分为为多个群体,并提供总体事件计数和所有事件的总和。

图片

直方图 Histogram 由以下部分组成:

  1. 增量(delta)或累积(cumulative)的 Aggregation Temporality2. 一组数据点,每个数据点包含:
  • 一组独立的属性名称-值对
  • 捆绑直方图的时间窗口((start, end])
  • 直方图中点总数的计数(count)
  • 直方图中所有值的总和(sum)
  • (可选)直方图中所有值的最小值(min)
  • (可选)直方图中所有值的最大值(max)
  • (可选)一系列桶:明确的边界值,这些值表示存储桶的下限和上限,以及是否将给定的观察结果记录在该存储桶中;属于该存储桶的观测值数量的计数。
  • (可选)一组 examplars

与 Sums 一样,直方图也定义聚合时间性。上图表示 Delta 时间性,其中累积的事件计数在报告后重置为零,并发生新的聚合。另一方面,累积继续聚合事件,并使用新的开始时间进行重置。聚合时间性 Aggregation Temporality 也对最小和最大字段有影响,最小值和最大值对于增量时间性(Delta)更有用,因为随着记录更多事件,累积最小值和最大值表示的值将稳定。此外,可以将最小值和最大值从 Delta 转换为 Cumulative,但不能从 Cumulative 转换为 Delta。从累积转换为增量时,可以删除最小值和最大值,或者以替代表示形式(例如仪表)捕获最小值和最大值。

桶数是可选的。没有桶的直方图仅根据总和和计数来传达总体,并且可以解释为具有单桶覆盖的直方图(-Inf,+Inf),如下为 Cumulative 型 Histogram 样例数据。

2023-11-29T13:43:45.238Z  info  ResourceMetrics #0
Resource SchemaURL: 
Resource attributes:
     -> service.name: Str(opentelemetry-metric-demo-delta-or-cumulative)
     -> service.version: Str(0.0.1)
     -> telemetry.sdk.language: Str(java)
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.version: Str(1.29.0)
ScopeMetrics #0
ScopeMetrics SchemaURL: 
InstrumentationScope aliyun 
Metric #0
Descriptor:
     -> Name: cumulative_long_histogram
     -> Description: ot cumulative demo cumulative_long_histogram
     -> Unit: ms
     -> DataType: Histogram
     -> AggregationTemporality: Cumulative
HistogramDataPoints #0
StartTimestamp: 2023-11-29 13:43:15.181 +0000 UTC
Timestamp: 2023-11-29 13:43:45.182 +0000 UTC
Count: 2
Sum: 141.000000
Min: 62.000000
Max: 79.000000
ExplicitBounds #0: 0.000000
ExplicitBounds #1: 5.000000
ExplicitBounds #2: 10.000000
ExplicitBounds #3: 25.000000
ExplicitBounds #4: 50.000000
ExplicitBounds #5: 75.000000
ExplicitBounds #6: 100.000000
ExplicitBounds #7: 250.000000
ExplicitBounds #8: 500.000000
ExplicitBounds #9: 750.000000
ExplicitBounds #10: 1000.000000
ExplicitBounds #11: 2500.000000
ExplicitBounds #12: 5000.000000
ExplicitBounds #13: 7500.000000
ExplicitBounds #14: 10000.000000
Buckets #0, Count: 0
Buckets #1, Count: 0
Buckets #2, Count: 0
Buckets #3, Count: 0
Buckets #4, Count: 0
Buckets #5, Count: 1
Buckets #6, Count: 1
Buckets #7, Count: 0
Buckets #8, Count: 0
Buckets #9, Count: 0
Buckets #10, Count: 0
Buckets #11, Count: 0
Buckets #12, Count: 0
Buckets #13, Count: 0
Buckets #14, Count: 0
Buckets #15, Count: 0
2.1.4.4 ExponentialHistogram

指数直方图数据点是直方图数据点的替代表示形式,用于以压缩格式传达一组记录的测量值。ExponentialHistogram 使用指数公式压缩桶边界,与类似大小的替代表示相比,使其适合以较小的相对误差传输高动态范围数据。

直方图 Histogram 涉及聚合时间性、属性和时间戳以及 sum、count、min、max 和 exemplars 字段,ExponentialHistogram 与 Histogram 类似,这些字段都与直方图 Histogram 具有相同的解释,只是这两种类型之间的存储 bucket 结构不同。如下为一个 delta 形式的 ExponentialHistogram 数据格式:

2023-11-29T13:13:09.866Z  info  ResourceMetrics #0
Resource SchemaURL: 
Resource attributes:
     -> service.name: Str(opentelemetry-metric-demo-delta-or-cumulative)
     -> service.version: Str(0.0.1)
     -> telemetry.sdk.language: Str(java)
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.version: Str(1.29.0)
ScopeMetrics #0
ScopeMetrics SchemaURL: 
InstrumentationScope aliyun 
Metric #0
Descriptor:
     -> Name: cumulative_long_e_histogram
     -> Description: ot cumulative demo cumulative_long_e_histogram
     -> Unit: ms
     -> DataType: ExponentialHistogram
     -> AggregationTemporality: Cumulative
ExponentialHistogramDataPoints #0
StartTimestamp: 2023-11-29 13:11:54.858 +0000 UTC
Timestamp: 2023-11-29 13:13:09.86 +0000 UTC
Count: 3
Sum: 191.000000
Min: 15.000000
Max: 89.000000
Bucket (14.993341, 15.321652], Count: 1
Bucket (15.321652, 15.657153], Count: 0
Bucket (15.657153, 16.000000], Count: 0
Bucket (16.000000, 16.350354], Count: 0
Bucket (16.350354, 16.708381], Count: 0
Bucket (16.708381, 17.074246], Count: 0
Bucket (17.074246, 17.448124], Count: 0
Bucket (17.448124, 17.830188], Count: 0
Bucket (17.830188, 18.220618], Count: 0
Bucket (18.220618, 18.619598], Count: 0
Bucket (18.619598, 19.027314], Count: 0
Bucket (19.027314, 19.443958], Count: 0
Bucket (19.443958, 19.869725], Count: 0
Bucket (19.869725, 20.304815], Count: 0
Bucket (20.304815, 20.749433], Count: 0
Bucket (20.749433, 21.203786], Count: 0
Bucket (21.203786, 21.668089], Count: 0
Bucket (21.668089, 22.142558], Count: 0
Bucket (22.142558, 22.627417], Count: 0
Bucket (22.627417, 23.122893], Count: 0
Bucket (23.122893, 23.629218], Count: 0
Bucket (23.629218, 24.146631], Count: 0
Bucket (24.146631, 24.675373], Count: 0
Bucket (24.675373, 25.215694], Count: 0
Bucket (25.215694, 25.767845], Count: 0
Bucket (25.767845, 26.332088], Count: 0
Bucket (26.332088, 26.908685], Count: 0
Bucket (26.908685, 27.497909], Count: 0
Bucket (27.497909, 28.100035], Count: 0
Bucket (28.100035, 28.715345], Count: 0
Bucket (28.715345, 29.344129], Count: 0
Bucket (29.344129, 29.986682], Count: 0
Bucket (29.986682, 30.643305], Count: 0
Bucket (30.643305, 31.314306], Count: 0
Bucket (31.314306, 32.000000], Count: 0
Bucket (32.000000, 32.700709], Count: 0
Bucket (32.700709, 33.416761], Count: 0
Bucket (33.416761, 34.148493], Count: 0
Bucket (34.148493, 34.896247], Count: 0
Bucket (34.896247, 35.660376], Count: 0
Bucket (35.660376, 36.441236], Count: 0
Bucket (36.441236, 37.239195], Count: 0
Bucket (37.239195, 38.054628], Count: 0
Bucket (38.054628, 38.887916], Count: 0
Bucket (38.887916, 39.739450], Count: 0
Bucket (39.739450, 40.609631], Count: 0
Bucket (40.609631, 41.498866], Count: 0
Bucket (41.498866, 42.407573], Count: 0
Bucket (42.407573, 43.336178], Count: 0
Bucket (43.336178, 44.285116], Count: 0
Bucket (44.285116, 45.254834], Count: 0
Bucket (45.254834, 46.245786], Count: 0
Bucket (46.245786, 47.258437], Count: 0
Bucket (47.258437, 48.293262], Count: 0
Bucket (48.293262, 49.350746], Count: 0
Bucket (49.350746, 50.431387], Count: 0
Bucket (50.431387, 51.535691], Count: 0
Bucket (51.535691, 52.664175], Count: 0
Bucket (52.664175, 53.817371], Count: 0
Bucket (53.817371, 54.995818], Count: 0
Bucket (54.995818, 56.200069], Count: 0
Bucket (56.200069, 57.430690], Count: 0
Bucket (57.430690, 58.688259], Count: 0
Bucket (58.688259, 59.973364], Count: 0
Bucket (59.973364, 61.286610], Count: 0
Bucket (61.286610, 62.628612], Count: 0
Bucket (62.628612, 64.000000], Count: 0
Bucket (64.000000, 65.401418], Count: 0
Bucket (65.401418, 66.833522], Count: 0
Bucket (66.833522, 68.296986], Count: 0
Bucket (68.296986, 69.792495], Count: 0
Bucket (69.792495, 71.320752], Count: 0
Bucket (71.320752, 72.882473], Count: 0
Bucket (72.882473, 74.478391], Count: 0
Bucket (74.478391, 76.109255], Count: 0
Bucket (76.109255, 77.775831], Count: 0
Bucket (77.775831, 79.478900], Count: 0
Bucket (79.478900, 81.219261], Count: 0
Bucket (81.219261, 82.997731], Count: 0
Bucket (82.997731, 84.815145], Count: 0
Bucket (84.815145, 86.672355], Count: 0
Bucket (86.672355, 88.570232], Count: 1
Bucket (88.570232, 90.509668], Count: 1

2.1.4.4.1 Exponential Scale

指数直方图的分辨率由 scale 参数来表征,scale 值越大,精度越高。指数直方图的 bucket 边界位于 base 的整数次幂,也称为“增长因子”,其中:

base = 2**(2**(-scale))

这些公式中的符号 ** 表示求幂,因此 2**x 读作“2 的 x 次方”,通常由 math.Pow(2.0, x) 等表达式计算,如下为 OpenTelemetry 官方中的样例,所选 scale 的计算 base 如下所示:

图片

该设计的一个重要属性被描述为“完美子集”,具有给定比例的指数直方图的桶精确地映射到具有较小比例的指数直方图的桶中,这允许消费者降低直方图的分辨率(即缩小比例)而不会引入误差。上述 delta ExponentialHistogram 数据使用默认的 Base2ExponentialHistogramAggregation,其中 max scale 为 20。

private static final int DEFAULT_MAX_BUCKETS = 160;
    private static final int DEFAULT_MAX_SCALE = 20;
    private static final Aggregation DEFAULT = new Base2ExponentialHistogramAggregation(160, 20);
    private final int maxBuckets;
    private final int maxScale;

    private Base2ExponentialHistogramAggregation(int maxBuckets, int maxScale) {
        this.maxBuckets = maxBuckets;
        this.maxScale = maxScale;
    }

    public static Aggregation getDefault() {
        return DEFAULT;
    }

    public static Aggregation create(int maxBuckets, int maxScale) {
        Utils.checkArgument(maxBuckets >= 1, "maxBuckets must be > 0");
        Utils.checkArgument(maxScale <= 20 && maxScale >= -10, "maxScale must be -10 <= x <= 20");
        return new Base2ExponentialHistogramAggregation(maxBuckets, maxScale);
    }

2.1.4.4.2 Exponential Buckets

由索引(有符号整数)标识的指数直方图桶表示总体中大于基数索引且小于或等于基数(索引+1)的值,直方图的正负范围分别表示。使用与正值范围相同的比例,将负值按其绝对值映射到负值范围。请注意,因此,在负范围内,直方图桶使用下限边界。ExponentialHistogram 数据点的每个范围都使用桶的密集表示,其中桶的范围表示为单个偏移值、有符号整数和计数值数组,其中数组元素 i 表示桶索引的桶计数偏移 +i。

对于给定范围(正数或负数):

  • 存储 bucket 索引 0 对范围 (1, base] 内的测量进行计数
  • 正索引对应于大于 base 的绝对值
  • 负索引对应于绝对值小于或等于 1
  • 连续的 2 次幂之间有 2** scale 个 bucket

例如,当 scale=3 时,1和2之间有 2**3 个桶,请注意,scale=3 直方图中存储桶索引 4 的下边界映射到 scale=2 直方图中存储桶索引 2 的下边界,并映射到 scale=3 直方图中存储桶索引 1(即基数)的下边界。1 个直方图——这些是完美子集的示例。

图片

Ps:由于最新版本中 Summay 已经不推荐,所以这里不做详细的介绍。

2.2 OpenTelemetry VS Prometheus

在本文中我们就不详细的介绍 Prometheus 的指标类型了,详细介绍参考 Prometheus 官网介绍 [ 7] 。我们通过对比 OpenTelemetry 指标类型以及 Prometheus 指标类型,我们会发现:

  • OpenTelemetry 可以将 Metric 表示为增量,而不是累计,存储每个数据点之间的差异,而不是累计总和。然而Prometheus 在设计上不允许这样做。
  • OpenTelemetry 允许 Metric 值为整数,而 Prometheus 无法表达浮点数。
  • OpenTelemetry 可以将一些额外的元数据附加到直方图中,允许您跟踪最大值和最小值,这一点在有些场景是非常有用的。
  • OpenTelemetry 具有指数直方图聚合类型(使用公式和刻度来计算 bucket 大小),Prometheus 不支持,但是可以实现兼容。

从上面的模型对比总结来说,OpenTelemetry 允许表示所有 Prometheus 度量类型(计数器、仪表、摘要和直方图),尽管如此 Prometheus 无法表示 OpenTelemetry 度量的某些配置,包括 delta 表示和指数直方图(尽管这些将很快添加到 Prometheus 中)以及整数值。所以换句话说,Prometheus 度量是 OpenTelemetry 度量的严格子集。

图片

尽管这样,但是两者还是存在一些差异的,这里需要强调一下。

  • Prometheus 提供 Metric 收集、存储和查询,它通过通过抓取目标来采集集指标,当然也可以通过 pushgateway形式,相关 Metric 数据最后存储在 Prometheus 本地数据库或者其他远端时许数据库中,最后通过 Prometheus 查询语言 PromQL 进行数据的读取,所以 Prometheus 是一个完整的可观测解决方法,集数据的采集、计算、存储、报警、查询等于一体。
  • OpenTelemetry 作用域要小很多。它通过推送或拉取使用整合的 API 收集指标(以及跟踪和日志),并将其发送到其他系统进行存储或查询。所以 OpenTelemetry 只关注应用程序交互的可观测性部分,从而将信号的创建与存储和查询信号的操作问题脱钩。所以在指标的存储上 OpenTelemetry Metric 通常回到 Prometheus 或者 Prometheus 兼容的系统中。

2.3 如何选择

不可否认 OpenTelemetry 与 Prometheus 都是非常优秀的,有时候选择上确实会比较纠结,所以总的原则还是结合实际的业务场景出发,因地制宜,以发展的眼光看待问题。如下的浅谈如有不妥欢迎交流、批评与指正。

  • 如果你尝试构建统一的可观测体系包含 Trace、Log 和 Metric,那么 OpenTelemetry 将允许使用相同的库来对所有三种信号类型进行检测,减少包依赖,方便运维管理。这是一个显著的好处,可以将三种相同的信号发送到同一一个后端也可以发送到不同的后端,OpenTelemetry 都支持。
  • 如果你希望你的应用/系统/组件在云原生、容器化的场景下监控指标能更好的被观测,特别是开源、被第三方使用的场景,这种场景一般建议使用 Prometheus,比如常见的中间 Redis、MySQL、Zookeeper 等都支持 Prometheus Exporter 形式暴露指标。
  • 比如特殊的网络环境或者其他限制条件下,不能采用 Prometheus pull 形式,但在 Prometheus pushgateway 形式又存在多种弊端的情况下,可以尝试使用 OpenTelemetry push 形式。

但无论如何选择,有点尴尬的就是即使客户端选择了 OpenTelemetry,实际情况 OpenTelemetry Metric 存储往往回到了 Prometheus 上。这也是当前的现状,大多数组织可能会混合使用这两种标准:用于基础设施监控的 Prometheus,利用更成熟的集成生态系统从数百个组件中提取指标,以及用于已开发服务的 OpenTelemetry。

图片

下一章节,我们重点介绍如何将 OpenTelemetry 指标接入到 Prometheus。

如何将 OpenTelemetry Metric 接入 Prometheus

3.1 原理介绍

将 OpenTelemetry 指标接入 Prometheus 的核心要素是需要将 OpenTelemetry 指标转化为 Prometheus 指标格式,所以无论是 OpenTelemetry Collector 形式,还是直接在客户端采用 Prometheus exporter bridge 形式,本质上就是进行数据格式转化。

1)OpenTelemetry 官网

下图为 OpenTelemetry 官网文档建议的 OpenTelemetry 指标到 Prometheus 指标的转化路径。

详细参考文档:otlp-metric-points-to-prometheus [ 8]

图片

2)OpenTelemetry Collector的实现

而 OpenTelemetry Collector 具体实现与官网的建议实现略有不同,详细实现参考 prometheus-client-bridge [ 9] 。具体的转化关系如下图所示,与 OpenTelemetry 官方文档的核心差异在于如下几点。

  • OpenTelemetry 官方文档建议将 monotonic & delta Sum 转化为 Prometheus cumulative 的 Counter;而 OpenTelemetry Collector 的 Prometheus bridge 中将该中类型直接转化为 Prometheus 的 gauge。
  • OpenTelemetry 官方文档建议 Histogram delta 转化为 cumulative,从而转化为 Prometheus Histogram;虽然 OpenTelemetry Collector 代码中没有区分 Histogram 的 cumulative 及 delta,实际仅支持 cumulative 型 Histogram 转化为 Prometheus Histogram。
  • OpenTelemetry 官方文档建议 Exponential Histogram cumulative 转化为 Prometheus 的 Histograms,而在 OpenTelemetry Collector 中 Exponential Histogram cumulative & Exponential Histogram delta 都做丢弃处理。

图片

3.2 传统接入方式

以 Java 应用为例,当前 Java 应用(其他多语言应用类似) 将 OpenTelemetry 指标接入到 Prometheus 有如下几种常见的方式,当然还有其他解决方案如使用 micrometer,这里就不赘述。

方式 1: 应用暴露 OpenTelemetry 指标,通过 gRpc/HTTP 上报到 OpenTelemetry Collector,OpenTelemetry Collector 中以 Prometheus exporter 形式暴露 Prometheus 指标,Prometheus 可通过静态 Job 形式进行采集(或者其他服务发现的形式)。

详细的代码参考 Demo:https://github.com/OuyangKevin/opentelemetry-metric-java-demo/blob/main/metric-http/README.md

图片

方式 2: 应用暴露 OpenTelemetry 指标通过,gRpc/HTTP 上报到 OpenTelemetry Collector,OpenTelemetry Collector 中直接将指标转化为 Prometheus 指标格式,然后通过 remote write 形式写入远端 Prometheus。

详细的代码参考 Demo:https://github.com/OuyangKevin/opentelemetry-metric-java-demo/blob/main/metric-grpc/README.md

Ps:老版本 OpenTelemetry Collector 不支持 remote write 形式,如需验证请使用最新版本。

图片

方式3: Java 应用引入 OpenTelemetry-exporter-prometheus lib,将 OpenTelemetry 指标直接以 Prometheus Exporter 形式进行暴露,Prometheus 直接以拉的形式进行采集。

图片

如下为初始化的核心代码:

详细代码参考 Demo:https://github.com/OuyangKevin/opentelemetry-metric-java-demo/blob/main/metric-prometheus/README.md

PrometheusHttpServer prometheusHttpServer = PrometheusHttpServer.builder().setPort(1000).build();
Resource resource = Resource.getDefault().toBuilder().put(SERVICE_NAME, "opentelemetry-metric-demo-http").put(SERVICE_VERSION, "0.0.1").build();
SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
        .registerMetricReader(prometheusHttpServer)
        .setResource(resource)
        .build();

LongCounter longCounter = sdkMeterProvider
        .get("aliyun")
        .counterBuilder("ping_long_counter")
        .setDescription("ot http demo long_counter")
        .setUnit("ms")
        .build();

可观测监控 Prometheus 版零距离拥抱OpenTelemetry

目前,阿里云可观测监控 Prometheus 版已全面支持 OpenTelemetry 指标接入,用户仅需修改相关的上报地址以及鉴权配置即可无缝接入可观测监控 Prometheus 版,欢迎前往 Prometheus 控制台 [ 10] 进行体验。

详细的使用限制说明参考 OpenTelemetry 指标上报地址使用说明:https://help.aliyun.com/zh/prometheus/user-guide/instructions-for-using-the-reporting-address-of-opentelemetry-indicator/

图片

4.1 准备工作

在接入可观测监控 Prometheus 版之前,请您确保已经创建如下类型的 Prometheus 实例,具体操作请参考:

  • Prometheus 实例 for 容器服务 [ 11]
  • Prometheus 实例 for 通用 [ 12]
  • Prometheus 实例 for ECS [ 13]
  • Prometheus 实例 for 云服务 [ 14]

4.2 获取 OpenTelemetry 指标上报地址

  1. 登录 Prometheus 控制台。

  2. 在左侧导航栏单击监控列表,进入可观测监控 Prometheus 版的实例列表页面。

  3. 在页面顶部选择 Prometheus 实例所在的地域,并在目标 Prometheus 实例右侧的操作列单击设置。

  4. 在设置页签上,根据需求复制公网或内网的 OpenTelemetry 指标上报地址(当前仅支持 HTTP 形式,暂不支持使用 gRPC)。

图片

4.3 应用程序改造

如下以 Java 语言为例,在 SpringBoot 项目中进行 OpenTelemetry 指标的埋点。添加依赖


  <properties>
      <java.version>1.8</java.version>
      <org.springframework.boot.version>2.7.17</org.springframework.boot.version>
      <org.projectlombok.version>1.18.0</org.projectlombok.version>
      <opentelemetry.version>1.31.0</opentelemetry.version>
  </properties>

  <dependencies>
      <!-- springboot -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <version>${org.springframework.boot.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
          <version>${org.springframework.boot.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
          <version>${org.springframework.boot.version}</version>
      </dependency>


      <!-- opentelemetry -->
      <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-api</artifactId>
          <version>${opentelemetry.version}</version>
      </dependency>
      <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-sdk</artifactId>
          <version>${opentelemetry.version}</version>
      </dependency>

      <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-exporter-otlp</artifactId>
          <version>${opentelemetry.version}</version>
      </dependency>
  </dependencies>

初始化 OpenTelemetry Bean

修改 OtlpHttpMetricExporterBuilder 中的  Endpoint 参数,将其替换为上文获取的 OpenTelemetry 指标上报地址,即可将应用的 OpenTelemetry 指标接入可观测监控 Prometheus 版。

详细请参考示例 Demo:https://github.com/OuyangKevin/opentelemetry-metric-java-demo/blob/main/metric-http/README.md

 @Bean
  public OpenTelemetry openTelemetry() {
    String endpoint = httpMetricConfig.getOetlExporterOtlpEndpoint();//自己修改
    Resource resource = Resource.getDefault().toBuilder()
                       .put("service.name", "opentelemetry-metric-demo-http")
                       .put("service.version", "0.0.1").build();

    SdkMeterProvider defaultSdkMeterProvider = SdkMeterProvider.builder()
            .registerMetricReader(PeriodicMetricReader.builder(
                    OtlpHttpMetricExporter.builder()
                            .setEndpoint(endpoint)
                            .build())
                    .setInterval(15, TimeUnit.SECONDS).build())
            .setResource(resource)
            .build();


    OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
            .setMeterProvider(defaultSdkMeterProvider)
            .buildAndRegisterGlobal();
    return openTelemetry;
  }

在初始化 OpenTelemetry bean 时,可以对上报的客户端进行详细地参数设置,具体配置说明如下:

1)OpenTelemetry 相关客户端默认没有开启压缩,建议设置 Compression 参数为 gzip,减少网络传输消耗。

OtlpHttpMetricExporter.builder()
 .setEndpoint("******")
 .setCompression("gzip")
 .build()

2)OpenTelemetry 指标上报可观测监控 Prometheus 版后,若需要针对所有的指标加上前缀,可以设置 Header “metricNamespace”,如下所示设置 metricNamespace 为 ot,所有的上报的指标将会加上"ot_"前缀。

OtlpHttpMetricExporter.builder()
  .setEndpoint("******")
  .setCompression("gzip")
  .addHeader("metricNamespace","ot")
   .build()

3)OpenTelemetry 指标上报到可观测监控 Prometheus 版后,所有的指标默认会带上 OpenTelemetry Scope Lables,如果不希望添加默认的 Scope Lables,可以设置 Header skipGlobalLabel=true,如下所示。

OtlpHttpMetricExporter.builder()
  .setEndpoint("******")
  .setCompression("gzip")
  .addHeader("skipGlobalLabel","true")
  .build()

定义业务指标,如下样例设置了一个 LongCounter 及 LongHistogram。

@RestController
public class MetricController {

    @Autowired
    private OpenTelemetry openTelemetry;

    @GetMapping("/ping")
    public String ping(){
         long startTime = System.currentTimeMillis();
         Meter meter = openTelemetry.getMeter("io_opentelemetry_metric_ping");

         LongCounter longCounter = meter.counterBuilder("ping_long_counter")
                 .setDescription("ot http demo long_counter")
                 .setUnit("ms")
                 .build();

         LongHistogram longHistogram= meter.histogramBuilder("ping_long_histogram")
             .ofLongs()
             .setDescription("ot http demo histogram")
             .setUnit("ms")
             .build();

         try{
             longCounter.add(1,Attributes.of(AttributeKey.stringKey("regionId"),"cn-hangzhou"));
             TimeUnit.MILLISECONDS.sleep(new Random().nextInt(10));
         }catch (Throwable e){

         }finally {
             longHistogram.record(System.currentTimeMillis() - startTime);
         }
         return "ping success!";
    }
}

关于 OpenTelemetry 指标模型与阿里云可观测监控 Prometheus 版指标模型转化的映射关系如下。由于 Prometheus 对于 delta Histogram 支持需要转化为 cumulative Histogram,所以可观测监控 Prometheus 版暂时不支持 OpenTelemetry delta Histogram 转化,建议在该场景下使用 OpenTelemetry cumulative Histogram。

图片

4.4 Grafana 中查看监控数据

  1. 登录可观测可视化 Grafana 版控制台 [ 15]
  2. 在工作区管理页面单击 Grafana 共享版,然后选择对应的公网地址单击登录
  3. 在左侧导航栏单击图标,然后 Explore 右侧选择对应的 Datasource。
  4. 配置自己的大盘与告警,如下为客户利用 OpenTelemetry 指标配置的大盘。

图片

阿里云可观测监控 Prometheus 版 VS 开源 Prometheus

阿里云可观测监控 Prometheus 版全面对接开源 Prometheus 生态,支持类型丰富的组件监控,覆盖绝大部分开源基础设施软件指标采集能力。提供多种开箱即用的预置监控大盘,并集成丰富的 Kubernetes 基础监控以及常用服务预设看板,且提供全面托管的 Prometheus 服务。阿里云可观测监控 Prometheus 版的优势可以归纳为 “开箱即用”、“低成本”、“开源兼容”、“数据规模无上限”、“高性能”、“高可用性”

图片

参考文档:

https://www.timescale.com/blog/prometheus-vs-opentelemetry-metrics-a-complete-guide/

https://opentelemetry.io/docs/specs/otel/metrics/data-model/

https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/

https://github.com/open-telemetry/opentelemetry-collector-contrib

相关链接:

[1] Instruments

https://opentelemetry.io/docs/specs/otel/metrics/api/#instrument

[2] Sums

https://github.com/open-telemetry/opentelemetry-proto/blob/v0.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L230

[3] monotonic

https://en.wikipedia.org/wiki/Monotonic_function

[4] examplars

https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exemplars

[5] Gauge

https://github.com/open-telemetry/opentelemetry-proto/blob/v0.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L200

[6] Histogram

https://github.com/open-telemetry/opentelemetry-proto/blob/v0.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L258

[7] 介绍

https://prometheus.io/docs/concepts/metric_types/

[8] otlp-metric-points-to-prometheus

https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/#otlp-metric-points-to-prometheus

[9] prometheus-client-bridge

https://github.com/open-telemetry/opentelemetry-java-contrib/blob/main/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java

[10] Prometheus 控制台

https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Fprometheus.console.aliyun.com%2F#/home

[11] Prometheus 实例 for 容器服务

https://help.aliyun.com/zh/prometheus/user-guide/create-a-prometheus-instance-to-monitor-an-ack-cluster

[12] Prometheus 实例 for 通用

https://help.aliyun.com/zh/prometheus/user-guide/create-a-prometheus-instance-for-remote-storage

[13] Prometheus 实例 for ECS

https://help.aliyun.com/zh/prometheus/user-guide/create-a-prometheus-instance-to-monitor-an-ecs-instance

[14] Prometheus 实例 for 云服务

https://help.aliyun.com/zh/prometheus/user-guide/create-a-prometheus-instance-to-monitor-alibaba-cloud-services

[15] 可观测可视化 Grafana 版控制台

https://account.aliyun.com/login/login.htm?oauth_callback=/#/grafana/workspace/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1400783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Softmax函数介绍

Softmax函数是一种常用的激活函数&#xff0c;用于将一组实数值转换为概率分布。它常用于多类别分类问题中&#xff0c;将输入向量映射为各个类别的概率。 Softmax函数的公式如下&#xff1a; 其中&#xff0c;示输入向量的第 &#xfffd;i 个元素&#xff0c;&#xfffd;n …

【目标检测】YOLOv5算法实现(九):模型预测

本系列文章记录本人硕士阶段YOLO系列目标检测算法自学及其代码实现的过程。其中算法具体实现借鉴于ultralytics YOLO源码Github&#xff0c;删减了源码中部分内容&#xff0c;满足个人科研需求。   本系列文章主要以YOLOv5为例完成算法的实现&#xff0c;后续修改、增加相关模…

RHCE上课笔记(前半部分)

第一部分 网络服务 第一章 例行性工作 1.单一执行的例行性工作 单一执行的例行性工作&#xff08;就像某一个时间点 的闹钟&#xff09;&#xff1a;仅处理执行一次 1.1 at命令&#xff1a;定时任务信息 [rhellocalhost ~]$ rpm -qa |grep -w at at-spi2-core-2.40.3-1.el9.x…

SDCMS靶场通过

考察核心&#xff1a;MIME类型检测文件内容敏感语句检测 这个挺搞的&#xff0c;一开始一直以为检查文件后缀名的&#xff0c;每次上传都失败&#xff0c;上传的多了才发现某些后缀名改成php也可通过&#xff0c;png图片文件只把后缀名改成php也可以通过&#xff0c;之前不成功…

最全机器学习预测全家桶,持续更新!看这一篇绝对够了!MATLAB代码

全家桶一直在持续更新中&#xff0c;截止到本期&#xff0c;一共发了7篇关于机器学习预测全家桶的文章。且后续还会继续更新。参考文章如下&#xff1a; 1.五花八门的机器学习预测&#xff1f;一篇搞定不行吗&#xff1f; 2.机器学习预测全家桶&#xff0c;多步预测之BiGRU、Bi…

阿里云国外服务器多少钱一个月?24元/月

阿里云国外服务器优惠活动「全球云服务器精选特惠」&#xff0c;国外服务器租用价格24元一个月起&#xff0c;免备案适合搭建网站&#xff0c;部署独立站等业务场景&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云国外服务器优惠活动&#xff1a; 全球云服务器精选特惠…

代码随想录刷题题Day38

刷题的第三十八天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day38 任务 ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组 1 最长递增子序列 300.最长递增子序列 …

运筹说 第107期 | 排队论创始人——阿格纳·克拉鲁普·爱尔朗

前面我们已经了解了非线性规划的相关内容&#xff0c;相信大家一定也有所收获&#xff0c;下面我们将带着大家继续了解排队论的相关内容&#xff0c;在本次文章中我们将一起走近排队论的奠基人——阿格纳克拉鲁普爱尔朗&#xff08;Agner Krarup Erlang&#xff09;&#xff0c…

x-cmd pkg | jieba - 中文结巴分词工具

目录 简介首次用户功能特点竞品分析进一步阅读 简介 结巴中文分词&#xff08;jieba&#xff09;是一款在 Python 环境下使用的开源中文文本分词工具。它支持多种分词模式&#xff0c;包括精确模式、全模式和搜索引擎模式&#xff0c;同时支持繁体分词和自定义词典。因其易用性…

【JavaEE】_基于UDP实现网络通信

目录 1. 服务器 1.1 实现逻辑 1.2 代码 1.3 部分代码解释 2. 客户端 2.1 实现逻辑 2.2 代码 2.3 客户端部分代码解释 3. 程序运行结果 4. 服务器客户端交互逻辑 此篇内容为实现UDP版本的回显服务器echo server&#xff1b; 普通服务器&#xff1a;收到请求&#xff…

Unity中ShaderGraph下获取主灯

文章目录 前言一、ShaderGraph获取主灯1、创建ShaderGraph2、创建一个自定义方法&#xff08;Custom Function&#xff09;节点3、新建两个 Vector3 类型的输出变量4、选择自定义节点程序体为 string 类型5、编写程序体6、我们输出主光方向看看效果7、我们输出主光颜色看看效果…

ios适配虚拟home键

在H5开发过程中遇到一个兼容性问题。iphone手机的虚拟home键会对屏幕底部的内容造成遮挡。要处理此问题&#xff0c;需要清楚安全区域这个概念。 安全区域 根据刘海和虚拟Home键&#xff0c;Apple为其设备提供了屏幕安全区域的视觉规范 竖屏&#xff1a;竖屏的时候&#xff…

「优选算法刷题」:查找总价格为目标值的两个商品

一、题目 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 示例 1&#xff1a; 输入&#xff1a;price [3, 9, 12, 15], target 18 输出&#xff1a;[3,15] 或者 [15,3]示例…

OpenCV-Python(49):图像去噪

目标 学习使用非局部平均值去噪算法去除图像中的噪音学习函数cv2.fastNlMeansDenoising()、cv2.fastNlMeansDenoisingColored等 原理 在前面的章节中我们已经学习了很多图像平滑技术&#xff0c;比如高斯平滑、中值平滑等。当噪声比较小时&#xff0c;这些技术的效果都是很好…

【Qt之模型视图】1. 模型和视图架构

1. 模型/视图架构是什么及有什么用 MVC&#xff08;Model-View-Control&#xff09;是一种源自Smalltalk的设计模式&#xff0c;通常用于构建用户界面。 MVC由三种类型的对象组成。模型是应用对象&#xff0c;用来表示数据&#xff1b;视图是模型的用户界面&#xff0c;用来显…

Miracast无线投屏的操作步骤

家里有台老爷机&#xff0c;估计在10年以上了。内核屏显还是HD 4400。今天原本在尝试挂蓝牙音箱&#xff0c;没整成。意外地激活了无线投屏。Miracast是一个wifi本身的功能包&#xff0c;可以让台式机通过wifi与屏幕互联&#xff0c;不必通过hdmi线。 Step1.确认无线投屏能力&…

【大数据分析与挖掘技术】Mahout推荐算法

目录 一、推荐的定义与评估 &#xff08;一&#xff09;推荐的定义 &#xff08;二&#xff09;推荐的评估 二、Mahout中的常见推荐算法 &#xff08;一&#xff09;基于用户的推荐算法 &#xff08;二&#xff09;基于物品的推荐算法 &#xff08;三&#xff09;基于S…

【C++干货铺】C++异常处理机制

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 C语言传统的处理错误的方式 C处理异常方式 异常的使用 异常的抛出和捕获 异常的重新抛出 异常安全 异常规范 自定义异常体系 C标准库中的异常体系 ​编辑…

【Linux系统编程二十八】基于条件变量的阻塞队列(生产消费模型)

【Linux系统编程二十八】基于条件变量的阻塞队列(生产消费模型&#xff09; 一.同步问题二.条件变量1.实现原理2.等待的前提3.使用接口①.【定义条件变量】②.【初始化条件变量】③.【让线程去条件变量下等待】④.【为什么第二个参数是锁&#xff1f;】条件变量和锁的关系是什么…

swift基础语法

swift学习笔记 参考教程 https://www.runoob.com/swift/swift-data-types.html swift代码规范 https://juejin.cn/post/7129465308376465422 1 环境搭建 必须要有苹果电脑且安装Xcode 2 基本语法 Swift是类型安全的语言&#xff0c;编译时会进行类型检查 import Cocoa var m…