远程写入规范总体上旨在记录 Prometheus 和 Prometheus 远程写入兼容发送端如何将数据发送到 Prometheus 或 Prometheus 远程写入兼容接收端的标准。
本文档旨在定义 Prometheus 远程写入 API 的第二个版本,对协议和语义进行了少量修改。第二个版本添加了一个新的 Protobuf 消息,其中包含新功能,在性能和成本节省的基础上,支持更多用例和更广泛的应用。第二个版本还弃用了1.0 远程写入规范中的先前 Protobuf 消息,并添加了强制性的X-Prometheus-Remote-Write-*-Written
HTTP 响应头,以提高可靠性。最后,此规范概述了如何使用现有基本内容协商请求头来实现向后兼容的发送端和接收端(甚至在单个端点下)。如果需要,未来的小版本中可能会出现更高级的自动化内容协商机制。有关 2.0 规范背后的原理,请参阅正式提案。
本文档中的关键词“必须 (MUST)”、“不得 (MUST NOT)”、“必需 (REQUIRED)”、“应 (SHALL)”、“不应 (SHALL NOT)”、“应该 (SHOULD)”、“不应该 (SHOULD NOT)”、“推荐 (RECOMMENDED)”、“可以 (MAY)”和“可选 (OPTIONAL)”应按照RFC 2119 中的描述进行解释。
注意:这是远程写入 2.0 规范的发布候选版本。这意味着此规范目前处于实验状态——预计不会有重大更改,但我们保留根据早期采用者的反馈在必要时破坏兼容性的权利。潜在的反馈、问题和建议应作为评论添加到包含公开提案的 PR 中。
远程写入协议旨在实现从发送端到接收端实时可靠地传播样本,且不会丢失。
远程写入协议设计为无状态的;严格来说没有消息间的通信。因此,该协议不被认为是“流式”的。要实现流式效果,应通过同一连接发送多个消息,例如使用 HTTP/1.1 或 HTTP/2。“花哨”的技术如 gRPC 曾被考虑,但当时并未广泛采用,并且在 AWS EC2 ELB 等负载均衡器后面向互联网暴露 gRPC 服务具有挑战性。
远程写入协议提供了批量处理的机会,例如在单个请求中发送不同时间序列的多个样本。不期望同一时间序列的多个样本会在同一请求中常见地发送,尽管 Protobuf 消息中对此有支持。
测试套件可以在https://github.com/prometheus/compliance/tree/main/remote_write_sender 找到。远程写入 2.0 兼容性的合规性测试仍在进行中。
本文档遵循以下定义
Remote-Write
是这个 Prometheus 协议的名称。协议 (Protocol)
是一种通信规范,使客户端和服务器能够传输指标。Protobuf 消息
(或 Proto 消息)是指此协议数据结构的内容类型定义。由于此规范完全使用 Google Protocol Buffers (“protobuf”),因此模式在“proto”文件中定义,并由单个 Protobuf “消息”表示。线路格式 (Wire Format)
是数据在网络中传输时的格式。对于远程写入,它始终是压缩的二进制 protobuf 格式。发送端 (Sender)
是发送远程写入数据的实体。接收端 (Receiver)
是接收(写入)远程写入数据的实体。已写入 (Written)
的含义取决于接收端,例如通常表示将接收到的数据存储到数据库中,但也可能只是验证、分割或增强它。已写入 (Written)
指的是 接收端
已接收并接受的数据。接收端是否已将此数据摄取到持久存储、写入 WAL 等,取决于 接收端
。唯一的区别在于 接收端
已经接受了这些数据,而不是明确地以错误响应拒绝它们。样本 (Sample)
是一对 (时间戳, 值)。直方图 (Histogram)
是一对 (时间戳, 直方图值)。标签 (Label)
是一对 (键, 值)。时间序列 (Series)
是样本的列表,由一组唯一的标签标识。远程写入协议必须 (MUST) 由使用 Google Protocol Buffers 序列化然后压缩的请求体组成 RPC。
protobuf 序列化必须 (MUST) 使用以下 Protobuf 消息之一
prometheus.WriteRequest
。截至 2.0 版本,此消息已被弃用。它应该 (SHOULD) 仅出于兼容性原因使用。发送端和接收端可以 (MAY) 不支持 prometheus.WriteRequest
。io.prometheus.write.v2.Request
。发送端和接收端应该 (SHOULD) 在可能的情况下使用此消息。发送端和接收端必须 (MUST) 支持 io.prometheus.write.v2.Request
。Protobuf 消息必须 (MUST) 使用二进制线路格式。然后,必须 (MUST) 使用Google 的 Snappy 进行压缩。Snappy 的块格式必须 (MUST) 使用——帧格式不得 (MUST NOT) 使用。
发送端必须 (MUST) 在 HTTP POST 请求的请求体中发送序列化和压缩的 Protobuf 消息,并通过 HTTP 将其发送到提供的 URL 路径上的接收端。接收端可以 (MAY) 指定任何 HTTP URL 路径来接收指标。
发送端必须 (MUST) 在 HTTP 请求中发送以下保留的头
Content-Encoding
Content-Type
X-Prometheus-Remote-Write-Version
User-Agent
发送端可以 (MAY) 允许用户添加自定义 HTTP 头;它们不得 (MUST NOT) 允许用户以发送保留头的方式配置它们。
Content-Encoding: <compression>
内容编码请求头必须 (MUST) 遵循RFC 9110。发送端必须 (MUST) 使用 snappy
值。接收端必须 (MUST) 支持 snappy
压缩。新的可选压缩算法可能会在 2.x 或更高版本中出现。
Content-Type: application/x-protobuf
Content-Type: application/x-protobuf;proto=<fully qualified name>
内容类型请求头必须 (MUST) 遵循RFC 9110。发送端必须 (MUST) 使用 application/x-protobuf
作为唯一的媒体类型。发送端可以 (MAY) 向头的 value 添加 ;proto=
参数,以指示使用的 Protobuf 消息的完全限定名称,即上面提到的两种。因此,发送端必须 (MUST) 发送以下三种支持的头 value 中的任何一个
对于 PRW 1.0 中引入的已弃用消息,由 prometheus.WriteRequest
标识
Content-Type: application/x-protobuf
Content-Type: application/x-protobuf;proto=prometheus.WriteRequest
对于 PRW 2.0 中引入的消息,由 io.prometheus.write.v2.Request
标识
Content-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request
与 1.x 接收端通信时,发送端应该 (SHOULD) 使用 Content-Type: application/x-protobuf
以实现向后兼容性。否则,发送端应该 (SHOULD) 使用 Content-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request
。更多的 Protobuf 消息可能会在 2.x 或更高版本中出现。
接收端必须 (MUST) 使用内容类型头来确定要使用的 Protobuf 消息模式。意外的错误模式选择可能导致非确定性行为(例如数据损坏)。
注意:由于io.prometheus.write.v2.Request
中的保留字段,接收端意外地将prometheus.WriteRequest
与错误模式一起使用将导致空消息。这通常是为了方便避免意外错误,但不要依赖它——未来的 Protobuf 消息可能没有此功能。
X-Prometheus-Remote-Write-Version: <Remote-Write spec major and minor version>
与 1.x 接收端通信时,发送端必须 (MUST) 使用 X-Prometheus-Remote-Write-Version: 0.1.0
以实现向后兼容性。否则,发送端应该 (SHOULD) 使用与之兼容的最新远程写入版本,例如 X-Prometheus-Remote-Write-Version: 2.0.0
。
User-Agent: <name & version of the Sender>
发送端必须 (MUST) 包含一个用户代理头,该头应该 (SHOULD) 遵循RFC 9110 User-Agent 头格式。
成功写入所有数据的接收端必须 (MUST) 返回一个成功 2xx HTTP 状态码。在这种成功情况下,来自接收端的响应体应该 (SHOULD) 为空,并且状态码应该 (SHOULD) 是204 HTTP 无内容;发送端必须 (MUST) 忽略响应体。响应体保留用于未来使用。
如果接收端知道的任何发送数据块(例如样本、直方图、Exemplars)未成功写入(部分写入或完全写入拒绝),接收端不得 (MUST NOT) 返回 2xx HTTP 状态码。在这种情况下,接收端必须 (MUST) 在响应体中提供人类可读的错误消息。接收端的错误应该 (SHOULD) 包含有关被拒绝样本数量和原因的信息。发送端不得 (MUST NOT) 尝试解释错误消息,并且应该 (SHOULD) 原样记录它。
以下小节详细说明了发送端和接收端围绕头以及不同写入错误情况的语义。
已写入
响应头成功进行内容协商后,接收端处理(写入)接收到的批量数据。对于每个重要的数据块(当前包括样本、直方图和 Exemplars),一旦完成(无论成功或失败),接收端必须 (MUST) 发送一个专用的 HTTP X-Prometheus-Remote-Write-*-Written
响应头,其中包含成功写入元素的精确数量。
每个头的值必须 (MUST) 是一个 64 位整数。头的名称必须 (MUST) 如下
X-Prometheus-Remote-Write-Samples-Written <count of all successfully written Samples>
X-Prometheus-Remote-Write-Histograms-Written <count of all successfully written Histogram samples>
X-Prometheus-Remote-Write-Exemplars-Written <count of all successfully written Exemplars>
收到 2xx 或 4xx 状态码后,发送端可以 (CAN) 假定任何缺失的 X-Prometheus-Remote-Write-*-Written
响应头意味着接收端没有写入此类别(例如样本)的任何元素(计数为 0
)。使用已弃用的 prometheus.WriteRequest
Protobuf 消息时,发送端不得 (MUST NOT) 做出同样的假设,因为存在遇到没有此功能的 1.0 接收端的风险。
发送端可以 (MAY) 使用这些头来确认接收端成功写入了哪些部分数据。常见用例包括
io.prometheus.write.v2.Request
请求发送数据并收到 2xx HTTP 状态码,但没有收到来自接收端的任何 X-Prometheus-Remote-Write-*-Written
响应头时,发送端应该 (SHOULD) 假定状态码为415 HTTP Unsupported Media Type。这是 1.0 接收端的一个常见问题,它们不检查 Content-Type
请求头;意外地使用 prometheus.WriteRequest
模式解码 io.prometheus.write.v2.Request
有效载荷会导致空结果且没有解码错误。发送端不得 (MUST NOT) 从远程写入响应头中假定接收端实现了哪个远程写入规范版本。
未来可能会添加更多(可选)头,例如添加更多实体或字段且值得确认时。
发送端应该 (SHOULD) 使用远程写入在单个请求中发送多个时间序列的样本。因此,接收端可以 (MAY) 在包含一些无效或未写入样本的写入请求中写入有效样本,这构成了部分写入的情况。在这种情况下,接收端必须 (MUST) 根据无效样本和部分写入重试部分返回非 2xx 状态码。
如果接收端不支持发送端提供的给定内容类型或编码,则必须 (MUST) 返回415 HTTP Unsupported Media Type 状态码。
为了向后兼容性,发送端应该 (SHOULD) 预期来自 1.x 接收端的400 HTTP Bad Request 状态码,原因如上所述。
接收端可以 (MAY) 不支持某些指标类型或样本(例如,一个接收端可能拒绝未指定元数据类型或未创建时间戳的样本,而另一个接收端可能接受此类样本)。哪个样本无效取决于接收端。除非发生可重试的部分写入,否则接收端必须 (MUST) 对包含任何无效样本的写入请求返回400 HTTP Bad Request 状态码。
发送端不得 (MUST NOT) 对 4xx HTTP 状态码(429 除外)进行重试,接收端必须 (MUST) 使用 4xx(429 除外)状态码表示写入操作永远无法成功,不应重试。发送端可以 (MAY) 对 415 HTTP 状态码使用不同的内容类型或编码进行重试,以查看接收端是否支持。
接收端可以 (MAY) 返回429 HTTP Too Many Requests 状态码以指示服务器过载情况。接收端可以 (MAY) 返回Retry-After 头以指示下一次写入尝试的时间。接收端可以 (MAY) 返回 5xx HTTP 状态码表示内部服务器错误。
发送端可以 (MAY) 对 429 HTTP 状态码进行重试。发送端必须 (MUST) 对 5xx HTTP 状态码的写入请求进行重试。发送端必须 (MUST) 使用指数退避算法以防止压垮服务器。发送端可以 (MAY) 处理Retry-After 响应头以估计下一次重试时间。
429 和 5xx 处理之间的区别在于,当接收端无法跟上请求量时,发送端可能“落后”,或者接收端选择限制发送端速率以保护其可用性。因此,发送端可以选择不对 429 进行重试,这允许在发生发送端错误(例如流量过大)时取得进展,同时在发生接收端错误(5xx)时数据不会丢失。
当期望发送端重试整个请求时,接收端可以 (MAY) 在部分写入或部分无效样本情况下返回 5xx HTTP 或 429 HTTP 状态码。在这种情况下,接收端必须 (MUST) 支持幂等性,因为发送端可以 (MAY) 使用相同的请求重试。
该协议遵循语义化版本控制 2.0:任何 2.x 兼容的接收端必须 (MUST) 能够读取任何 2.x 兼容的发送端,反之亦然。破坏性或向后不兼容的更改将导致规范的 3.x 版本。
Protobuf 消息(在线路格式中)本身在某些方面是向前/向后兼容的
换句话说,这意味着未来的 2.x 次要版本可以 (MAY) 向 io.prometheus.write.v2.Request
添加新的可选字段、新的压缩算法、Protobuf 消息和协商机制,只要它们是向后兼容的(例如,对接收端和发送端都是可选的)。
2.x 协议通过引入新的、强制性的 io.prometheus.write.v2.Request
Protobuf 消息并弃用 prometheus.WriteRequest
,破坏了与 1.x 的兼容性。
2.x 发送端可以 (MAY) 通过允许用户配置发送端应使用何种内容类型来支持 1.x 接收端。如果接收端返回 415 HTTP 状态码,2.x 发送端也可以 (MAY) 自动回退到不同的内容类型。
io.prometheus.write.v2.Request
io.prometheus.write.v2.Request
指的是新的 Protobuf 消息,旨在替换和弃用远程写入 1.0 的 prometheus.WriteRequest
消息。
完整的模式和事实来源位于 Prometheus 仓库的prompb/io/prometheus/write/v2/types.proto
文件中。gogo
依赖和选项可以 (CAN) 忽略(最终将被移除)。它们不属于规范的一部分,因为它们不影响序列化格式。
新的 io.prometheus.write.v2.Request
的简化版本如下所示。
// Request represents a request to write the given timeseries to a remote destination.
message Request {
// Since Request supersedes 1.0 spec's prometheus.WriteRequest, we reserve the top-down message
// for the deterministic interop between those two.
// Generally it's not needed, because Receivers must use the Content-Type header, but we want to
// be sympathetic to adopters with mistaken implementations and have deterministic error (empty
// message if you use the wrong proto schema).
reserved 1 to 3;
// symbols contains a de-duplicated array of string elements used for various
// items in a Request message, like labels and metadata items. For the sender's convenience
// around empty values for optional fields like unit_ref, symbols array MUST start with
// empty string.
//
// To decode each of the symbolized strings, referenced, by "ref(s)" suffix, you
// need to lookup the actual string by index from symbols array. The order of
// strings is up to the sender. The receiver should not assume any particular encoding.
repeated string symbols = 4;
// timeseries represents an array of distinct series with 0 or more samples.
repeated TimeSeries timeseries = 5;
}
// TimeSeries represents a single series.
message TimeSeries {
// labels_refs is a list of label name-value pair references, encoded
// as indices to the Request.symbols array. This list's length is always
// a multiple of two, and the underlying labels should be sorted lexicographically.
//
// Note that there might be multiple TimeSeries objects in the same
// Requests with the same labels e.g. for different exemplars, metadata
// or created timestamp.
repeated uint32 labels_refs = 1;
// Timeseries messages can either specify samples or (native) histogram samples
// (histogram field), but not both. For a typical sender (real-time metric
// streaming), in healthy cases, there will be only one sample or histogram.
//
// Samples and histograms are sorted by timestamp (older first).
repeated Sample samples = 2;
repeated Histogram histograms = 3;
// exemplars represents an optional set of exemplars attached to this series' samples.
repeated Exemplar exemplars = 4;
// metadata represents the metadata associated with the given series' samples.
Metadata metadata = 5;
// created_timestamp represents an optional created timestamp associated with
// this series' samples in ms format, typically for counter or histogram type
// metrics. Created timestamp represents the time when the counter started
// counting (sometimes referred to as start timestamp), which can increase
// the accuracy of query results.
//
// Note that some receivers might require this and in return fail to
// write such samples within the Request.
//
// For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go
// for conversion from/to time.Time to Prometheus timestamp.
//
// Note that the "optional" keyword is omitted due to
// https://cloud.google.com/apis/design/design_patterns.md#optional_primitive_fields
// Zero value means value not set. If you need to use exactly zero value for
// the timestamp, use 1 millisecond before or after.
int64 created_timestamp = 6;
}
// Exemplar represents additional information attached to some series' samples.
message Exemplar {
// labels_refs is an optional list of label name-value pair references, encoded
// as indices to the Request.symbols array. This list's len is always
// a multiple of 2, and the underlying labels should be sorted lexicographically.
// If the exemplar references a trace it should use the `trace_id` label name, as a best practice.
repeated uint32 labels_refs = 1;
// value represents an exact example value. This can be useful when the exemplar
// is attached to a histogram, which only gives an estimated value through buckets.
double value = 2;
// timestamp represents the timestamp of the exemplar in ms.
// For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go
// for conversion from/to time.Time to Prometheus timestamp.
int64 timestamp = 3;
}
// Sample represents series sample.
message Sample {
// value of the sample.
double value = 1;
// timestamp represents timestamp of the sample in ms.
int64 timestamp = 2;
}
// Metadata represents the metadata associated with the given series' samples.
message Metadata {
enum MetricType {
METRIC_TYPE_UNSPECIFIED = 0;
METRIC_TYPE_COUNTER = 1;
METRIC_TYPE_GAUGE = 2;
METRIC_TYPE_HISTOGRAM = 3;
METRIC_TYPE_GAUGEHISTOGRAM = 4;
METRIC_TYPE_SUMMARY = 5;
METRIC_TYPE_INFO = 6;
METRIC_TYPE_STATESET = 7;
}
MetricType type = 1;
// help_ref is a reference to the Request.symbols array representing help
// text for the metric. Help is optional, reference should point to an empty string in
// such a case.
uint32 help_ref = 3;
// unit_ref is a reference to the Request.symbols array representing a unit
// for the metric. Unit is optional, reference should point to an empty string in
// such a case.
uint32 unit_ref = 4;
}
// A native histogram, also known as a sparse histogram.
// See https://github.com/prometheus/prometheus/blob/remote-write-2.0/prompb/io/prometheus/write/v2/types.proto#L142
// for a full message that follows the native histogram spec for both sparse
// and exponential, as well as, custom bucketing.
message Histogram { ... }
所有时间戳必须 (MUST) 是自 Unix 纪元以来的毫秒数,计为 int64。样本的值必须 (MUST) 是 float64。
对于每个 TimeSeries
消息
labels_refs
必须 (MUST) 提供。samples
或 histograms
中至少必须 (MUST) 提供一个元素。一个 TimeSeries
不得 (MUST NOT) 同时包含 samples
和 histograms
。对于(很少)混合浮点和直方图样本的时间序列,必须 (MUST) 使用单独的 TimeSeries
消息。metadata
子字段应该 (SHOULD) 提供。接收端可以 (MAY) 拒绝未指定 Metadata.type
的时间序列。created_timestamp
。接收端可以 (MAY) 拒绝未设置 created_timestamp
的时间序列。以下小节详细定义了一些模式元素。
io.prometheus.write.v2.Request
Protobuf 消息旨在intern 所有字符串,以便在标准压缩基础上获得经过验证的额外压缩和内存效率提升。
symbols
表必须 (MUST) 提供,并且必须 (MUST) 包含在时间序列、exemplar 标签和元数据字符串中使用的去重字符串。symbols
表的第一个元素必须 (MUST) 是一个空字符串,用于表示空或未指定的值,例如未提供 Metadata.unit_ref
或 Metadata.help_ref
时。引用必须 (MUST) 指向 symbols
字符串数组中现有的索引。
完整的标签集必须 (MUST) 与每个 Sample
或 Histogram
样本一起发送。此外,与样本关联的标签集
__name__
标签。指标名称、标签名称和标签值必须 (MUST) 是任意 UTF-8 字符序列。
指标名称应该 (SHOULD) 遵循正则表达式 [a-zA-Z_:]([a-zA-Z0-9_:])*
。
标签名称应该 (SHOULD) 遵循正则表达式 [a-zA-Z_]([a-zA-Z0-9_])*
。
不符合上述规则的名称,对于 PromQL 用户来说可能更难使用(有关更多详细信息,请参阅UTF-8 提案)。
以 "__" 开头的标签名称保留用于系统使用,不应该 (SHOULD NOT) 使用,请参阅Prometheus 数据模型。
接收端也可以 (MAY) 对标签的数量和长度施加限制,但这取决于接收端,超出本文档的范围。
对于任何给定的 TimeSeries
,发送端必须 (MUST) 按时间戳顺序发送 samples
(或 histograms
)。发送端可以 (MAY) 并行发送不同时间序列的多个请求。
当某个时间序列不再附加数据时,发送端应该 (SHOULD) 发送陈旧标记。如果可以检测到时间序列的终止,发送端必须 (MUST) 发送陈旧标记,例如
通常,对于已终止的时间序列不发送陈旧标记可能导致接收端出现复杂的查询时间对齐问题。
陈旧标记必须 (MUST) 通过特殊的 NaN 值 0x7ff0000000000002
来表示。此值不得 (MUST NOT) 用于其他用途。
通常,发送端可以使用以下技术检测何时某个时间序列不再附加数据
元数据应该 (SHOULD) 遵循 Prometheus 官方关于类型 (Type) 和帮助字符串 (Help) 的指南。
元数据可以 (MAY) 遵循 OpenMetrics 官方关于单位 (Unit) 的指南。
每个 exemplar,如果附加到 TimeSeries
trace_id
标签名称。与1.0 中的相同。
本节包含尚未被视为协议规范一部分,但在此提及以供参考的推测性计划。注意 2.0 规范完成了1.0 中 3 个未来计划中的 2 个。
io.prometheus.write.v2.Request
线路格式实现自定义分桶。发送端可以 (MAY) 以这种方式将所有经典直方图转换为原生直方图,但这超出了本规范的要求。然而,出于这个原因,接收端可以 (MAY) 忽略某些指标类型(例如经典直方图)。替代线路格式。OpenTelemetry 社区通过其 OTLP 协议展示了 Apache Arrow(以及潜在的其他列式格式)用于线路数据传输的有效性。我们希望进行实验以确认类似格式与 Prometheus 数据模型的兼容性,并包含任何资源使用变化的基准测试。出于兼容性原因,我们可能会长期维护 protobuf 和列式两种格式,并利用我们的内容协商为此目的添加不同的 Protobuf 消息。
全局符号。用于字符串 interning 的预定义字符串字典 协议可以预定义一个静态的 ref->symbol 字典,其中包含被认为是常见的字符串,例如“namespace”、“le”、“job”、“seconds”、“bytes”等。发送端可以引用这些字符串,而无需将它们包含在请求的符号表中。该字典可以随着该协议的次要版本发布而逐步增长。
为什么不使用流式 protobuf 消息? 如果你使用持久的 HTTP/1.1 连接,它们已经非常接近流式了。当然,头部必须重新发送,但这比建立新的 TCP 连接的开销要小。
为什么我们按顺序发送样本? 顺序约束来自于我们在 Prometheus 中用于时间序列数据的编码,其实现针对仅追加工作负载进行了优化。然而,这个要求也在生态系统中的许多其他数据库和供应商之间共享。事实上,启用了 OOO 功能的 Prometheus 允许乱序写入,但会牺牲性能,因此保留用于罕见事件。总而言之,接收端可能支持乱序写入,尽管规范不允许。将来,例如 2.x 规范版本,我们可以扩展内容类型来协商乱序写入,如果需要的话。
如何在具有顺序约束的情况下并行化请求? 样本必须按顺序发送给给定时间序列。但是,即使接收端不支持乱序写入,只要远程写入请求针对不同的时间序列,就可以并行发送。Prometheus 通过标签将样本分片到单独的队列中,然后在每个队列中按顺序进行写入。这确保了同一时间序列的样本按顺序传递,但不同时间序列的样本并行发送——并且可能在不同时间序列之间“乱序”。
远程写入 2.0 与 OpenTelemetry 的 OTLP 协议有何区别? OpenTelemetry OTLP 是一个用于在遥测源、中间节点和遥测后端之间传输遥测数据(如指标、日志、跟踪和概要)的协议。推荐的传输方式是使用 gRPC 和 protobuf,但也描述了使用 HTTP 和 protobuf 或 JSON 的方式。它从零开始设计,旨在支持各种不同的可观测性信号、数据类型和额外信息。对于指标,这意味着额外的非标识标签、标志、时间聚合类型、资源或范围指标、模式 URL 等。OTLP 也要求使用语义约定。
远程写入设计简单、高效且有机发展。第一个版本于 2023 年正式发布,当时 CNCF 生态系统中已有数十家经过实战检验的采用者多年来一直在使用该协议。远程写入 2.0 在先前协议的基础上进行迭代,添加了一些新元素(元数据、exemplars、创建时间戳和原生直方图)和字符串 interning。远程写入 2.0 始终是无状态的,只关注指标,并且具有明确的观点;因此,它的范围被限制在 Prometheus 社区认为足以构建一个健壮指标解决方案的元素。其目的是确保远程写入是一个稳定协议,比可观测性生态系统中的替代方案更便宜、更简单地采用和使用。
本文档是开源的。请通过提交issue 或 pull request 帮助改进它。
© Prometheus 作者 2014-2025 | 文档根据 CC-BY-4.0 分发