Prometheus 遠端寫入 2.0 規範 [實驗性]
- 版本:2.0-rc.4
- 狀態:實驗性
- 日期:2024 年 5 月
遠端寫入規範旨在總體上記錄 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/remotewrite/sender
- 接收方:https://github.com/prometheus/compliance/tree/main/remotewrite/receiver
術語表
本文件遵循以下定義
Remote-Write是此 Prometheus 協議的名稱。Protocol是一種通訊規範,使客戶端和伺服器能夠傳輸指標。Protobuf Message(或 Proto 訊息)指此協議資料結構的 內容型別 定義。由於規範完全使用 Google Protocol Buffers(“protobuf”) ,因此模式在 “proto”檔案 中定義,並由單個 Protobuf “訊息” 表示。Wire Format是資料在傳輸過程中(即在網路中)的格式。對於遠端寫入,這始終是壓縮的二進位制 protobuf 格式。Sender是傳送遠端寫入資料的實體。Receiver是接收(寫入)遠端寫入資料的實體。Written的含義由接收方決定,例如,通常它表示將接收到的資料儲存到資料庫中,但也可能僅僅是驗證、拆分或增強資料。Written指接收方已接收並接受的資料。接收方是否已將此資料攝取到持久儲存、寫入 WAL 等,由接收方決定。唯一的區別是接收方已接受此資料,而不是透過錯誤響應明確拒絕它。Sample是一個三元組(起始時間戳、時間戳、值)。Histogram是一個三元組(起始時間戳、時間戳、直方圖值 )。Label是一個鍵值對(鍵,值)。Series是由一組唯一標籤標識的樣本(或直方圖)列表。
定義
協議
遠端寫入協議 MUST(必須)由 RPC 組成,其請求體使用 Google Protocol Buffers 序列化,然後進行壓縮。
Protobuf 序列化 MUST(必須)使用以下任一 Protobuf 訊息
- 在 遠端寫入 1.0 規範 中引入的
prometheus.WriteRequest。截至 2.0 版本,此訊息已被棄用。它 SHOULD(建議)僅出於相容性原因使用。傳送方和接收方 MAY NOT(可以不支援)prometheus.WriteRequest。 - 本規範中引入並在下方定義的
io.prometheus.write.v2.Request。傳送方和接收方 SHOULD(建議)在可能的情況下使用此訊息。傳送方和接收方 MUST(必須)支援io.prometheus.write.v2.Request。
Protobuf 訊息 MUST(必須)使用二進位制線格式(Wire Format)。然後,MUST(必須)使用 Google 的 Snappy 進行壓縮。Snappy 的 塊格式 MUST(必須)使用——幀格式 MUST NOT(不得)使用。
傳送方 MUST(必須)在 HTTP POST 請求體中傳送序列化並壓縮的 Protobuf 訊息,並透過 HTTP 將其傳送到接收方提供的 URL 路徑。接收方 MAY(可以)指定任何 HTTP URL 路徑來接收指標。
傳送方 MUST(必須)在 HTTP 請求中傳送以下保留頭
Content-EncodingContent-TypeX-Prometheus-Remote-Write-VersionUser-Agent
傳送方 MAY(可以)允許使用者新增自定義 HTTP 頭;它們 MUST NOT(不得)允許使用者以傳送保留頭的方式配置它們。
Content-Encoding
Content-Encoding: <compression>
內容編碼請求頭 MUST(必須)遵循 RFC 9110 。傳送方 MUST(必須)使用 snappy 值。接收方 MUST(必須)支援 snappy 壓縮。新的可選壓縮演算法可能會在 2.x 或更高版本中出現。
Content-Type
Content-Type: application/x-protobuf
Content-Type: application/x-protobuf;proto=<fully qualified name>
內容型別請求頭 MUST(必須)遵循 RFC 9110 。傳送方 MUST(必須)使用 application/x-protobuf 作為唯一的媒體型別。傳送方 MAY(可以)在頭的值中新增 ;proto= 引數,以指示所使用的 Protobuf 訊息的完全限定名,即上述兩種之一。因此,傳送方 MUST(必須)傳送以下三種受支援的頭值中的任何一種
對於 PRW 1.0 中引入的已棄用訊息,識別符號為 prometheus.WriteRequest
Content-Type: application/x-protobufContent-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。未來 2.x 或更高版本中可能會出現更多 Protobuf 訊息。
接收方 MUST(必須)使用內容型別頭來識別要使用的 Protobuf 訊息模式。意外選擇錯誤的模式可能導致非確定性行為(例如損壞)。
注意由於io.prometheus.write.v2.Request中的保留欄位,接收方意外地將錯誤模式與prometheus.WriteRequest配合使用將導致空訊息。這通常是為了方便避免意外錯誤,但請勿依賴此功能——未來的 Protobuf 訊息可能不具備此功能。
X-Prometheus-Remote-Write-Version
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
User-Agent: <name & version of the Sender>
傳送方 MUST(必須)包含一個使用者代理頭,該頭 SHOULD(建議)遵循 RFC 9110 使用者代理頭格式 。
響應
成功寫入所有資料的接收方 MUST(必須)返回 成功 2xx HTTP 狀態碼 。在這種成功情況下,接收方的響應體 SHOULD(建議)為空,並且狀態碼 SHOULD(建議)為 204 HTTP 無內容 ;傳送方 MUST(必須)忽略響應體。響應體 RESERVED(保留)供將來使用。
如果接收方已知的任何傳送資料(例如樣本、直方圖、Exemplar)未成功寫入(無論是部分寫入還是完全寫入拒絕),接收方 MUST NOT(不得)返回 2xx HTTP 狀態碼。在這種情況下,接收方 MUST(必須)在響應體中提供人類可讀的錯誤訊息。接收方的錯誤 SHOULD(建議)包含有關被拒絕樣本數量和原因的資訊。傳送方 MUST NOT(不得)嘗試解釋錯誤訊息,並 SHOULD(建議)按原樣記錄它。
以下小節詳細說明了傳送方和接收方在頭和不同寫入錯誤情況下的語義。
必需的 Written 響應頭
在成功進行內容協商後,接收方會處理(寫入)接收到的批資料。一旦為每個重要資料片段(目前是樣本、直方圖和 Exemplar)完成(成功或失敗),接收方 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)。由於存在 1.0 接收方可能不支援此功能的風險,傳送方在使用已棄用的 prometheus.WriteRequest Protobuf 訊息時 MUST NOT(不得)做出相同的假設。
傳送方 MAY(可以)使用這些頭來確認接收方成功寫入了哪些部分資料。常見用例包括
- 更好地處理 部分寫入 失敗情況:傳送方 MAY(可以)使用這些頭來實現更精確的客戶端儀器化和錯誤處理。
- 檢測損壞的 1.0 接收方實現:傳送方 SHOULD(建議)在傳送使用
io.prometheus.write.v2.Request請求的資料並收到 2xx HTTP 狀態碼,但接收方未傳送任何X-Prometheus-Remote-Write-*-Written響應頭時,假定為 415 HTTP 不支援的媒體型別 狀態碼。這是 1.0 接收方常見的問題,它們不檢查Content-Type請求頭;使用prometheus.WriteRequest模式意外解碼io.prometheus.write.v2.Request有效載荷會導致空結果且無解碼錯誤。 - 檢測其他損壞的實現或問題:傳送方 MAY(可以)使用這些頭來檢測損壞的傳送方和接收方實現或其他問題。
傳送方 MUST NOT(不得)從遠端寫入響應頭中假定接收方實現了哪個遠端寫入規範版本。
未來可能會有更多(可選)的頭,例如,當新增更多實體或欄位且值得確認時。
部分寫入
傳送方 SHOULD(建議)使用遠端寫入在單個請求中傳送多個序列的樣本。因此,接收方 MAY(可以)在包含一些無效或未寫入樣本的寫入請求中寫入有效樣本,這表示部分寫入情況。在這種情況下,接收方 MUST(必須)遵循無效樣本和部分寫入重試部分返回非 2xx 狀態碼。
不支援的請求內容
如果接收方不支援傳送方提供的特定內容型別或編碼,它們 MUST(必須)返回 415 HTTP 不支援的媒體型別 狀態碼。
出於向後相容性原因,傳送方 SHOULD(建議)期望 1.x 接收方因上述原因返回 400 HTTP 錯誤請求 。
無效樣本
接收方 MAY NOT(可以不支援)某些指標型別或樣本(例如,一個接收方可能會拒絕未指定元資料型別或沒有起始時間戳的樣本,而另一個接收方可能會接受此類樣本)。哪個樣本無效取決於接收方。接收方 MUST(必須)對包含任何無效樣本的寫入請求返回 400 HTTP 錯誤請求 狀態碼,除非發生部分可重試寫入。
傳送方 MUST NOT(不得)對 4xx HTTP 狀態碼(429 除外)進行重試,429 HTTP 狀態碼 MUST(必須)由接收方用於指示寫入操作永遠無法成功,不應重試。傳送方 MAY(可以)在 415 HTTP 狀態碼下嘗試使用不同的內容型別或編碼進行重試,以檢視接收方是否支援。
重試與退避
接收方 MAY(可以)返回 429 HTTP 請求過多 狀態碼以指示伺服器過載情況。接收方 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 訊息(線格式)本身在某些方面是向前/向後相容的
- 從 Protobuf 訊息中刪除欄位需要增加主版本號。
- 新增(可選)欄位可以在次版本號增加時完成。
換句話說,這意味著 2.x 的未來次要版本 MAY(可以)向 io.prometheus.write.v2.Request 新增新的可選欄位、新的壓縮、Protobuf 訊息和協商機制,只要它們是向後相容的(例如,對接收方和傳送方都是可選的)。
2.x 與 1.x 相容性
2.x 協議透過引入新的強制性 io.prometheus.write.v2.Request Protobuf 訊息並棄用 prometheus.WriteRequest,打破了與 1.x 的相容性。
2.x 傳送方 MAY(可以)透過允許使用者配置傳送方應使用的內容型別來支援 1.x 接收方。如果接收方返回 415 HTTP 狀態碼,2.x 傳送方也 MAY(可以)自動回退到不同的內容型別。
Protobuf 訊息
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 的簡化版本如下所示。
message Request {
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 {
reserved 6;
// 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 start 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;
}
// Exemplar is an additional information attached to some series' samples.
// It is typically used to attach an example trace or request ID associated with
// the metric changes.
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.
//
// For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go
// for conversion from/to time.Time to Prometheus timestamp.
int64 timestamp = 2;
// start_timestamp represents an optional start timestamp for the sample,
// in ms format. This information is typically used for counter, histogram (cumulative)
// or delta type metrics.
//
// For cumulative metrics, the start timestamp represents the time when the
// counter started counting (sometimes referred to as created timestamp), which
// can increase the accuracy of certain processing and query semantics (e.g. rates).
//
// Note:
// * That some receivers might require start timestamps for certain metric
// types; rejecting such samples within the Request as a result.
// * start timestamp is the same as "created timestamp" name Prometheus used in the past.
//
// 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 efficiency and consistency.
// Zero value means value not set. If you need to use exactly zero value for
// the timestamp, use 1 millisecond before or after.
int64 start_timestamp = 3;
}
// 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 message, supporting
// * sparse exponential bucketing, custom bucketing.
// * float or integer histograms.
//
// See the full spec: https://prometheus.golang.com.tw/docs/specs/native_histograms/
message Histogram { ... }
所有時間戳 MUST(必須)是自 Unix 紀元以來的毫秒數,以 int64 計數。樣本的值 MUST(必須)是 float64。
對於每個 TimeSeries 訊息
- MUST(必須)提供
labels_refs。
- MUST(必須)提供
samples或histograms中的至少一個元素。一個TimeSeriesMUST NOT(不得)同時包含samples和histograms。對於(極少)混合浮點和直方圖樣本的序列,MUST(必須)使用單獨的TimeSeries訊息。
- SHOULD(建議)提供
metadata子欄位。接收方 MAY(可以)拒絕具有未指定Metadata.type的序列。 - 如果序列存在 Exemplar,SHOULD(建議)提供它們。
以下小節詳細定義了一些模式元素。
符號
io.prometheus.write.v2.Request Protobuf 訊息旨在 對所有字串進行字串駐留(intern) ,以在標準壓縮的基礎上獲得額外的壓縮和記憶體效率提升。
MUST(必須)提供 symbols 表,並且它 MUST(必須)包含序列、Exemplar 標籤和元資料字串中使用的去重字串。symbols 表的第一個元素 MUST(必須)是一個空字串,用於表示空值或未指定值,例如未提供 Metadata.unit_ref 或 Metadata.help_ref 時。引用 MUST(必須)指向 symbols 字串陣列中已存在的索引。
序列標籤
MUST(必須)隨每個 Sample 或 Histogram 樣本傳送完整的標籤集。此外,與樣本關聯的標籤集
- SHOULD(建議)包含一個
__name__標籤。 - MUST NOT(不得)包含重複的標籤名。
- MUST(必須)按字典序排序標籤名。
- MUST NOT(不得)包含任何空的標籤名或標籤值。
指標名稱、標籤名稱和標籤值 MUST(必須)是任何 UTF-8 字元序列。
指標名稱 SHOULD(建議)遵循正則表示式 [a-zA-Z_:]([a-zA-Z0-9_:])*。
標籤名稱 SHOULD(建議)遵循正則表示式 [a-zA-Z_]([a-zA-Z0-9_])*。
不符合上述規則的名稱可能對 PromQL 使用者來說更難使用(詳情請參閱 UTF-8 提案 )。
以“__”開頭的標籤名 RESERVED(保留)用於系統用途,SHOULD NOT(不建議)使用,請參閱 Prometheus 資料模型。
接收方也 MAY(可以)對標籤的數量和長度施加限制,但這取決於接收方,超出本文件的範圍。
樣本和直方圖樣本
傳送方 MUST(必須)按時間戳順序傳送給定 TimeSeries 的 samples(或 histograms)。傳送方 MAY(可以)並行傳送針對不同序列的多個請求。
對於遵循計數器語義的型別(例如計數器和計數器直方圖),SHOULD(建議)提供樣本或直方圖的 start_timestamp。接收方 MAY(可以)拒絕未設定 start_timestamp 的序列。考慮到可選性,0 值 MUST(必須)被接收方視為未設定值。要表示不太可能發生的 0 毫秒 Unix 時間戳,MUST(必須)使用“1”或“-1”值。
當時間序列不再附加資料時,傳送方 SHOULD(建議)傳送陳舊標記。如果可以檢測到時間序列的停止,傳送方 MUST(必須)傳送陳舊標記,例如
- 對於被拉取(抓取)的序列,除非使用了明確的時間戳。
- 對於透過記錄規則評估產生的序列。
通常,對於已停止的序列不傳送陳舊標記可能導致接收方出現非簡單的查詢時間對齊問題。
陳舊標記 MUST(必須)由特殊的 NaN 值 0x7ff0000000000002 來表示。否則 MUST NOT(不得)使用此值。
通常,傳送方可以使用以下技術檢測時間序列何時不再附加資料
- 使用服務發現檢測到暴露該序列的目標已消失。
- 注意到目標在連續抓取之間不再暴露時間序列。
- 抓取最初暴露時間序列的目標失敗。
- 跟蹤記錄規則和告警規則的配置和評估。
- 跟蹤非抓取來源指標的停止(例如,在 k6 中,當每個基準測試的序列已完成時,它可以發出一個陳舊標記)。
元資料
元資料應遵循官方 Prometheus 指南,針對型別和幫助資訊。
元資料可遵循官方 OpenMetrics 指南,針對單位 。
Exemplars(範例)
每個 exemplar,如果附加到TimeSeries
- 必須包含一個值。
- 可以包含標籤,例如引用跟蹤或請求 ID。如果 exemplar 引用了跟蹤,作為最佳實踐,它應使用
trace_id標籤名。 - 必須包含一個時間戳。雖然 Prometheus/Open Metrics 暴露格式中的 exemplar 時間戳是可選的,但其假設是時間戳在抓取時被分配,就像抓取樣本的時間戳一樣。接收器需要 exemplar 時間戳來可靠地處理(例如去重)傳入的 exemplar。
範圍外
與1.0相同。
未來計劃
本節包含投機性計劃,這些計劃尚未被視為協議規範的一部分,但在此提及以求完整。請注意,2.0 規範完成了1.0 中的 3 個未來計劃中的 2 個。
-
事務性 2.0 規範仍然沒有定義事務性,主要是因為它使得可伸縮的傳送方實現變得困難。Prometheus 傳送方旨在實現“事務性”——即絕不向查詢暴露部分抓取的目標。我們打算對遠端寫入(Remote-Write)也這樣做——例如,未來我們希望“對齊”遠端寫入與抓取,也許讓單個抓取的所有樣本、元資料和 exemplar 在一個遠端寫入請求中傳送。
然而,遠端寫入 2.0 規範解決了經典直方圖桶 的一個重要事務性問題。這得益於原生直方圖支援透過
io.prometheus.write.v2.Request有線格式實現的自定義分桶。傳送方可以透過這種方式將所有經典直方圖轉換為原生直方圖,但這超出了本規範的規定範圍。然而,因此,接收器可以忽略某些度量型別(例如經典直方圖)。 -
替代有線格式。OpenTelemetry 社群已經透過其 OTLP 協議展示了 Apache Arrow(以及可能其他列式格式)用於資料有線傳輸的有效性。我們希望進行實驗,以確認類似格式與 Prometheus 資料模型的相容性,並納入任何資源使用變化的基準測試。出於相容性原因,我們可能會長期維護 protobuf 和列式兩種格式,並使用我們的內容協商為此目的新增不同的 Protobuf 訊息。
-
全域性符號。預定義用於內部化的字串字典 協議可以預定義一個靜態的 ref->symbol 字典,其中包含被認為是常見的字串,例如“namespace”、“le”、“job”、“seconds”、“bytes”等。傳送方可以直接引用這些符號,而無需將其包含在請求的符號表中。這個字典可以隨著協議的小版本釋出而逐步增長。
相關問題
常見問題
為什麼不使用 gRPC? 因為 1.0 協議不使用 gRPC,打破這一慣例會增加採用的摩擦。請參閱 1.0原因。
為什麼不流式傳輸 protobuf 訊息? 如果使用持久的 HTTP/1.1 連線,它們非常接近流式傳輸。當然,標頭必須重新發送,但這比建立新的 TCP 連線的開銷要小。
為什麼我們按順序傳送樣本? 順序約束來自於 Prometheus 中時間序列資料所使用的編碼,其實現針對只追加(append-only)工作負載進行了最佳化。然而,這個要求也在生態系統中許多其他資料庫和供應商之間共享。事實上,啟用 OOO 功能的 Prometheus 允許亂序寫入,但會帶來效能損失,因此僅保留用於罕見事件。總而言之,接收器可能支援亂序寫入,儘管規範不允許這樣做。未來,例如在 2.x 規範版本中,如果需要,我們可以擴充套件內容型別來協商亂序寫入。
如何在有順序約束的情況下並行化請求? 樣本必須是針對給定序列按順序的。然而,即使接收器不支援亂序寫入,只要遠端寫入請求是針對不同序列的,它們就可以並行傳送。Prometheus 根據標籤將樣本分片到不同的佇列中,然後每個佇列中的寫入按順序發生。這保證了同一序列的樣本按順序傳遞,但不同序列的樣本則並行傳送——並且可能在不同序列之間“亂序”。
遠端寫入 2.0 與 OpenTelemetry 的 OTLP 協議有什麼區別? OpenTelemetry OTLP 是一種用於在遙測源、中間節點和遙測後端之間傳輸遙測資料(如指標、日誌、跟蹤和配置檔案)的協議。推薦的傳輸方式是 gRPC 結合 protobuf,但也描述了 HTTP 結合 protobuf 或 JSON 的方式。它從頭開始設計,旨在支援各種不同的可觀測性訊號、資料型別和額外資訊。對於指標 ,這意味著額外的非識別標籤、標誌、時間聚合型別、資源或範圍指標、模式 URL 等。OTLP 還要求使用語義約定 。
遠端寫入(Remote-Write)的設計旨在實現簡潔性、效率和有機增長。第一個版本於 2023 年正式釋出,當時CNCF 生態系統中數十個經過實戰驗證的採用者已經使用該協議多年。遠端寫入 2.0 在先前協議的基礎上進行了迭代,增加了一些新元素(元資料、exemplar、起始時間戳和原生直方圖)以及字串內部化。遠端寫入 2.0 始終是無狀態的,只專注於指標,並且是主觀的;因此,它僅限於 Prometheus 社群認為足以提供健壯指標解決方案的元素。其目的是確保遠端寫入是一個穩定的協議,比可觀測性生態系統中的替代方案更便宜、更簡單地採用和使用。