Metrics SDK
状态: 混合
OpenTelemetry 的用户需要一种方式,使他们的 instrumentation 与 OpenTelemetry API 的交互能够实际产生遥测数据。OpenTelemetry SDK(以下简称 SDK)是 OpenTelemetry API 的一个实现,它为用户提供了这种功能。
所有 OpenTelemetry 的语言实现都**必须**提供一个 SDK。
MeterProvider
状态: 稳定
MeterProvider **必须**提供一种方式,允许指定一个 Resource。如果指定了 Resource,它**应该**与该 MeterProvider 产生的任何 Meter 所产生的指标相关联。 Tracing SDK 规范已经提供了一些关于如何高效实现这一点建议。
MeterProvider 创建
SDK **应该**允许创建多个独立的 MeterProvider。
Meter 创建
**应该**只能通过 MeterProvider 创建 Meter 实例(参见 API)。
MeterProvider **必须**实现 Get a Meter API。
用户提供的输入**必须**用于创建一个 InstrumentationScope 实例,该实例存储在创建的 Meter 上。
在指定无效 name(null 或空字符串)的情况下,**必须**返回一个工作的 Meter 作为回退,而不是返回 null 或抛出异常,其 name **应该**保持原始的无效值,并且**应该**记录一条报告指定值无效的消息。
状态:开发中 - MeterProvider **必须**使用配置的 MeterConfigurator 计算相关的 MeterConfig,并创建一个行为符合该 MeterConfig 的 Meter。
配置
配置(例如 MetricExporters、MetricReaders、Views,以及(**开发中**) MeterConfigurator)**必须**由 MeterProvider 拥有。配置**可以**在 MeterProvider 创建时应用(如果适用)。
MeterProvider **可以**提供更新配置的方法。如果配置被更新(例如,添加一个 MetricReader),更新后的配置**必须**也适用于所有已返回的 Meters(即,从 MeterProvider 之前或之后获取的 Meter 实例都**必须**不受影响)。注意:在实现上,这可能意味着 Meter 实例拥有对其 MeterProvider 的引用,并且仅通过此引用访问配置。
MeterConfigurator
状态: 开发中
MeterConfigurator 是一个函数,用于计算 Meter 的 MeterConfig。
该函数必须接受以下参数
meter_scope:Meter的InstrumentationScope。
该函数**必须**返回相关的 MeterConfig,或一些指示**应该**使用 默认 MeterConfig 的信号。此信号**可以**是 nil、null、空,或默认 MeterConfig 的实例,具体取决于语言的惯用法。
此函数在 Meter 首次创建时调用,并且在 MeterProvider 的 MeterConfigurator 更新时(如果支持更新)对每个已存在的 Meter 调用。因此,快速返回很重要。
MeterConfigurator 被建模为一个函数,以最大化灵活性。但是,实现**可以**提供快捷方式或辅助函数来适应常见的用例。
- 通过名称选择一个或多个 Meter,支持精确匹配或模式匹配。
- 禁用一个或多个特定的 Meter。
- 禁用所有 Meter,并选择性地启用一个或多个特定的 Meter。
Shutdown
此方法提供了一种方式,让 provider 进行任何必要的清理。
每个 MeterProvider 实例**只能**调用一次 Shutdown。调用 Shutdown 后,不允许后续尝试获取 Meter。SDK **应该**在可能的情况下为这些调用返回一个有效的 no-op Meter。
Shutdown 应提供一种方式,让调用者知道它是否成功、失败或超时。
Shutdown **应该**在某个超时时间内完成或中止。Shutdown **可以**实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者**可以**决定是否使 shutdown 超时可配置。
Shutdown **必须**至少通过调用已注册的 MetricReader 和 MetricExporter 实例上的 Shutdown 来实现。
ForceFlush
此方法提供了一种方式,让 Provider 通知已注册的、具有关联 Push Metric Exporter 的 MetricReader 实例,以便它们尽可能地收集和发送指标。注意:Pull Metric Exporter 只能在被 scraper 请求时发送数据,因此 ForceFlush 的意义不大。
ForceFlush **必须**调用所有已注册的、实现 ForceFlush 的 MetricReader 实例上的 ForceFlush。
ForceFlush **应该**提供一种方式,让调用者知道它是否成功、失败或超时。如果存在错误条件,ForceFlush **应该**返回某种 **ERROR** 状态;如果没有错误条件,它**应该**返回某种 **NO ERROR** 状态。语言实现**可以**决定如何模拟 **ERROR** 和 **NO ERROR**。
ForceFlush **应该**在某个超时时间内完成或中止。ForceFlush **可以**实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者**可以**决定是否使 flush 超时可配置。
View
View 为 SDK 用户提供了自定义 SDK 输出指标的灵活性。以下是 View 可能需要的示例:
- 自定义哪些 Instruments 被处理/忽略。例如,一个 instrumented library 可以同时提供温度和湿度,但应用程序开发人员可能只想要温度。
- 自定义 aggregation - 如果 Instrument 的默认 aggregation 不能满足用户的需求。例如,HTTP 客户端库可能默认暴露 HTTP 客户端请求持续时间作为 Histogram,但应用程序开发人员可能只想要出站请求的总数。
- 自定义要报告给指标的 attribute(s)。例如,HTTP 服务器库可能暴露 HTTP 动词(例如 GET、POST)和 HTTP 状态码(例如 200、301、404)。应用程序开发人员可能只关心 HTTP 状态码(例如,报告每个 HTTP 状态码的 HTTP 请求总数)。也可能存在极端情况,应用程序开发人员不需要任何 attributes(例如,只获取所有传入请求的总数)。
SDK **必须**提供功能,允许用户为 MeterProvider 创建 Views。此功能**必须**接受 Instrument 选择条件和结果的 stream 配置作为输入。
SDK **必须**提供向 MeterProvider 注册 Views 的方法。
Instrument 选择条件
Instrument 选择条件是决定 View 是否应用于 Instrument 的谓词。
条件**应该**被视为累加的。这意味着一个 Instrument 必须匹配**所有**提供的条件,View 才能被应用。例如,如果条件是*instrument name == “Foobar”* 和 *instrument type is Histogram*,它将被视为*(instrument name == “Foobar”)AND(instrument type is Histogram)*。
SDK **必须**接受以下条件:
name:要匹配的 Instrument 的名称。此name的评估方式如下:- 如果
name的值为*,则该条件匹配所有 Instruments。 - 如果
name的值与 Instrument 完全相同,则该条件匹配该 Instrument。
此外,SDK **可以**支持使用以下字符对
name条件进行通配符模式匹配。- 问号(
?):匹配任何单个字符 - 星号(
*):匹配任意数量的任意字符,包括零个
如果支持通配符模式匹配,则当通配符模式匹配 Instrument 名称时,
name条件将匹配。如果 SDK 不支持通用通配符,它**必须**仍然将特殊的单星号(
*)字符识别为匹配所有 Instruments。用户可以提供一个
name,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受name,但**不得**强制用户提供。- 如果
type:要匹配的 Instruments 的类型。如果type的值与 Instrument 的类型相同,则该条件匹配该 Instrument。用户可以提供一个
type,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受type,但**不得**强制用户提供。unit:如果unit的值与 Instrument 的单位相同,则该条件匹配该 Instrument。用户可以提供一个
unit,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受unit,但**不得**强制用户提供。meter_name:如果meter_name的值与创建 Instrument 的 Meter 相同,则该条件匹配该 Instrument。用户可以提供一个
meter_name,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受meter_name,但**不得**强制用户提供。meter_version:如果meter_version的值与创建 Instrument 的 Meter 版本相同,则该条件匹配该 Instrument。用户可以提供一个
meter_version,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受meter_version,但**不得**强制用户提供。meter_schema_url:如果meter_schema_url的值与创建 Instrument 的 Meter 模式 URL 相同,则该条件匹配该 Instrument。用户可以提供一个
meter_schema_url,但这由他们自行决定。因此,Instrument 选择条件参数需要被结构化为接受meter_schema_url,但**不得**强制用户提供。
SDK **可以**接受额外的条件。例如,一个强类型语言可能支持点类型条件(例如,允许用户根据底层数字是整数还是有理数来选择 Instruments)。用户可以提供 SDK 接受的这些额外条件,但这由他们自行决定。因此,Instrument 选择条件可以被结构化为接受这些条件,但**不得**强制用户提供。
Stream 配置
Stream 配置是定义 MeterProvider 将用于定义遥测管道的 metric stream 的参数。
SDK **必须**接受以下 stream 配置参数:
name:**应该**使用的 metric stream 名称。为了避免冲突,如果提供了一个
name,View **应该**有一个 instrument selector,最多选择一个 instrument。如果具有 stream 配置name参数的 View 的 Instrument 选择条件可以匹配多个 instrument(即通配符),SDK **可以**根据初始化 错误处理原则快速失败。用户可以提供一个
name,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受一个name,但**不得**强制用户提供。如果用户没有提供name值,则默认**应该**使用 View 匹配的 Instrument 的名称。description:**应该**使用的 metric stream 描述。用户可以提供一个
description,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受一个description,但**不得**强制用户提供。如果用户没有提供description值,则默认**应该**使用 View 匹配的 Instrument 的描述。attribute_keys:这至少是一个属性键的允许列表,用于捕获 metric stream 中度量的属性。允许列表包含标识**必须**保留的属性的属性键,而所有其他属性**必须**被忽略。实现**可以**为该参数接受额外的属性过滤功能。
用户可以提供
attribute_keys,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受attribute_keys,但**不得**强制用户提供。如果用户没有提供任何值,SDK **应该**使用 instrument 上配置的Attributes建议参数。如果Attributes建议参数不存在,则**必须**保留所有属性。此外,实现**应该**支持配置属性键的排除列表。排除列表包含标识**必须**排除的属性的属性键,所有其他属性**必须**保留。如果一个属性键既被包含又被排除,SDK **可以**根据初始化 错误处理原则快速失败。
aggregation:用于聚合 metric stream 数据的 aggregation 函数的名称。用户可以提供一个
aggregation,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受一个aggregation,但**不得**强制用户提供。如果用户没有提供aggregation值,MeterProvider**必须**根据 MetricReader 实例应用一个可配置的 默认 aggregation(基于 instrument 类型)。exemplar_reservoir:一个函数类型,用于生成MeterProvider在存储 exemplars 时使用的 exemplar reservoir。此函数类型需要是一个工厂或回调,类似于 aggregation 选择功能,允许根据 aggregation 选择不同的 reservoir。用户可以提供一个
exemplar_reservoir,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受一个exemplar_reservoir,但**不得**强制用户提供。如果用户没有提供exemplar_reservoir值,MeterProvider**必须**应用 默认 exemplar reservoir。aggregation_cardinality_limit:一个正整数值,定义在收集周期内由单个 instrument 发出的最大数据点数。请参见下文的 基数限制。用户可以提供一个
aggregation_cardinality_limit,但这由他们自行决定。因此,stream 配置参数需要被结构化为接受一个aggregation_cardinality_limit,但**不得**强制用户提供。如果用户没有提供aggregation_cardinality_limit值,MeterProvider**必须**应用 MetricReader 配置的 默认 aggregation cardinality limit。
Measurement 处理
SDK **应该**使用以下逻辑来确定如何处理由 Instrument 产生的 Measurements:
- 确定“拥有” Instrument 的
MeterProvider。 - 如果
MeterProvider没有注册任何View,则采用 Instrument,并根据 MetricReader 实例的aggregation属性,对 Instrument 类型应用默认的 Aggregation。 Instrument advisory parameters(如果有)**必须**得到遵守。 - 如果
MeterProvider注册了一个或多个View(s)- 如果 Instrument 能够匹配 instrument 选择条件,则对于每个 View:
- 尝试独立于为同一匹配 Instrument 注册的任何其他 View 来应用 View 的 stream 配置(即 View 不会合并)。这可能会导致 冲突的指标标识,即使 stream 配置指定了不重叠的属性(例如,一个 View 设置了
aggregation,另一个 View 设置了attribute_keys,两者都将 streamname留为 Instrument 配置的默认值)。如果应用 View 导致了冲突的指标标识,则实现**应该**应用 View 并发出警告。如果无法在不产生语义错误的情况下应用 View(例如,View 将异步 instrument 设置为使用 Explicit bucket histogram aggregation),则实现**应该**发出警告并像 View 未被应用一样继续。如果 View 和 Instrument advisory parameters 都指定了 Stream configuration 的相同方面,则 View 定义的设置**必须**优先于 advisory parameters。
- 尝试独立于为同一匹配 Instrument 注册的任何其他 View 来应用 View 的 stream 配置(即 View 不会合并)。这可能会导致 冲突的指标标识,即使 stream 配置指定了不重叠的属性(例如,一个 View 设置了
- 如果 Instrument 未能与任何已注册的
View(s) 匹配,SDK **应该**使用默认的 aggregation 和 temporality 来启用该 instrument。用户可以使用 Drop aggregation 配置全局匹配的 Views 来默认禁用 instruments。
- 如果 Instrument 能够匹配 instrument 选择条件,则对于每个 View:
View 示例
以下是 SDK 为 MeterProvider 创建 Views 的功能的示例。
# Python
'''
+------------------+
| MeterProvider |
| Meter A |
| Counter X |
| Histogram Y |
| Meter B |
| Gauge Z |
+------------------+
'''
# metrics from X and Y (reported as Foo and Bar) will be exported
meter_provider
.add_view("X")
.add_view("Foo", instrument_name="Y")
.add_view(
"Bar",
instrument_name="Y",
aggregation=HistogramAggregation(buckets=[5.0, 10.0, 25.0, 50.0, 100.0]))
.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()))
# all the metrics will be exported using the default configuration
meter_provider.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()))
# all the metrics will be exported using the default configuration
meter_provider
.add_view("*") # a wildcard view that matches everything
.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()))
# Counter X will be exported as cumulative sum
meter_provider
.add_view("X", aggregation=SumAggregation())
.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()))
# Counter X will be exported as a delta sum and the default attributes
# Counter X, Histogram Y, and Gauge Z will be exported with 2 attributes (a and b)
# A warning will be emitted for conflicting metric identities on Counter X (as two Views matching that Instrument
# are configured with the same default name X) and streams from both views will be exported
meter_provider
.add_view("X", aggregation=SumAggregation())
.add_view("*", attribute_keys=["a", "b"]) # wildcard view matches everything, including X
.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()),
temporality=lambda kind: Delta if kind in [Counter, AsyncCounter, Histogram] else Cumulative)
# Only Counter X will be exported, with the default configuration (match-all drop aggregation does not result in
# conflicting metric identities)
meter_provider
.add_view("X")
.add_view("*", aggregation=DropAggregation()) # a wildcard view to disable all instruments
.add_metric_reader(PeriodicExportingMetricReader(ConsoleExporter()))
聚合
Aggregation(通过 View 配置)会告知 SDK 如何计算来自传入 Instrument Measurements 的 Aggregated Metrics。
注意:此处使用“aggregation”一词而不是“aggregator”。**建议**实现者为 SDK 允许自定义 aggregation 实现的未来保留“aggregator”一词。
Aggregation 指定一个操作(即 可分解的聚合函数,如 Sum、Histogram、Min、Max、Count)和可选的配置参数覆盖。操作的默认配置参数值将被使用,除非被可选的配置参数覆盖。
注意:实现**可以**选择其语言的最佳惯用实践来表示 Aggregation 和可选配置参数的语义。
例如:View 通过字符串名称(例如,“ExplicitBucketHistogram”)指定 Aggregation。
# Use Histogram with custom boundaries
meter_provider
.add_view(
"X",
aggregation="ExplicitBucketHistogram",
aggregation_params={"Boundaries": [0, 10, 100]}
)
例如:View 通过类/类型实例指定 Aggregation。
// Use Histogram with custom boundaries
meterProviderBuilder
.AddView(
instrumentName: "X",
aggregation: new ExplicitBucketHistogramAggregation(
boundaries: new double[] { 0.0, 10.0, 100.0 }
)
);
SDK **必须**提供以下 Aggregation 来支持 Metrics Data Model 中的 Metric Points。
SDK **应该**提供以下 Aggregation:
Drop Aggregation
Drop Aggregation 告知 SDK 忽略/丢弃此 Aggregation 的所有 Instrument Measurements。
此 Aggregation 没有配置参数。
默认 Aggregation
Default Aggregation 告知 SDK 使用 Instrument kind 来选择一个 aggregation,并使用 advisory 参数来影响 aggregation 的配置参数(如“Selected Aggregation”列所示)。
| Instrument Kind | Selected Aggregation |
|---|---|
| Counter | Sum Aggregation |
| Asynchronous Counter | Sum Aggregation |
| UpDownCounter | Sum Aggregation |
| Asynchronous UpDownCounter | Sum Aggregation |
| Gauge | Last Value Aggregation |
| Asynchronous Gauge | Last Value Aggregation |
| Histogram | Explicit Bucket Histogram Aggregation,如果提供了 ExplicitBucketBoundaries advisory parameter。 |
此 Aggregation 没有配置参数。
Sum Aggregation
Sum Aggregation 告知 SDK 为 Sum Metric Point 收集数据。
聚合的单调性由 instrument 类型决定。
| Instrument Kind | SumType |
|---|---|
| Counter | Monotonic |
| UpDownCounter | Non-Monotonic |
| Histogram | Monotonic |
| Gauge | Non-Monotonic |
| Asynchronous Gauge | Non-Monotonic |
| Asynchronous Counter | Monotonic |
| Asynchronous UpDownCounter | Non-Monotonic |
此 Aggregation 没有配置参数。
此 Aggregation 告知 SDK 收集:
Measurement值的算术和。
Last Value Aggregation
Last Value Aggregation 告知 SDK 为 Gauge Metric Point 收集数据。
此 Aggregation 没有配置参数。
此 Aggregation 告知 SDK 收集:
- 最后一个
Measurement。 - 最后一个
Measurement的时间戳。
Histogram Aggregations
所有 histogram Aggregations 都告知 SDK 收集:
Measurement值在总体中的计数。Measurement值在总体中的算术和。当与记录负值测量的 instruments(例如UpDownCounter或ObservableGauge)一起使用时,**不应该**收集此项。- Min (可选)
Measurement值在总体中的值。 - Max (可选)
Measurement值在总体中的值。
显式分桶直方图聚合
显式分桶直方图聚合会通知 SDK,使用一组显式的边界值来进行直方图分桶,以收集 直方图度量点 的数据。
此聚合遵守以下配置参数
| 键 | 值 | 默认值 | 描述 |
|---|---|---|---|
| Boundaries | double[] | [ 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000 ] | 表示显式分桶边界值的递增值的数组。 默认值代表以下分桶(很大程度上受 Prometheus 客户端默认分桶的影响,例如 Java 和 Go) (-∞, 0], (0, 5.0], (5.0, 10.0], (10.0, 25.0], (25.0, 50.0], (50.0, 75.0], (75.0, 100.0], (100.0, 250.0], (250.0, 500.0], (500.0, 750.0], (750.0, 1000.0], (1000.0, 2500.0], (2500.0, 5000.0], (5000.0, 7500.0], (7500.0, 10000.0], (10000.0, +∞)。SDK 应该在未显式提供边界值时使用默认值,除非有充分理由使用不同的值(例如,出于稳定 SDK 版本向后兼容性的原因)。 |
| RecordMinMax | true, false | true | 是否记录 min 和 max。 |
显式分桶以其上边界表示。分桶不包含下边界,包含上边界(正无穷大除外)。测量值被定义为落入边界值大于或等于测量值的最大编号的分桶中。
基于 2 的指数分桶直方图聚合
基于 2 的指数直方图聚合会通知 SDK,收集 指数直方图度量点 的数据,该度量点使用基于 2 的指数公式来确定分桶边界,并使用整数 scale 参数来控制分辨率。实现会根据数据进行必要的 scale 调整。
此聚合遵守以下配置参数
| 键 | 值 | 默认值 | 描述 |
|---|---|---|---|
| MaxSize | integer | 160 | 正范围和负范围中每个分桶的最大数量,不包括特殊零分桶。 |
| MaxScale | integer | 20 | 最大 scale 因子。 |
| RecordMinMax | true, false | true | 是否记录 min 和 max。 |
默认的 160 个分桶旨在提供对高分辨率直方图的默认支持,该直方图能够覆盖从 1ms 到 100s 的长尾延迟分布,相对误差小于 5%。由于 160 可以分解为 10 * 2**K,因此对于 scale K,最大对比度相对容易推导。
| Scale | 10 * 2**K 个分桶的最大数据对比度 |
|---|---|
| K+2 | 5.657 (2**(10/4)) |
| K+1 | 32 (2**(10/2)) |
| K | 1024 (2**10) |
| K-1 | 1048576 (2**20) |
下表显示了 160 个分桶的理想 scale 如何根据输入范围计算得出
| Input range | Contrast | Ideal Scale | Base | Relative error |
|---|---|---|---|---|
| 1ms - 4ms | 4 | 6 | 1.010889 | 0.542% |
| 1ms - 20ms | 20 | 5 | 1.021897 | 1.083% |
| 1ms - 1s | 10**3 | 4 | 1.044274 | 2.166% |
| 1ms - 100s | 10**5 | 3 | 1.090508 | 4.329% |
| 1μs - 10s | 10**7 | 2 | 1.189207 | 8.643% |
请注意,相对误差计算为分桶宽度的一半除以分桶中点,这在每个分桶中都是相同的。使用 [1, base) 中的分桶,我们有 (bucketWidth / 2) / bucketMidpoint = ((base - 1) / 2) / ((base + 1) / 2) = (base - 1) / (base + 1)。
此聚合使用“理想”scale 的概念。理想 scale 要么是
MaxScale(参见配置参数),通常用于单值直方图聚合,其中 scale 未受到其他限制。- 最大的 scale 值,以便在正范围或负范围内,表示完整输入数据范围所需的桶数不超过最大数量。
处理所有正常值
实现必须接受 IEEE 浮点值的整个正常范围(即,除 +Inf、-Inf 和 NaN 值之外的所有值)。
实现不应将非正常值(即 +Inf、-Inf 和 NaN)计入 sum、min 和 max 字段,因为这些值无法映射到有效分桶。
实现可以圆整亚正常值(subnormal values)使其远离零到最近的正常值。
支持最小和最大 scale
实现必须维护自动 scale 参数不会超出的合理的最小和最大 scale 参数。最大 scale 由 MaxScale 配置参数定义。
对单个测量使用最大 scale
当直方图在正范围或负范围中只有一个值时,实现应使用最大 scale。
维护理想 scale
实现应根据需要调整直方图 scale,以在最大大小(分桶的最大数量)的约束下保持尽可能高的分辨率。当正范围或负范围的分桶数量超过最大尺寸的一半时,可以实现最佳分辨率(最高的 scale),这样在大小限制下,scale 增加一将是不可能的。
异步回调中的观测
必须为执行收集的特定 MetricReader 调用回调函数,以便在收集期间,通过执行回调所做或产生的观测仅适用于预期的 MetricReader。
实现应忽略在注册回调之外使用异步 instrument API。
实现应使用超时来防止回调执行无限期。
实现必须在开始下一轮收集之前完成给定 instrument 的所有回调执行。
实现不应为之前观察到的但在此次成功的回调中未被观察到的属性集生成聚合的度量数据。有关度量在连续收集中的持久性,请参阅 MetricReader。
基数限制
状态: 稳定
SDK 应该支持配置基数限制。属性的唯一组合数量称为基数。对于给定的度量,基数限制是在收集周期内可以收集的 度量点 的硬限制。基数限制的执行应该发生在属性过滤(如果存在)*之后*。这确保用户可以使用 视图 过滤掉不需要的属性,并防止达到基数限制。
Configuration
聚合的基数限制通过以下三种方式之一定义
- 匹配 instrument 的 视图 具有为流定义的
aggregation_cardinality_limit值,该值应该被使用。 - 如果没有匹配的视图,但
MetricReader为创建聚合的 instrument 定义了默认基数限制值,则应该使用该值。 - 如果以上值均未定义,则应使用默认值 2000。
溢出属性
定义了溢出属性集,其中包含一个名为 otel.metric.overflow 的属性,其值为 true(布尔型),用于报告由于限制而无法独立聚合的 测量值 的合成聚合。
SDK 必须在达到基数限制之前创建具有溢出属性集的 Aggregator,并使用它来聚合无法创建正确 Aggregator 的 测量值。SDK 必须保证,如果不同、非溢出的属性集的数量小于或等于限制,则不会发生溢出。
同步 instrument 的基数限制
具有累积时态(cumulative temporality)的同步 instrument 的 Aggregator 必须继续导出在溢出开始之前观察到的所有属性集。与属性集对应的 Measurements(在溢出前未被观察到)将在由(仅)溢出属性描述的单个数据点中反映出来。
具有增量时态(delta aggregation temporality)的同步 instrument 的 Aggregator 可以选择任意属性集子集进行输出,以维持指定的基数限制。
无论聚合时态如何,SDK 都必须确保每个 Measurement 都反映在恰好一个 Aggregator 中,该 Aggregator 要么与正确的属性集相关联,要么与溢出属性集相关联。
Measurements 在溢出期间不得重复计数或丢失。
异步 instrument 的基数限制
异步 instrument 的 Aggregator 在限制基数时,应优先考虑回调中的首次观察到的属性,无论时态如何。
Meter
对于检测 重复 instrument 注册,不同的 Meter 必须被视为独立的命名空间。
状态:开发中 - Meter 必须根据 Meter 创建期间计算出的 MeterConfig 进行行为。如果 MeterProvider 支持更新 MeterConfigurator,那么在更新后,Meter 必须更新为根据新的 MeterConfig 进行行为。
MeterConfig
状态: 开发中
MeterConfig 定义了 Meter 行为的各种可配置方面。它由以下参数组成
disabled:一个布尔值,指示 Meter 是否已启用。如果未显式设置,
disabled参数应默认为false(即,Meter默认启用)。如果
Meter被禁用,它必须表现得与 No-op Meter 相同。disabled的值必须用于解析 instrument 是否 启用。有关详细信息,请参阅 Instrument Enabled。
重复 instrument 注册
当为来自同一 MeterProvider 的相同 Meters 创建多个具有相同 name 的 Instrument,但它们具有不同的 标识字段 时,就会发生重复 instrument 注册。
发生这种情况时,用户仍然需要能够使用重复的 instrument 进行测量。这意味着 Meter 必须返回一个功能正常的 instrument,即使这会导致 数据模型中的语义错误,也应该能够导出数据。
此外,用户需要收到关于此错误的通知。因此,当发生重复 instrument 注册且未通过 View 进行更正时,应发出警告。发出的警告应包含有关用户如何解决冲突的信息(如果可能)。
- 如果潜在冲突涉及多个
description属性,则通过配置的 View 设置description应避免警告。 - 如果潜在冲突涉及可以通过支持的 View 选择器(例如,名称、instrument 类型)区分的 instrument,则警告中应包含一个重命名 View 的配方。
- 否则(例如,使用多个单位),SDK 应通过报告两个
Metric对象来传递数据,并发出一个通用的警告来描述重复的 instrument 注册。
返回的 Instrument 实例是相同还是不同,作为重复 instrument 注册的结果,这未指定或在何种条件下发生。术语相同(identical)应用于 Instruments,表示所有 标识字段 都相等的实例。术语不同(distinct)应用于 Instruments,表示至少一个字段值不同。
为了满足 数据模型的建议,SDK 必须将来自 相同 Instruments 的数据聚合在一起进行导出。
Name conflict
Instrument 的 name 被定义为不区分大小写。如果 SDK 使用区分大小写的方式来表示此 name,那么当用户传递相同 name 的多个大小写时,就会发生重复 instrument 注册。发生这种情况时,Meter 必须返回一个使用首次看到的 instrument 名称的 instrument,并记录上述相应的错误。
例如,如果用户创建一个名为 requestCount 的 instrument,然后向同一 Meter 请求创建另一个名为 RequestCount 的 instrument,在这两种情况下,都必须向用户返回一个名为 requestCount 的 instrument,并为第二次请求发出日志消息。
Instrument name
当 Meter 创建 instrument 时,应验证 instrument 名称是否符合 instrument 名称语法。
如果 instrument 名称不符合此语法,Meter 应发出错误通知用户名称无效。是否也返回有效的 instrument 未指定。
Instrument unit
当 Meter 创建 instrument 时,不应验证 instrument 单位。如果未提供单位或单位为 null,Meter 必须将其视为与空单位字符串相同。
Instrument description
当 Meter 创建 instrument 时,不应验证 instrument 描述。如果未提供描述或描述为 null,Meter 必须将其视为与空描述字符串相同。
Instrument advisory parameters
Status: Stable, 除非另有说明
当 Meter 创建 instrument 时,应验证 instrument 的建议参数。如果建议参数无效,Meter 应发出错误通知用户,并像未提供参数一样继续。
如果使用不同的建议参数创建了多个 相同 Instruments,Meter 必须返回一个使用首次看到的建议参数的 instrument,并记录 重复 instrument 注册 中描述的相应错误。
如果 View 和建议参数都指定了 流配置 的相同方面,则 View 定义的设置必须优先于建议参数。
Instrument advisory parameter: ExplicitBucketBoundaries
当使用 显式分桶直方图 聚合时,此建议参数适用。
如果匹配的 View 指定了显式分桶直方图聚合(无论是否带分桶边界),则 ExplicitBucketBoundaries 建议参数将被忽略。
如果没有匹配的 View,或者匹配的 View 选择 默认聚合,则必须使用 ExplicitBucketBoundaries 建议参数。如果两者均未提供,则应用默认分桶边界。
Instrument advisory parameter: Attributes
状态: 开发中
此建议参数适用于所有聚合。
Attributes(属性键列表)指定了用于聚合以生成度量流的测量值的推荐属性键集。
如果用户通过 View 提供了属性键,则这些键优先。如果没有配置 View,或者匹配的 View 未指定属性键,则应使用建议参数。如果两者均未提供,则必须保留所有属性。
Instrument enabled
状态: 开发中
当以下任一情况发生时,instrument Enabled 必须返回 false
- 用于创建 instrument 的
Meter的 MeterConfig 参数disabled=true。 - instrument 的所有 解析视图 都配置为 Drop Aggregation。
否则,应返回 true。为了支持其他优化和功能,可以返回 false。
注意:如果用户未进行任何配置更改,Enabled 返回 true,因为默认情况下 MeterConfig.disabled=false,并且 instrument 在没有匹配视图的情况下使用默认聚合。
实现不必确保对 Enabled 调用者来说 MeterConfig.disabled 的更改立即可见。但是,这些更改必须最终可见。
Attribute limits
状态: 稳定
属于 Metrics 的属性目前豁免于 属性限制的通用规则。属性截断或删除可能会影响指标时间序列的身份,该主题需要进一步分析。
Exemplar
状态: 稳定
Exemplars 是聚合数据的示例数据点。它们为一般聚合提供特定的上下文。Exemplars 允许在聚合指标数据和记录测量值的原始 API 调用之间进行关联。Exemplars 支持跨任何度量(不仅仅是那些可以从 Span 派生的度量)的跟踪-度量关联。
一个 Exemplar 是一个记录的 Measurement,它暴露了以下信息
- API 调用记录的
Measurement的value。 - API 调用记录
Measurement的time。 - 与
Measurement关联的Attributes集,这些属性尚未包含在度量数据点中。 - 在 API 调用时,与
Measurement处于活跃 Span 处于 Context 中的 trace id 和 span id。
例如,如果用户配置了一个 View 来保留属性:X 和 Y,但用户进行了如下测量记录
const span = tracer.startSpan('makeRequest');
api.context.with(api.trace.setSpan(api.context.active(), span), () => {
// Record a measurement.
cache_miss_counter.add(1, {"X": "x-value", "Y": "y-value", "Z": "z-value"});
...
span.end();
})
然后 OTLP 中的 exemplar 输出将包括
- 值为 1。
- 调用
add方法的时间。 {"Z": "z-value"}的Attributes,因为这些属性未在结果度量点中保留。makeRequestspan 的 trace/span id。
而计数器的度量数据点将包含属性 X 和 Y。
Metric SDK 必须提供一种机制,通过 ExemplarFilter 和 ExemplarReservoir 钩子从测量值中采样 Exemplar。
Exemplar 采样默认应开启。如果 Exemplar 采样关闭,SDK 不应有与 exemplar 采样相关的开销。
Metric SDK 必须允许 exemplar 采样利用度量聚合的配置。例如,直方图的 Exemplar 采样应该能够利用分桶边界。
Metric SDK 应提供 Exemplar 采样配置,特别是
ExemplarFilter:过滤哪些测量值可以成为 exemplar。ExemplarReservoir:exemplar 的存储和采样。
ExemplarFilter
ExemplarFilter 配置必须允许用户在内置 ExemplarFilters 之间进行选择。虽然 ExemplarFilter 决定哪些测量值有资格成为 Exemplar,但 ExemplarReservoir 最终决定测量值是否成为 exemplar 并被存储。
ExemplarFilter 应是 SDK 的 MeterProvider 的配置参数。默认值应为 TraceBased。过滤器配置应遵循 环境变量规范。
OpenTelemetry SDK 必须支持以下过滤器
AlwaysOn
一个 ExemplarFilter,使所有测量值都有资格成为 Exemplar。
AlwaysOff
一个 ExemplarFilter,使任何测量值都不具备成为 Exemplar 的资格。使用此 ExemplarFilter 与禁用 Exemplar 功能一样好。
TraceBased
一个 ExemplarFilter,使在采样父 Span 的上下文中记录的测量值有资格成为 Exemplar。
ExemplarReservoir
ExemplarReservoir 接口必须提供一个方法来向 reservoir 提供测量值,另一个方法用于收集累积的 Exemplars。
对于每个已知的时序列数据点(由聚合和视图配置确定),都必须创建一个新的 ExemplarReservoir。此数据点及其定义属性集被称为关联的时序列点。
“offer” 方法应接受测量值,包括
“offer” 方法应能够提取关联的 trace 和 span 信息,而无需记录完整的 context。换句话说,当前 span context 和 baggage 可以在此时进行检查。
“offer” 方法不需要存储所有给它的测量值,并且可以进行比 ExemplarFilter 更进一步的采样。
“offer” 方法可以接受与 reservoir 关联的时序列不同的属性的过滤子集。这必须在 API 中明确记录,并且 reservoir 必须在构造时提供与其时序列点关联的 Attributes,以便 reservoir 执行的其他采样可以在“offer”方法中访问测量值的所有属性。鼓励 SDK 作者对该选项是否适合其实现进行基准测试。
“collect” 方法必须返回累积的 Exemplar。Exemplars 应遵守其记录的任何度量点所拥有的 AggregationTemporality。换句话说,报告给度量数据点的 Exemplars 应发生在点开始/停止时间戳之内。SDK 可以自由决定“collect”是否也应重置增量时态收集的内部存储,或者使用更优化的实现。
Exemplars 必须保留在测量值中可用的任何属性,而这些属性未被聚合或视图配置保留在关联的时序列中。将 Exemplar 上的属性与它们关联的度量数据点上的属性结合起来,应该能够得到原始采样测量值的完整属性集。
ExemplarReservoir 在采样 exemplars 时应避免分配。
Exemplar defaults
SDK 必须包含两种类型的内置 exemplar reservoir
SimpleFixedSizeExemplarReservoirAlignedHistogramBucketExemplarReservoir
By default
- 具有多个分桶的显式分桶直方图聚合应使用
AlignedHistogramBucketExemplarReservoir。 - 基于 2 的指数直方图聚合应使用
SimpleFixedSizeExemplarReservoir,其 reservoir 大小等于聚合配置的最大分桶数或二十(例如,min(20, max_buckets))中的较小者。 - 所有其他聚合都应使用
SimpleFixedSizeExemplarReservoir。
Exemplar 默认 reservoir 在 次版本更新 中可能会改变。不对返回的 exemplars 的形状或统计属性做出任何保证。
SimpleFixedSizeExemplarReservoir
此 reservoir 必须使用基于 reservoir 已看到样本数量的均匀加权采样算法来确定是否应采样提供的测量值。例如,可以使用 简单 reservoir 采样算法。
if num_measurements_seen < num_buckets then
bucket = num_measurements_seen
else
bucket = random_integer(0, num_measurements_seen)
end
if bucket < num_buckets then
reservoir[bucket] = measurement
end
num_measurements_seen += 1
采样计算的任何有状态部分都应在每个收集周期重置。以上述算法为例,这意味着每次收集 reservoir 时,num_measurements_seen 计数都会重置。
此 Exemplar reservoir 可以接受一个用于 reservoir 大小的配置参数。如果未提供大小配置,默认大小可以是并发线程数(例如,CPU 数量)以帮助减少争用。否则,应使用默认大小 1。
AlignedHistogramBucketExemplarReservoir
此 Exemplar reservoir 必须接受一个配置参数,该参数是直方图的配置。此实现最多必须存储落入直方图分桶的一个测量值,并且应使用基于分桶已看到测量数量的均匀加权采样算法来确定是否应采样提供的测量值。或者,实现也可以保留最后一个落入直方图分桶的测量值。
该 reservoir 将使用以下朴素算法的等效实现来接受测量值
bucket = find_histogram_bucket(measurement)
num_measurements_seen_bucket = num_measurements_seen[bucket]
if random_integer(0, num_measurements_seen_bucket) == 0 then
reservoir[bucket] = measurement
end
num_measurements_seen[bucket] += 1
def find_histogram_bucket(measurement):
for boundary, idx in bucket_boundaries do
if value <= boundary then
return idx
end
end
return boundaries.length
此 Exemplar reservoir 可以接受一个配置参数,用于 reservoir 使用的分桶边界。reservoir 的大小始终是分桶边界的数量加一。此配置参数应具有与指定分桶边界到 显式分桶直方图聚合 相同的格式。
Custom ExemplarReservoir
SDK 必须提供一种机制,供 SDK 用户提供自己的 ExemplarReservoir 实现。此扩展必须在度量 View 上可配置,尽管单个 reservoir 仍然必须为每个度量-时序列实例化(参见 Exemplar Reservoir - 第二段)。
MetricReader
状态: 稳定
MetricReader 是一个 SDK 实现对象,它提供 OpenTelemetry Metrics SDK 的常见可配置方面,并确定以下能力
- 根据需要从 SDK 和任何已注册的 MetricProducers 收集指标。
- 处理来自 SDK 的 ForceFlush 和 Shutdown 信号。
在设置 SDK 时构造 MetricReader,至少应提供以下内容
- 要使用的
exporter,即MetricExporter实例。 - 默认输出
aggregation(可选),它是 instrument 种类的函数。此函数应从exporter获取。如果未配置,则应使用 默认聚合。 - 输出
temporality(可选),它是 instrument 种类的函数。此函数应从exporter获取。如果未配置,则应使用 Cumulative temporality。 - 默认聚合 基数限制(可选)使用,它是 instrument 种类的函数。如果未配置,则应使用默认值 2000。
- 状态:开发中 - 在
MetricReader#Collect过程中应用于指标和属性的 MetricFilter。 - 零个或多个 MetricProducer(可选),除了 SDK 中的指标外,还可以从中收集指标。
状态:开发中 - 当调用 Produce 操作时,MetricReader 应向 SDK 或已注册的 MetricProducer(s) 提供 MetricFilter。
MetricReader.Collect 方法允许通用 MetricExporter 实例显式启动收集,通常与拉取式指标收集一起使用。MetricReader 的一个常见实现,周期导出 MetricReader,应提供给通常与推送式指标收集一起使用。
MetricReader 必须确保 OpenTelemetry instruments 的数据点以每个 instrument 种类的配置的聚合时态输出。对于具有累积聚合时态的同步 instrument,这意味着将 Delta 转换为 Cumulative 聚合时态。对于具有增量时态的异步 instrument,这意味着将 Cumulative 转换为 Delta 聚合时态。
MetricReader 不必确保来自非 SDK MetricProducer 的数据点以配置的聚合时态输出,因为这些数据点不是使用 OpenTelemetry instruments 收集的。
MetricReader 为 instrument 种类选择 temporality 会影响度量数据点在收集之间的持久性。对于具有累积聚合时态的同步 instrument,MetricReader.Collect 必须接收到先前收集暴露的数据点,无论是否记录了新的测量值。对于具有增量聚合时态的同步 instrument,MetricReader.Collect 只能接收自上次收集以来记录了测量值的数据点。对于具有增量或累积聚合时态的异步 instrument,MetricReader.Collect 只能接收自上次收集以来记录了测量值的数据点。这些规则适用于所有指标,而不仅仅是那些 点种类 包含聚合时态字段的指标。
MetricReader 选择 temporality 作为 instrument 类型的一种函数,会影响 MetricReader.Collect 接收到的 metrics 数据点的起始时间戳(即 StartTimeUnixNano)。对于具有 Cumulative 聚合临时性的 instruments, successive data points received by successive calls to MetricReader.Collect MUST repeat the same starting timestamps (e.g. (T0, T1], (T0, T2], (T0, T3])。对于具有 Delta 聚合临时性的 instruments, successive data points received by successive calls to MetricReader.Collect MUST advance the starting timestamp ( e.g. (T0, T1], (T1, T2], (T2, T3])。结束时间戳(即 TimeUnixNano)MUST always be equal to time the metric data point took effect, which is equal to when MetricReader.Collect was invoked. These rules apply to all metrics, not just those whose point kinds includes an aggregation temporality field. See data model temporality for more details。
SDK MUST support multiple MetricReader instances to be registered on the same MeterProvider, and the MetricReader.Collect invocation on one MetricReader instance SHOULD NOT introduce side-effects to other MetricReader instances。For example, if a MetricReader instance is receiving metric data points that have delta temporality, it is expected that SDK will update the time range - e.g. from (Tn, Tn+1] to (Tn+1, Tn+2] - ONLY for this particular MetricReader instance。
SDK MUST NOT allow a MetricReader instance to be registered on more than one MeterProvider instance。
+-----------------+ +--------------+
| | Metrics... | |
| In-memory state +------------> MetricReader |
| | | |
+-----------------+ +--------------+
+-----------------+ +--------------+
| | Metrics... | |
| In-memory state +------------> MetricReader |
| | | |
+-----------------+ +--------------+
SDK SHOULD provide a way to allow MetricReader to respond to MeterProvider.ForceFlush and MeterProvider.Shutdown。OpenTelemetry SDK authors MAY decide the language idiomatic approach, for example, as OnForceFlush and OnShutdown callback functions。
MetricReader operations
Collect
Collects the metrics from the SDK and any registered MetricProducers。If there are asynchronous SDK Instruments involved, their callback functions will be triggered。
Collect SHOULD provide a way to let the caller know whether it succeeded, failed or timed out。When the Collect operation fails or times out on some of the instruments, the SDK MAY return successfully collected results and a failed reasons list to the caller。
Collect does not have any required parameters, however, OpenTelemetry SDK authors MAY choose to add parameters (e.g. callback, filter, timeout)。OpenTelemetry SDK authors MAY choose the return value type, or do not return anything。
Collect SHOULD invoke Produce on registered MetricProducers。If the batch of metric points from Produce includes Resource information, Collect MAY replace the Resource from the MetricProducer with the Resource provided when constructing the MeterProvider instead。
Note: it is expected that the MetricReader.Collect implementations will be provided by the SDK, so it is RECOMMENDED to prevent the user from accidentally overriding it, if possible (e.g. final in C++ and Java, sealed in C#)。
Shutdown
This method provides a way for the MetricReader to do any cleanup required。
Shutdown MUST be called only once for each MetricReader instance。After the call to Shutdown, subsequent invocations to Collect are not allowed。SDKs SHOULD return some failure for these calls, if possible。
Shutdown 应提供一种方式,让调用者知道它是否成功、失败或超时。
Shutdown **应该**在某个超时时间内完成或中止。Shutdown **可以**实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者**可以**决定是否使 shutdown 超时可配置。
Periodic exporting MetricReader
This is an implementation of the MetricReader which collects metrics based on a user-configurable time interval, and passes the metrics to the configured Push Metric Exporter。
Configurable parameters
exportIntervalMillis- the time interval in milliseconds between two consecutive exports。The default value is 60000 (milliseconds)。exportTimeoutMillis- how long the export can run before it is cancelled。The default value is 30000 (milliseconds)。
The reader MUST synchronize calls to MetricExporter’s Export to make sure that they are not invoked concurrently。
One possible implementation of periodic exporting MetricReader is to inherit from MetricReader and start a background task which calls the inherited Collect() method at the requested exportIntervalMillis。The reader’s Collect() method may still be invoked by other callers。For example,
- A user configures periodic exporting MetricReader with a push exporter and a 30 second interval。
- At the first 30 second interval, the background task calls
Collect()which passes metrics to the push exporter。 - After 15 seconds, the user decides to flush metrics for just this reader。They call
Collect()which passes metrics to the push exporter。 - After another 15 seconds (at the end of the second 30 second interval), the background task calls
Collect()which passes metrics to the push exporter。
ForceFlush
This method provides a way for the periodic exporting MetricReader so it can do as much as it could to collect and send the metrics。
ForceFlush SHOULD collect metrics, call Export(batch) and ForceFlush() on the configured Push Metric Exporter。
ForceFlush **应该**提供一种方式,让调用者知道它是否成功、失败或超时。如果存在错误条件,ForceFlush **应该**返回某种 **ERROR** 状态;如果没有错误条件,它**应该**返回某种 **NO ERROR** 状态。语言实现**可以**决定如何模拟 **ERROR** 和 **NO ERROR**。
ForceFlush SHOULD complete or abort within some timeout。ForceFlush MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event。
MetricExporter
状态: 稳定
MetricExporter defines the interface that protocol-specific exporters MUST implement so that they can be plugged into OpenTelemetry SDK and support sending of telemetry data。
Metric Exporters always have an associated MetricReader。The aggregation and temporality properties used by the OpenTelemetry Metric SDK are determined when registering Metric Exporters through their associated MetricReader。OpenTelemetry language implementations MAY support automatically configuring the MetricReader to use for an Exporter。
The goal of the interface is to minimize the burden of implementation for protocol-dependent telemetry exporters。The protocol exporter is expected to be primarily a simple telemetry data encoder and transmitter。
Metric Exporter has access to the aggregated metrics data。Metric Exporters SHOULD report an error condition for data output by the MetricReader with unsupported Aggregation or Aggregation Temporality, as this condition can be corrected by a change of MetricReader configuration。
There could be multiple Push Metric Exporters or Pull Metric Exporters or even a mixture of both configured at the same time on a given MeterProvider using one MetricReader for each exporter。Different exporters can run at different schedule, for example
- Exporter A is a push exporter which sends data every 1 minute。
- Exporter B is a push exporter which sends data every 5 seconds。
- Exporter C is a pull exporter which reacts to a scraper over HTTP。
- Exporter D is a pull exporter which reacts to another scraper over a named pipe。
Push Metric Exporter
Push Metric Exporter sends metric data it receives from a paired MetricReader。Here are some examples
- Sends the data based on a user configured schedule, e.g. every 1 minute。This MAY be accomplished by pairing the exporter with a periodic exporting MetricReader。
- Sends the data when there is a severe error。
The following diagram shows Push Metric Exporter’s relationship to other components in the SDK
+-----------------+ +---------------------------------+
| | Metrics... | |
| In-memory state +------------> Periodic exporting MetricReader |
| | | |
+-----------------+ | +-----------------------+ |
| | | |
| | MetricExporter (push) +-------> Another process
| | | |
| +-----------------------+ |
| |
+---------------------------------+
Interface Definition
A Push Metric Exporter MUST support the following functions
Export(batch)
Exports a batch of Metric Points。Protocol exporters that will implement this function are typically expected to serialize and transmit the data to the destination。
The SDK MUST provide a way for the exporter to get the Meter information (e.g. name, version, etc.) associated with each Metric Point。
Export should never be called concurrently with other Export calls for the same exporter instance。
Export MUST NOT block indefinitely, there MUST be a reasonable upper limit after which the call must time out with an error result (Failure)。
Any retry logic that is required by the exporter is the responsibility of the exporter。The default SDK SHOULD NOT implement retry logic, as the required logic is likely to depend heavily on the specific protocol and backend the metrics are being sent to。
参数
batch - a batch of Metric Points。The exact data type of the batch is language specific, typically it is some kind of list。The exact type of Metric Point is language specific, and is typically optimized for high performance。Here are some examples
+--------+ +--------+ +--------+
Batch: | Metric | | Metric | ... | Metric |
+---+----+ +--------+ +--------+
|
+--> name, unit, description, meter information, ...
|
| +-------------+ +-------------+ +-------------+
+--> MetricPoints: | MetricPoint | | MetricPoint | ... | MetricPoint |
+-----+-------+ +-------------+ +-------------+
|
+--> timestamps, attributes, value (or buckets), exemplars, ...
Refer to the Metric Points section from the Metrics Data Model specification for more details。
Note: it is highly recommended that implementors design the Metric data type based on the Data Model, rather than directly use the data types generated from the proto files (because the types generated from proto files are not guaranteed to be backward compatible)。
Returns: ExportResult
ExportResult is one of
Success- 批次已成功导出。对于协议导出器,这通常意味着数据已通过线路发送并传递到目标服务器。Failure- 导出失败。批次必须被丢弃。例如,当批次包含错误数据且无法序列化时,可能会发生这种情况。
Note: this result may be returned via an async mechanism or a callback, if that is idiomatic for the language implementation。
ForceFlush
This is a hint to ensure that the export of any Metrics the exporter has received prior to the call to ForceFlush SHOULD be completed as soon as possible, preferably before returning from this method。
ForceFlush 应提供一种方式,让调用者知道它是否成功、失败或超时。
ForceFlush SHOULD only be called in cases where it is absolutely necessary, such as when using some FaaS providers that may suspend the process after an invocation, but before the exporter exports the completed metrics。
ForceFlush SHOULD complete or abort within some timeout。ForceFlush can be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event。OpenTelemetry SDK authors MAY decide if they want to make the flush timeout configurable。
Shutdown
Shuts down the exporter。Called when SDK is shut down。This is an opportunity for exporter to do any cleanup required。
Shutdown SHOULD be called only once for each MetricExporter instance。After the call to Shutdown subsequent calls to Export are not allowed and should return a Failure result。
Shutdown SHOULD NOT block indefinitely (e.g. if it attempts to flush the data and the destination is unavailable)。OpenTelemetry SDK authors MAY decide if they want to make the shutdown timeout configurable。
Pull Metric Exporter
Pull Metric Exporter reacts to the metrics scrapers and reports the data passively。This pattern has been widely adopted by Prometheus。
Unlike Push Metric Exporter which can send data on its own schedule, pull exporter can only send the data when it is being asked by the scraper, and ForceFlush would not make sense。
Implementors MAY choose the best idiomatic design for their language。For example, they could generalize the Push Metric Exporter interface design and use that for consistency, they could model the pull exporter as MetricReader, or they could design a completely different pull exporter interface。If the pull exporter is modeled as MetricReader, implementors MAY name the MetricExporter interface as PushMetricExporter to prevent naming confusion。
The following diagram gives some examples on how Pull Metric Exporter can be modeled to interact with other components in the SDK
Model the pull exporter as MetricReader
+-----------------+ +-----------------------------+ | | Metrics... | | | In-memory state +------------> PrometheusExporter (pull) +---> Another process (scraper) | | | (modeled as a MetricReader) | +-----------------+ | | +-----------------------------+Use the same MetricExporter design for both push and pull exporters
+-----------------+ +-----------------------------+ | | Metrics... | | | In-memory state +------------> Exporting MetricReader | | | | | +-----------------+ | +-----------------------+ | | | | | | | MetricExporter (pull) +------> Another process (scraper) | | | | | +-----------------------+ | | | +-----------------------------+
MetricProducer
状态:稳定,除非另有说明
MetricProducer defines the interface which bridges to third-party metric sources MUST implement, so they can be plugged into an OpenTelemetry MetricReader as a source of aggregated metric data。The SDK’s in-memory state MAY implement the MetricProducer interface for convenience。
MetricProducer implementations SHOULD accept configuration for the AggregationTemporality of produced metrics。SDK authors MAY provide utility libraries to facilitate conversion between delta and cumulative temporalities。
+-----------------+ +--------------+
| | Metrics... | |
| In-memory state +------------> MetricReader |
| | | |
+-----------------+ | |
| |
+-----------------+ | |
| | Metrics... | |
| MetricProducer +------------> |
| | | |
+-----------------+ +--------------+
When new OpenTelemetry integrations are added, the API is the preferred integration point。The MetricProducer is only meant for integrations that bridge pre-processed data。
Interface Definition
A MetricProducer MUST support the following functions
Produce batch
Produce provides metrics from the MetricProducer to the caller。Produce MUST return a batch of Metric Points, filtered by the optional metricFilter parameter。Implementation SHOULD use the filter as early as possible to gain as much performance gain possible (memory allocation, internal metric fetching, etc)。
If the batch of Metric Points includes resource information, Produce SHOULD require a resource as a parameter。Produce does not have any other required parameters, however, OpenTelemetry SDK authors MAY choose to add required or optional parameters (e.g. timeout)。
Produce SHOULD provide a way to let the caller know whether it succeeded, failed or timed out。When the Produce operation fails, the MetricProducer MAY return successfully collected results and a failed reasons list to the caller。
If a batch of Metric Points can include InstrumentationScope information, Produce SHOULD include a single InstrumentationScope which identifies the MetricProducer。
参数
Status: Development metricFilter: An optional MetricFilter。
MetricFilter
状态: 开发中
MetricFilter defines the interface which enables the MetricReader’s registered MetricProducers or the SDK’s MetricProducer to filter aggregated data points (Metric Points) inside its Produce operation。The filtering is done at the MetricProducer for performance reasons。
The MetricFilter allows filtering an entire metric stream - dropping or allowing all its attribute sets - by its TestMetric operation, which accepts the metric stream information (scope, name, kind and unit) and returns an enumeration: Accept, Drop or Accept_Partial。If the latter returned, the TestAttributes operation is to be called per attribute set of that metric stream, returning an enumeration determining if the data point for that (metric stream, attributes) pair is to be allowed in the result of the MetricProducer Produce operation。
Interface Definition
A MetricFilter MUST support the following functions
TestMetric
This operation is called once for every metric stream, in each MetricProducer Produce operation。
参数
instrumentationScope: the metric stream instrumentation scopename: the name of the metric streamkind: the metric stream kindunit: the metric stream unit
Returns: MetricFilterResult
MetricFilterResult is one of
Accept- All attributes of the given metric stream are allowed (not to be filtered)。This provides a “short-circuit” as there is no need to callTestAttributesoperation for each attribute set。Drop- All attributes of the given metric stream are NOT allowed (filtered out - dropped)。This provides a “short-circuit” as there is no need to callTestAttributesoperation for each attribute set, and no need to collect those data points be it synchronous or asynchronous: e.g. the callback for this given instrument does not need to be invoked。Accept_Partial- Some attributes are allowed and some aren’t, henceTestAttributesoperation must be called for each attribute set of that instrument。
TestAttributes
An operation which determines for a given metric stream and attribute set if it should be allowed or filtered out。
This operation should only be called if TestMetric operation returned Accept_Partial for the given metric stream arguments (instrumentationScope, name, kind, unit)。
参数
instrumentationScope: the metric stream instrumentation scopename: the name of the metric streamkind: the metric stream kindunit: the metric stream unitattributes: the attributes
Returns: AttributesFilterResult
AttributesFilterResult is one of
Accept- This givenattributesare allowed (not to be filtered)。Drop- This givenattributesare NOT allowed (filtered out - dropped)。
Defaults and configuration
The SDK MUST provide configuration according to the SDK environment variables specification。
Numerical limits handling
The SDK MUST handle numerical limits in a graceful way according to Error handling in OpenTelemetry。
If the SDK receives float/double values from Instruments, it MUST handle all the possible values。For example, if the language runtime supports IEEE 754, the SDK needs to handle NaNs and Infinites。
It is unspecified how the SDK should handle the input limits。The SDK authors MAY leverage/follow the language runtime behavior for better performance, rather than perform a check on each value coming from the API。
It is unspecified how the SDK should handle the output limits (e.g. integer overflow)。The SDK authors MAY rely on the language runtime behavior as long as errors/exceptions are taken care of。
Compatibility requirements
状态: 稳定
All the metrics components SHOULD allow new methods to be added to existing components without introducing breaking changes。
All the metrics SDK methods SHOULD allow optional parameter(s) to be added to existing methods without introducing breaking changes, if possible。
并发要求
状态: 稳定
For languages which support concurrent execution the Metrics SDKs provide specific guarantees and safeties。
MeterProvider - Meter creation, ForceFlush and Shutdown are safe to be called concurrently。
ExemplarReservoir - all methods are safe to be called concurrently。
MetricReader - Collect, ForceFlush (for periodic exporting MetricReader) and Shutdown are safe to be called concurrently。
MetricExporter - ForceFlush and Shutdown are safe to be called concurrently。
参考
- OTEP0113 Integrate Exemplars with Metrics
- OTEP0126 A Proposal For SDK Support for Configurable Batching and Aggregations (Basic Views)
- OTEP0146 Scenarios for Metrics API/SDK Prototyping