OpenMetrics 1.0

  • バージョン: 1.0
  • ステータス: 公開済み
  • 日付: 2022年3月
  • 著者: Richard Hartmann、Ben Kochie、Brian Brazil、Rob Skillington

2012年に作成されたPrometheusは、2015年以来、クラウドネイティブな可観測性のデフォルトとなっています。Prometheusの設計の中心的な部分は、2014年以来安定しているPrometheus公開形式0.0.4と呼ばれるテキストメトリック公開形式です。この形式では、生成、取り込み、人間による理解を容易にするための特別な配慮がなされています。2020年現在、700を超える公開されているエクスポーター、不明な数の非公開エクスポーター、および何千ものネイティブライブラリ統合がこの形式を使用しています。さまざまなプロジェクトや企業からの数十の取り込みシステムがその消費をサポートしています。

OpenMetricsでは、IETFに持ち込むという明確な目的で仕様を整理し、厳格化しています。私たちは、広く有機的に採用されている作業標準を文書化するとともに、最小限で、ほとんど後方互換性があり、十分に検討された変更を導入しています。2020年現在、数十のエクスポーター、インテグレーション、取り込みシステムがすでにOpenMetricsを使用し、優先的にネゴシエートしています。

エコシステムにおける広範な採用と大幅な調整要件を考慮すると、Prometheus公開形式0.0.4またはOpenMetrics 1.0のいずれかに抜本的な変更を加えることは対象外と見なされます。

OpenMetrics 2.0の開発が進行中です。こちらでPrometheus OM 2.0作業グループへの参加方法をご覧ください。

概要

メトリックは、特定の種類のテレメトリーデータです。これらは、一連のデータの現在の状態のスナップショットを表します。個々のイベントの記録や情報に焦点を当てるログやイベントとは異なります。

OpenMetricsは主にワイヤー形式であり、その形式の特定の転送に依存しません。この形式は定期的に消費され、連続する公開にわたって意味を持つことが期待されます。

実装者は、所定のプロセスまたはデバイスの文書化されたURLへの単純なHTTP GETリクエストに応答して、OpenMetricsテキスト形式でメトリックを公開しなければなりません (MUST)。このエンドポイントは "/metrics" と呼ばれるべきです (SHOULD)。実装者は、OpenMetrics形式のメトリックを、HTTP経由で演算子構成のエンドポイントに定期的にメトリックセットをプッシュするなど、他の方法で公開しても構いません (MAY)。

メトリックと時系列

この標準は、すべてのシステム状態を数値として表現します。一般的な例としては、カウント、現在の値、列挙、およびブール状態があります。メトリックとは対照的に、単一のイベントは特定の時間に発生します。メトリックは時間的にデータを集約する傾向があります。これは情報を失う可能性がありますが、オーバーヘッドの削減は、多くの最新の監視システムで一般的に選択されるエンジニアリング上のトレードオフです。

時系列とは、時間の経過とともに変化する情報の記録です。時系列は任意の文字列やバイナリデータをサポートできますが、このRFCの範囲では数値データのみが対象です。

メトリック時系列の一般的な例としては、ネットワークインターフェースカウンター、デバイス温度、BGP接続状態、およびアラート状態があります。

データモデル

このセクションはABNFセクションと合わせて読む必要があります (MUST)。両者の間に不一致がある場合、ABNFの制限が優先されなければなりません (MUST)。これは、テキストワイヤーフォーマットがサポートされなければならない (MUST) ため、繰り返しを減らします。

データ型

OpenMetricsのメトリック値は、浮動小数点数または整数でなければなりません (MUST)。形式の取り込み側がfloat64のみをサポートする可能性があることに注意してください (Note)。非実数値のNaN、+Inf、-Infはサポートされなければなりません (MUST)。NaNは欠損値と見なされてはなりません (MUST NOT) が、ゼロ除算を示すために使用されても構いません (MAY)。

ブール値

ブール値は、1==true0==false に従わなければなりません (MUST)。

タイムスタンプ

タイムスタンプはUnixエポックからの秒数でなければなりません (MUST)。負のタイムスタンプを使用しても構いません (MAY)。

文字列

文字列は有効なUTF-8文字のみで構成されなければならず (MUST)、長さがゼロであっても構いません (MAY)。NULL (ASCII 0x0) はサポートされなければなりません (MUST)。

ラベル

ラベルは文字列からなるキーと値のペアです。

アンダースコアで始まるラベル名は予約されており (RESERVED)、この標準で指定されていない限り使用してはなりません (MUST NOT)。ラベル名はABNFセクションの制限に従わなければなりません (MUST)。

空のラベル値は、ラベルが存在しないかのように扱われるべきです (SHOULD)。

ラベルセット

LabelSetはLabelで構成されなければならず (MUST)、空であっても構いません (MAY)。LabelSet内でラベル名は一意でなければなりません (MUST)。

メトリックポイント

各MetricPointは、MetricFamilyのタイプに応じて、一連の値で構成されます。

ExemplarはMetricSetの外部のデータへの参照です。一般的な使用例は、プログラムトレースのIDです。

ExemplarはLabelSetと値で構成されなければならず (MUST)、タイムスタンプを持っても構いません (MAY)。それらはMetricPointのLabelSetとタイムスタンプとは異なっても構いません (MAY)。

ExemplarのLabelSetのラベル名と値の合計の長さは、128 UTF-8文字コードポイントを超えてはなりません (MUST NOT)。エクゼンプラーのテキスト表現における",=などの他の文字は、実装の簡素化とテキスト形式とプロト形式の一貫性のために、この制限に含まれません。

取り込みシステムはExemplarを破棄しても構いません (MAY)。

メトリック

メトリックは、MetricFamily内の一意のLabelSetによって定義されます。メトリックは、1つ以上のMetricPointのリストを含まなければなりません (MUST)。特定のMetricFamilyで同じ名前を持つメトリックは、そのLabelSetに同じラベル名のセットを持つべきです (SHOULD)。

MetricPointは明示的なタイムスタンプを持つべきではありません (SHOULD NOT)。

メトリックに対して複数のMetricPointが公開されている場合、そのMetricPointは単調増加するタイムスタンプを持たなければなりません (MUST)。

メトリックファミリー

MetricFamilyは0個以上のMetricを持つことができます (MAY)。MetricFamilyは名前、HELP、TYPE、およびUNITメタデータを持たなければなりません (MUST)。MetricFamily内のすべてのMetricは一意のLabelSetを持たなければなりません (MUST)。

名前

MetricFamily名は文字列であり、MetricSet内で一意でなければなりません (MUST)。名前はsnake_caseであるべきです (SHOULD)。メトリック名はABNFセクションの制限に従わなければなりません (MUST)。

MetricFamily名内のコロンは、MetricFamilyが汎用監視システムの計算または集計の結果であることを示すために予約されています (RESERVED)。

アンダースコアで始まるMetricFamily名は予約されており (RESERVED)、この標準で指定されていない限り使用してはなりません (MUST NOT)。

接尾辞

MetricFamilyの名前は、MetricSet内のテキスト形式で別のMetricFamilyとのサンプルメトリック名の潜在的な衝突を引き起こしてはなりません (MUST NOT)。例としては、「foo_created」というゲージは、カウンター「foo」がテキスト形式で「foo_created」を作成する可能性があるため、衝突を引き起こす可能性があります。

エクスポーターは、テキスト形式のサンプルメトリック名が使用する接尾辞と混同される可能性のある名前を避けるべきです (SHOULD)。

  • 各タイプの接尾辞は次のとおりです。
  • カウンター: _total, _created
  • サマリー: _count, _sum, _created, `` (空)
  • ヒストグラム: _count, _sum, _bucket, _created
  • ゲージヒストグラム: _gcount, _gsum, _bucket
  • 情報: _info
  • ゲージ: `` (空)
  • ステートセット: `` (空)
  • 不明: `` (空)
タイプ

TypeはMetricFamilyのタイプを指定します。有効な値は "unknown"、"gauge"、"counter"、"stateset"、"info"、"histogram"、"gaugehistogram"、および "summary" です。

単位

UnitはMetricFamilyの単位を指定します。空でない場合、MetricFamily名にアンダースコアで区切られた接尾辞でなければなりません (MUST)。さらなる生成ルールにより、テキスト形式では中置になる可能性があることに注意してください。

ヘルプ

Helpは文字列であり、空であってはいけません (SHOULD NOT)。人間が消費するためにMetricFamilyの簡単な説明を与えるために使用され、ツールチップとして使用できるほど短いべきです (SHOULD)。

メトリックセット

MetricSetはOpenMetricsによって公開されるトップレベルオブジェクトです。それはMetricFamilyで構成されなければならず (MUST)、空であっても構いません (MAY)。

各MetricFamily名は一意でなければなりません (MUST)。同じラベル名と値がMetricSet内のすべてのMetricに現れてはなりません (SHOULD NOT)。

MetricSet内のMetricFamilyに特定の順序は必要ありません。公開者は、例えば、パフォーマンスのトレードオフが理にかなっている場合、人間が読みやすいようにアルファベット順に並べても構いません (MAY)。

存在する場合、以下の「プッシュベースおよびプルベースシステムにおけるターゲットメタデータのサポート」セクションに従って、「target」と呼ばれるInfo MetricFamilyが最初であるべきです (SHOULD)。

メトリックタイプ

ゲージ

ゲージは、現在使用されているメモリバイト数やキュー内の項目数など、現在の測定値です。ゲージの場合、ユーザーにとって関心があるのは絶対値です。

ゲージタイプのメトリック内のMetricPointは、単一の値を持たなければなりません (MUST)。

ゲージは時間の経過とともに増加、減少、または一定のままであっても構いません (MAY)。常に一方向にしか進まなくても、ゲージであってカウンターではない場合があります。ログファイルのサイズは通常は増加するだけですが、リソースは減少する可能性があり、キューサイズの制限は一定である場合があります。

ゲージは、多くの状態を持ち、時間の経過とともに変化するenumをエンコードするために使用しても構いません (MAY)。これは最も効率的ですが、最もユーザーフレンドリーではありません。

カウンター

カウンターは離散イベントを測定します。一般的な例としては、受信したHTTPリクエストの数、費やされたCPU秒数、送信されたバイト数などがあります。カウンターの場合、時間の経過とともにどれだけ早く増加しているかがユーザーにとって関心のある点です。

Counterタイプのメトリック内のMetricPointは、Totalという1つの値を持たなければなりません (MUST)。TotalはNaNではなく、0から始まり、時間とともに単調に非減少でなければなりません (MUST)。

Counterタイプのメトリック内のMetricPointは、Createdというタイムスタンプ値を持つべきです (SHOULD)。これにより、取り込みシステムは、新しいメトリックと、以前には見られなかった長時間実行されているメトリックを区別するのに役立ちます。

メトリックのカウンターの合計値のメトリックポイントは0にリセットされても構いません (MAY)。存在する場合、対応する作成時刻もリセットのタイムスタンプに設定されなければなりません (MUST)。

メトリックのカウンターの合計値のメトリックポイントは、エクゼンプラーを持っても構いません (MAY)。

ステートセット

StateSetは、ビットセットとも呼ばれる、関連する一連のブール値を表します。ENUMをエンコードする必要がある場合、これはStateSetを使用して行っても構いません (MAY)。

StateSetメトリックのポイントは、複数の状態を含んでもよく (MAY)、状態ごとに1つのブール値を含まなければなりません (MUST)。状態には文字列である名前があります。

StateSet MetricのLabelSetは、そのMetricFamilyの名前と同じラベル名を持ってはなりません (MUST NOT)。

StateSetとしてエンコードされた場合、ENUMはMetricPoint内に真であるブール値をちょうど1つ持たなければなりません (MUST)。

これは、enum値が時間とともに変化し、Stateの数がわずかである場合に適しています。

StateSetsタイプのMetricFamilyは、空のUnit文字列を持たなければなりません (MUST)。

情報

情報メトリックは、プロセス寿命中に変更すべきではない (SHOULD NOT) テキスト情報を公開するために使用されます。一般的な例としては、アプリケーションのバージョン、リビジョン管理コミット、コンパイラのバージョンなどがあります。

Info MetricPointはLabelSetを含みます。Info MetricPointのLabelSetは、そのMetricのLabelSetのラベル名と同じラベル名を持ってはなりません (MUST NOT)。

Infoは、ネットワークインターフェースのタイプなど、時間の経過とともに値が変化しないENUMをエンコードするために使用しても構いません (MAY)。

InfoタイプのMetricFamilyは、空のUnit文字列を持たなければなりません (MUST)。

ヒストグラム

ヒストグラムは、離散イベントの分布を測定します。一般的な例としては、HTTPリクエストのレイテンシ、関数実行時間、I/Oリクエストサイズなどがあります。

ヒストグラム MetricPointは少なくとも1つのバケットを含まなければならず (MUST)、SumとCreatedの値を含むべきです (SHOULD)。すべてのバケットは閾値と値を持たなければなりません (MUST)。

Histogram MetricPointsは、+Infの閾値を持つバケットを1つ持たなければなりません (MUST)。バケットは累積でなければなりません (MUST)。例えば、HTTPリクエストのレイテンシを秒単位で表すメトリックの場合、閾値1、2、3、および+Infのバケットの値はvalue_1 <= value_2 <= value_3 <= value_+Infに従わなければなりません (MUST)。10個のリクエストがそれぞれ1秒かかった場合、1、2、3、および+Infバケットの値は10と等しくなければなりません (MUST)。

+Infバケットはすべてのリクエストをカウントします。存在する場合、Sumの値は測定されたすべてのイベント値の合計と等しくなければなりません (MUST)。MetricPoint内のバケット閾値は一意でなければなりません (MUST)。

意味論的には、Sumとバケットの値はカウンターであるため、NaNまたは負であってはなりません (MUST NOT)。負の閾値バケットを使用しても構いません (MAY) が、その場合、意味論的にカウンターではなくなるため、Histogram MetricPointは合計値を含んではなりません (MUST NOT)。バケットの閾値はNaNと等しくなってはなりません (MUST NOT)。Countとバケットの値は整数でなければなりません (MUST)。

Histogram MetricPointは、Createdというタイムスタンプ値を持つべきです (SHOULD)。これにより、取り込みシステムは、新しいメトリックと、以前には見られなかった長時間実行されているメトリックを区別するのに役立ちます。

HistogramのMetricのLabelSetは、「le」というラベル名を持ってはなりません (MUST NOT)。

バケット値はエクゼンプラーを持つことができます (MAY)。バケットは累積であるため、監視システムがパフォーマンス/サービス拒否対策のために、粒度は失われるものの有効なヒストグラムである方法で、+Inf以外のバケットを破棄することができます。

各バケットはそれ以下またはそれに等しい値をカバーし、エクゼンプラーの値はこの範囲内でなければなりません (MUST)。エクゼンプラーは最大値を持つバケットに入れられるべきです (SHOULD)。1つのバケットは複数のエクゼンプラーを持ってはなりません (MUST NOT)。

ゲージヒストグラム

ゲージヒストグラムは現在の分布を測定します。一般的な例としては、キュー内のアイテムが待機している時間、またはキュー内のリクエストのサイズなどがあります。

GaugeHistogram MetricPointは、+Infの閾値を持つバケットを1つ持たなければならず (MUST)、Gsum値を含むべきです (SHOULD)。すべてのバケットは閾値と値を持たなければなりません (MUST)。

GaugeHistogramのバケットは、Histogramと同じルールに従います。

GaugeHistogramのバケットとGsumは概念的にはゲージですが、バケット値は負またはNaNであってはなりません (MUST NOT)。負の閾値バケットが存在する場合、合計は負であっても構いません (MAY)。GsumはNaNであってはなりません (MUST NOT)。バケット値は整数でなければなりません (MUST)。

GaugeHistogramのMetricのLabelSetは、「le」というラベル名を持ってはなりません (MUST NOT)。

バケット値はエクゼンプラーを持つことができます。

各バケットはそれ以下またはそれに等しい値をカバーし、エクゼンプラーの値はこの範囲内でなければなりません (MUST)。エクゼンプラーは最大値を持つバケットに入れられるべきです (SHOULD)。1つのバケットは複数のエクゼンプラーを持ってはなりません (MUST NOT)。

サマリー

サマリーも離散イベントの分布を測定し、ヒストグラムが高価すぎる場合や、平均イベントサイズで十分な場合に使用しても構いません (MAY)。

また、一部の既存の計測ライブラリが事前計算されたパーセンタイルを公開しており、ヒストグラムをサポートしていないため、下位互換性のために使用されても構いません (MAY)。パーセンタイルは集計可能ではなく、ユーザーはそれらがカバーする期間を推測できないことが多いため、事前計算されたパーセンタイルは使用すべきではありません (SHOULD NOT)。

Summary MetricPointは、Count、Sum、Created、および一連のパーセンタイルで構成されても構いません (MAY)。

意味論的には、CountとSumの値はカウンターであるため、NaNまたは負であってはなりません (MUST NOT)。Countは整数でなければなりません (MUST)。

CountまたはSum値を含むSummaryタイプのメトリック内のMetricPointは、Createdというタイムスタンプ値を持つべきです (SHOULD)。これにより、取り込みシステムは、新しいメトリックと、以前には見られなかった長時間実行されているメトリックを区別するのに役立ちます。Createdはパーセンタイル値の収集期間に関連してはなりません (MUST NOT)。

パーセンタイルは、パーセンタイルから値へのマップです。例として、myapp_http_request_duration_secondsというメトリックで、パーセンタイル0.95が値0.2を持つ場合、これは95パーセンタイルのレイテンシが不明な期間にわたって200msであることを意味します。関連する期間にイベントがない場合、パーセンタイルの値はNaNでなければなりません (MUST)。QuantileのMetricのLabelSetは、「quantile」ラベル名を持ってはなりません (MUST NOT)。パーセンタイルは0から1の範囲内(両端を含む)でなければなりません (MUST)。パーセンタイル値は負であってはなりません (MUST NOT)。パーセンタイル値は最近の値を表すべきです (SHOULD)。一般的には過去5~10分間のものであると考えられます。

不明

Unknownは使用すべきではありません (SHOULD NOT)。Unknownは、サードパーティシステムからの個々のメトリックのタイプを決定できない場合に使用しても構いません (MAY)。

不明なタイプのメトリック内のポイントは、単一の値を持たなければなりません (MUST)。

データ転送とワイヤーフォーマット

テキストワイヤーフォーマットはサポートされなければならず (MUST)、デフォルトです。protobufワイヤーフォーマットはサポートされても構いません (MAY) が、ネゴシエーション後にのみ使用しなければなりません (MUST ONLY)。

OpenMetrics形式は正規チョムスキー文法であり、高速で小さなパーサーの作成を可能にします。テキスト形式はよく圧縮され、protobufはすでにバイナリであり、効率的にエンコードされています。

部分的または無効な公開は、その全体がエラーと見なされなければなりません (MUST)。

プロトコルネゴシエーション

すべての取り込みシステム実装は、TLS 1.2以降で保護されたデータを取り込めるようにしなければなりません (MUST)。すべての公開システムは、TLS 1.2以降で保護されたデータを出力できるようにすべきです (SHOULD)。取り込みシステム実装は、TLSなしのHTTPからデータを取り込めるようにすべきです (SHOULD)。すべての実装は、データを送信するためにTLSを使用すべきです (SHOULD)。

OpenMetrics形式のどのバージョンを使用するかのネゴシエーションは帯域外で行われます。例えば、HTTP経由のプルベースの公開では、標準のHTTPコンテンツタイプネゴシエーションが使用され、新しいバージョンが要求されない限り、標準の最も古いバージョン (すなわち1.0.0) をデフォルトとしなければなりません (MUST)。

プッシュベースのネゴシエーションは、公開者が通常接続を開始するため、本質的に複雑です。プロデューサーは、取り込みシステムによって別途要求されない限り、標準の最も古いバージョン (すなわち1.0.0) を使用しなければなりません (MUST)。

テキスト形式

ABNF

RFC 5234に基づくABNF

"exposition"はABNFのトップレベルトークンです。

exposition = metricset HASH SP eof [ LF ]

metricset = *metricfamily

metricfamily = *metric-descriptor *metric

metric-descriptor = HASH SP type SP metricname SP metric-type LF
metric-descriptor =/ HASH SP help SP metricname SP escaped-string LF
metric-descriptor =/ HASH SP unit SP metricname SP *metricname-char LF

metric = *sample

metric-type = counter / gauge / histogram / gaugehistogram / stateset
metric-type =/ info / summary / unknown

sample = metricname [labels] SP number [SP timestamp] [exemplar] LF

exemplar = SP HASH SP labels SP number [SP timestamp]

labels = "{" [label *(COMMA label)] "}"

label = label-name EQ DQUOTE escaped-string DQUOTE

number = realnumber
; Case insensitive
number =/ [SIGN] ("inf" / "infinity")
number =/ "nan"

timestamp = realnumber

; Not 100% sure this captures all float corner cases.
; Leading 0s explicitly okay
realnumber = [SIGN] 1*DIGIT
realnumber =/ [SIGN] 1*DIGIT ["." *DIGIT] [ "e" [SIGN] 1*DIGIT ]
realnumber =/ [SIGN] *DIGIT "." 1*DIGIT [ "e" [SIGN] 1*DIGIT ]


; RFC 5234 is case insensitive.
; Uppercase
eof = %d69.79.70
type = %d84.89.80.69
help = %d72.69.76.80
unit = %d85.78.73.84
; Lowercase
counter = %d99.111.117.110.116.101.114
gauge = %d103.97.117.103.101
histogram = %d104.105.115.116.111.103.114.97.109
gaugehistogram = gauge histogram
stateset = %d115.116.97.116.101.115.101.116
info = %d105.110.102.111
summary = %d115.117.109.109.97.114.121
unknown = %d117.110.107.110.111.119.110

BS = "\"
EQ = "="
COMMA = ","
HASH = "#"
SIGN = "-" / "+"

metricname = metricname-initial-char 0*metricname-char

metricname-char = metricname-initial-char / DIGIT
metricname-initial-char = ALPHA / "_" / ":"

label-name = label-name-initial-char *label-name-char

label-name-char = label-name-initial-char / DIGIT
label-name-initial-char = ALPHA / "_"

escaped-string = *escaped-char

escaped-char = normal-char
escaped-char =/ BS ("n" / DQUOTE / BS)
escaped-char =/ BS normal-char

; Any unicode character, except newline, double quote, and backslash
normal-char = %x00-09 / %x0B-21 / %x23-5B / %x5D-D7FF / %xE000-10FFFF

全体構造

UTF-8を使用しなければなりません (MUST)。バイト順マーク (BOM) を使用してはなりません (MUST NOT)。実装者への重要な注意点として、バイト0は有効なUTF-8ですが、例えばバイト255はそうではありません。

コンテンツタイプは次のとおりでなければなりません。

application/openmetrics-text; version=1.0.0; charset=utf-8

行末はラインフィード (\n) で示されなければならず (MUST)、キャリッジリターン (\r) を含んではなりません (MUST NOT)。公開はEOFで終了しなければならず (MUST)、EOF\nで終了すべきです (SHOULD)。

完全な公開の例

# TYPE acme_http_router_request_seconds summary
# UNIT acme_http_router_request_seconds seconds
# HELP acme_http_router_request_seconds Latency though all of ACME's HTTP request router.
acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 9036.32
acme_http_router_request_seconds_count{path="/api/v1",method="GET"} 807283.0
acme_http_router_request_seconds_created{path="/api/v1",method="GET"} 1605281325.0
acme_http_router_request_seconds_sum{path="/api/v2",method="POST"} 479.3
acme_http_router_request_seconds_count{path="/api/v2",method="POST"} 34.0
acme_http_router_request_seconds_created{path="/api/v2",method="POST"} 1605281325.0
# TYPE go_goroutines gauge
# HELP go_goroutines Number of goroutines that currently exist.
go_goroutines 69
# TYPE process_cpu_seconds counter
# UNIT process_cpu_seconds seconds
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
process_cpu_seconds_total 4.20072246e+06
# EOF
エスケープ

ABNFがエスケープを記述している場合、以下のエスケープが適用されなければなりません (MUST)。ラインフィード、\n (0x0A) -> 文字列\\n (バイトコード 0x5c 0x6e)、二重引用符 -> \\" (バイトコード 0x5c 0x22)、バックスラッシュ -> \\\\ (バイトコード 0x5c 0x5c)

バックスラッシュ文字を表すには、二重バックスラッシュを使用すべきです (SHOULD)。未定義のエスケープシーケンスには、単一のバックスラッシュを使用すべきではありません (SHOULD NOT)。例として、\\\\a\\aと同等であり、好ましいです。

数値

整数には小数点を含めてはなりません (MUST NOT)。例として、230042、および1341298465647914があります。

浮動小数点数は、小数点または科学表記法で表現されなければなりません。例は 8903.123421 および 1.89e-7 です。浮動小数点数は、IEEE 754 で定義されている 64 ビット浮動小数点値の範囲内に収まらなければなりませんが、仮数部のビット数が多く、精度が失われる可能性があります。これは、ナノ秒分解能のタイムスタンプをエンコードするために使用されることがあります。

「Canonical Numbers」セクションにある「quantile」および「le」ラベル値には、任意の整数および浮動小数点の数値表現を使用してはなりません。それ以外の場所では、数値が使用されている限り、使用されることがあります。

考慮事項: 標準的な数値

ヒストグラムの「le」ラベル値とサマリーメトリクスの「quantile」ラベル値の数値は、ラベル値であり、ラベル値は不透明であることを意図しているため、特別です。エンドユーザーがこれらの文字列値を直接操作する可能性が高く、多くの監視システムがそれらをファーストクラスの数値として扱う機能がないため、与えられた数値がまったく同じテキスト表現を持つことが有益です。

一貫性は非常に望ましいですが、言語とそのランタイムの実装は、これを義務付けることを非現実的にしています。最も重要な一般的なクオンタイルは 0.5、0.95、0.9、0.99、0.999 であり、一般的なウェブサービスのレイテンシー SLA や Apdex のようなケースをカバーするため、ミリ秒から 10.0 秒までの値を表すバケット値です。固定小数点と指数表記の切り替えが一貫していることを保証するために、10 の累乗がカバーされています。これはランタイムによって異なります。目標となる表現は、float64 値のデフォルトの Go 表現 (すなわち %g) と同等であり、小数点または指数がない場合は、浮動小数点であることを明確にするために .0 が追加されます。

公開者は、正の無限大に対して +Inf として出力しなければなりません。

公開者は、0.0 から 10.0 までの値を 0.001 刻みで、以下の例に従って出力すべきです: 0.0 0.001 0.002 0.01 0.1 0.9 0.95 0.99 0.999 1.0 1.7 10.0

公開者は、1e-10 から 1e+10 までの値を 10 の累乗で、以下の例に従って出力すべきです: 1e-10 1e-09 1e-05 0.0001 0.1 1.0 100000.0 1e+06 1e+10

パーサーは、入力が標準値と一致しないという理由だけで、標準値の範囲外の入力を拒否してはなりません。例えば、1.1e-4 は 0.00011 の一貫した表現ではありませんが、拒否してはなりません。

公開者は、非標準の数値に対してこれらのパターンに従うべきであり、この意図は、これらの値に対してレンダリングアルゴリズムを調整することで、他の大部分の値も一貫したレンダリングを持つようになることです。特定の le/quantile 値のみを使用する公開者は、ハードコードすることもできます。C のような言語で、Grisu3 のような最小限の浮動小数点レンダリングアルゴリズムが容易に入手できない場合、公開者は異なるレンダリングを使用することができます。

C やその printf 実装を共有する他の言語の実装者への警告: %f、%e、%g の標準精度はわずか 6 桁です。完全な精度には 17 桁が必要です。例えば、printf("%.17g", d)

タイムスタンプ

ナノ秒の精度が必要な場合、タイムスタンプに指数浮動小数点表現を使用してはなりません。float64 のレンダリングは十分な精度を持たないためです。例: 1604676851.123456789

MetricFamily

MetricFamilies の間に明示的な区切り文字があってはなりません。次の MetricFamily は、メタデータまたは前の MetricFamily の一部ではない新しいサンプルメトリック名で通知されなければなりません。

MetricFamilies はインターリーブされてはなりません。

MetricFamily メタデータ

メタデータは、MetricFamily 名、TYPE、UNIT、HELP の 4 つです。foo というカウンターメトリックのメタデータの例は次のとおりです。

# TYPE foo counter

TYPE が公開されていない場合、MetricFamily は Unknown 型でなければなりません。

単位が指定されている場合、UNIT メタデータ行で提供されなければなりません。さらに、MetricFamily 名のサフィックスとしてアンダースコアと単位が付加されなければなりません。

単位が「seconds」の foo_seconds メトリックの有効な例

# TYPE foo_seconds counter
# UNIT foo_seconds seconds

単位が名前にサフィックスとして付いていない無効な例

# TYPE foo counter
# UNIT foo seconds

以下も有効です。

# TYPE foo_seconds counter

単位が既知の場合は、提供すべきです。

UNIT または HELP 行の値は空であってもかまいません。これは、MetricFamily のメタデータ行が存在しなかったかのように扱われなければなりません。

# TYPE foo_seconds counter
# UNIT foo_seconds seconds
# HELP foo_seconds Some text and \n some \" escaping

MetricFamily ごとに同じ種類のメタデータ行が複数あってはなりません。順序は TYPE、UNIT、HELP であるべきです。

このメタデータとメッセージの末尾にある EOF 行を除き、# で始まる行を公開してはなりません。

メトリック

メトリックはインターリーブされてはなりません。

「テキスト形式 -> MetricPoint」の例を参照してください。ラベル ラベルまたはタイムスタンプがなく、値が 0 のサンプルは次のようにレンダリングされなければなりません。

bar_seconds_count 0

または次のように

bar_seconds_count{} 0

ラベル値は任意の有効な UTF-8 値であってもよいので、ABNF に従ってエスケープが適用されなければなりません。2 つのラベルを持つ有効な例

bar_seconds_count{a="x",b="escaping\" example \n "} 0

MetricPoint の値のレンダリングには、追加のラベル (例: Histogram 型の「le」ラベル) を含めることができ、これらはメトリック自身の LabelSet と同じ方法でレンダリングされなければなりません。

MetricPoint

MetricPoints はインターリーブされてはなりません。

MetricFamily 内に複数の MetricPoints と Samples があった場合の正しい例は次のとおりです。

# TYPE foo_seconds summary
# UNIT foo_seconds seconds
foo_seconds_count{a="bb"} 0 123
foo_seconds_sum{a="bb"} 0 123
foo_seconds_count{a="bb"} 0 456
foo_seconds_sum{a="bb"} 0 456
foo_seconds_count{a="ccc"} 0 123
foo_seconds_sum{a="ccc"} 0 123
foo_seconds_count{a="ccc"} 0 456
foo_seconds_sum{a="ccc"} 0 456

メトリックがインターリーブされた誤った例

# TYPE foo_seconds summary
# UNIT foo_seconds seconds
foo_seconds_count{a="bb"} 0 123
foo_seconds_count{a="ccc"} 0 123
foo_seconds_count{a="bb"} 0 456
foo_seconds_count{a="ccc"} 0 456

MetricPoints がインターリーブされた誤った例

# TYPE foo_seconds summary
# UNIT foo_seconds seconds
foo_seconds_count{a="bb"} 0 123
foo_seconds_count{a="bb"} 0 456
foo_seconds_sum{a="bb"} 0 123
foo_seconds_sum{a="bb"} 0 456

メトリックの種類

ゲージ

ゲージ型の MetricFamily の MetricPoint の値のサンプル MetricName にはサフィックスがあってはなりません。

ラベルなしのメトリックとタイムスタンプなしの MetricPoint を持つ MetricFamily の例

# TYPE foo gauge
foo 17.0

ラベルとタイムスタンプなしの MetricPoints を持つ 2 つのメトリックを持つ MetricFamily の例

# TYPE foo gauge
foo{a="bb"} 17.0
foo{a="ccc"} 17.0

メトリックのない MetricFamily の例

# TYPE foo gauge

ラベルを持つメトリックとタイムスタンプを持つ MetricPoint の例

# TYPE foo gauge
foo{a="b"} 17.0 1520879607.789

ラベルなしのメトリックとタイムスタンプを持つ MetricPoint の例

# TYPE foo gauge
foo 17.0 1520879607.789

ラベルなしのメトリックとタイムスタンプを持つ 2 つの MetricPoint の例

# TYPE foo gauge
foo 17.0 123
foo 18.0 456
カウンター

MetricPoint の合計値サンプルの MetricName には、サフィックス _total が付いていなければなりません。存在する場合、MetricPoint の作成値サンプルの MetricName には、サフィックス _created が付いていなければなりません。

ラベルなしのメトリック、タイムスタンプなし、created なしの MetricPoint の例

# TYPE foo counter
foo_total 17.0

ラベルなしのメトリック、タイムスタンプあり、created なしの MetricPoint の例

# TYPE foo counter
foo_total 17.0 1520879607.789

ラベルなしのメトリック、タイムスタンプなし、created ありの MetricPoint の例

# TYPE foo counter
foo_total 17.0
foo_created 1520430000.123

ラベルなしのメトリック、タイムスタンプあり、created ありの MetricPoint の例

# TYPE foo counter
foo_total 17.0 1520879607.789
foo_created 1520430000.123 1520879607.789

Exemplars は MetricPoint の合計サンプルに添付されても構いません。

状態セット

StateSet 型の MetricFamily の MetricPoint の値のサンプル MetricName にはサフィックスがあってはなりません。

StateSets は MetricPoint の State ごとに 1 つのサンプルを持たなければなりません。各 State のサンプルには、MetricFamily 名をラベル名、State 名をラベル値とするラベルを持たなければなりません。State サンプルの値は、State が true の場合は 1、State が false の場合は 0 でなければなりません。

状態が「a」、「bb」、「ccc」で、bb の値のみが有効で、メトリック名が foo の例

# TYPE foo stateset
foo{foo="a"} 0
foo{foo="bb"} 1
foo{foo="ccc"} 0

メトリック上の「entity」ラベルの例

# TYPE foo stateset
foo{entity="controller",foo="a"} 1.0
foo{entity="controller",foo="bb"} 0.0
foo{entity="controller",foo="ccc"} 0.0
foo{entity="replica",foo="a"} 1.0
foo{entity="replica",foo="bb"} 0.0
foo{entity="replica",foo="ccc"} 1.0
情報

Info 型の MetricFamily の MetricPoint の値のサンプル MetricName には、サフィックス _info が付いていなければなりません。サンプル値は常に 1 でなければなりません。

ラベルなしのメトリック、および「name」と「version」ラベルを持つ 1 つの MetricPoint 値の例

# TYPE foo info
foo_info{name="pretty name",version="8.2.7"} 1

「entity」ラベルを持つメトリックと、「name」と「version」ラベルを持つ 1 つの MetricPoint 値の例

# TYPE foo info
foo_info{entity="controller",name="pretty name",version="8.2.7"} 1.0
foo_info{entity="replica",name="prettier name",version="8.1.9"} 1.0

メトリックラベルと MetricPoint 値ラベルは、任意の順序であっても構いません。

要約

存在する場合、MetricPoint の合計値サンプルの MetricName には、サフィックス _sum が付いていなければなりません。存在する場合、MetricPoint のカウント値サンプルの MetricName には、サフィックス _count が付いていなければなりません。存在する場合、MetricPoint の作成値サンプルの MetricName には、サフィックス _created が付いていなければなりません。存在する場合、MetricPoint の Quantile 値は、ラベル名が「quantile」、ラベル値が測定されたクオンタイルのラベルを使用して測定されたクオンタイルを指定しなければなりません。

ラベルなしのメトリックと、合計、カウント、および作成値を持つ MetricPoint の例

# TYPE foo summary
foo_count 17.0
foo_sum 324789.3
foo_created 1520430000.123

ラベルなしのメトリックと、2 つのクオンタイルを持つ MetricPoint の例

# TYPE foo summary
foo{quantile="0.95"} 123.7
foo{quantile="0.99"} 150.0

Quantile は任意の順序であっても構いません。

ヒストグラム

MetricPoint のバケット値サンプル MetricNames には、サフィックス _bucket が付いていなければなりません。存在する場合、MetricPoint の合計値サンプル MetricName には、サフィックス _sum が付いていなければなりません。存在する場合、MetricPoint の作成値サンプル MetricName には、サフィックス _created が付いていなければなりません。Sum 値が MetricPoint に存在する場合に限り、MetricPoint の +Inf バケット値も、サフィックス「_count」を持つ MetricName のサンプルに表示されなければなりません。

バケットは「le」の数値の昇順でソートされなければならず、「le」ラベルの値は Canonical Numbers のルールに従わなければなりません。

ラベルなしのメトリックと、合計、カウント、作成値、および 12 個のバケットを持つ MetricPoint の例。「le」値の広範で非典型的だが有効な多様性が意図的に示されています

# TYPE foo histogram
foo_bucket{le="0.0"} 0
foo_bucket{le="1e-05"} 0
foo_bucket{le="0.0001"} 5
foo_bucket{le="0.1"} 8
foo_bucket{le="1.0"} 10
foo_bucket{le="10.0"} 11
foo_bucket{le="100000.0"} 11
foo_bucket{le="1e+06"} 15
foo_bucket{le="1e+23"} 16
foo_bucket{le="1.1e+23"} 17
foo_bucket{le="+Inf"} 17
foo_count 17
foo_sum 324789.3
foo_created 1520430000.123
Exemplars

ラベルのないExemplarsは、空のLabelSetを{}として表現しなければなりません。

いくつかの有効なケースを示すExemplarsの例: 「0.01」バケットにはExemplarがありません。0.1バケットにはラベルのないExemplarがあります。1バケットには1つのラベルを持つExemplarがあります。10バケットにはラベルとタイムスタンプを持つExemplarがあります。実際には、すべてのバケットは同じスタイルのExemplarsを持つべきです。

# TYPE foo histogram
foo_bucket{le="0.01"} 0
foo_bucket{le="0.1"} 8 # {} 0.054
foo_bucket{le="1"} 11 # {trace_id="KOO5S4vxi0o"} 0.67
foo_bucket{le="10"} 17 # {trace_id="oHg5SJYRHA0"} 9.8 1520879607.789
foo_bucket{le="+Inf"} 17
foo_count 17
foo_sum 324789.3
foo_created  1520430000.123
ゲージヒストグラム

MetricPointのバケット値サンプルMetricNamesは、サフィックス_bucketを持たなければなりません。存在する場合、MetricPointの合計値サンプルMetricNameは、サフィックス_gsumを持たなければなりません。MetricPointにSum値が存在する場合に限り、MetricPointの+Infバケット値も、サフィックス_gcountを持つMetricNameのサンプルに表示されなければなりません。

バケットは「le」の数値の昇順でソートされなければならず、「le」ラベルの値は Canonical Numbers のルールに従わなければなりません。

ラベルなしのメトリック、バケットにExemplarのないExemplarなしの1つのMetricPoint値の例

# TYPE foo gaugehistogram
foo_bucket{le="0.01"} 20.0
foo_bucket{le="0.1"} 25.0
foo_bucket{le="1"} 34.0
foo_bucket{le="10"} 34.0
foo_bucket{le="+Inf"} 42.0
foo_gcount 42.0
foo_gsum 3289.3
不明

Unknown型のMetricFamilyのMetricPointの値のサンプルメトリック名には、サフィックスがあってはなりません。

ラベルなしのメトリックとタイムスタンプなしのMetricPointの例

# TYPE foo unknown
foo 42.23

Protobuf形式

全体構造

Protobufメッセージはバイナリでエンコードされなければならず、application/openmetrics-protobuf; version=1.0.0をコンテンツタイプとして持たなければなりません。

すべてのペイロードは、OpenMetrics protobufスキーマで定義されている単一のバイナリエンコードされたMetricSetメッセージでなければなりません。

バージョン

protobuf形式は、プロトコルバッファ言語のproto3バージョンに従わなければなりません。

文字列

すべての文字列フィールドはUTF-8でエンコードされなければなりません。

タイムスタンプ

OpenMetrics protobuf スキーマのタイムスタンプ表現は、公開されている google.protobuf.Timestamp [timestamp] メッセージに従わなければなりません。タイムスタンプメッセージは、Unixエポック秒を int64、秒タイムスタンプコンポーネントから前向きにカウントするナノ秒分解能の非負の秒の分数部分を int32 で表現しなければなりません。これは 0 から 999,999,999 (両端を含む) の範囲内でなければなりません。

Protobuf スキーマ

Protobuf スキーマは現在こちらで入手可能です。

PrometheusとエコシステムはOpenMetrics protobufスキーマをサポートしておらず、代わりに同様のio.prometheus.clientフォーマットを使用しています。OpenMetrics 2.0におけるprotobufスキーマの将来についての議論は進行中です。

設計上の考慮事項

範囲

OpenMetrics は、オンラインシステムのテレメトリーを提供することを意図しています。リアルタイム保証を提供するプロトコル上では動作しないため、OpenMetrics 自体はリアルタイム保証を行うことができません。OpenMetrics の遅延およびジッター特性は、基盤となるネットワーク、オペレーティングシステム、CPU などと同様に不正確です。意思決定の基礎として集計が使用されるには十分に正確ですが、個々のイベントを反映するものではありません。

1 時間に数件のリクエストを受信するアプリケーションから、400Gb ネットワークポートでの帯域幅使用量の監視まで、あらゆる規模のシステムがサポートされるべきです。送信されたテレメトリーの集計と分析は、任意の期間にわたって可能であるべきです。

これは、定期的な周期でデータ送信時の状態のスナップショットを転送することを意図しています。

範囲外

インジェスターがどのエクスポージャーが存在するかを発見する方法、およびその逆は、この標準の範囲外であり、したがって定義されていません。

拡張と改善

この OpenMetrics の最初のバージョンは、確立された事実上の標準である Prometheus テキスト形式 0.0.4 に基づいており、主要な構文的または意味的な拡張、あるいはその上での最適化を意図的に追加していません。例えば、ヒストグラムバケットのテキスト表現をよりコンパクトにする試みは行われておらず、基盤となるスタックの圧縮に依存して、その反復的な性質に対処しています。

これは意図的な選択であり、既存のユーザーベースの採用と勢いを活用できるよう、標準が恩恵を受けられるようにするためです。これにより、Prometheus テキスト形式 0.0.4 からの比較的簡単な移行が保証されます。

また、実装が容易な基本的な標準があることも保証します。これは、将来の標準バージョンで拡張される可能性があります。将来の標準バージョンは、常にこの 1.0 バージョンを構文的および意味的にサポートすることを要求する意図です。

監視システムが不当な負担なしに OpenMetrics の公開から有用な情報を取得できるようにしたいと考えています。すべてのメタデータと構造を取り除き、OpenMetrics の公開を順序付けされていないサンプルのセットとして捉えた場合、それはそれ自体で利用可能であるべきです。そのため、スケッチや t-ダイジェストのような、ゲージとカウンターの組み合わせとして表現できない不透明なバイナリ型もありません。これらはカスタムのパースと処理が必要となるためです。

この原則は、標準全体にわたって一貫して適用されています。例えば、MetricFamily の単位は名前に重複して記述されており、単位メタデータを理解しないシステムでも単位を利用できるようにしています。「le」ラベルは、独自の特別な構文を持つのではなく、通常のラベル値であるため、インジェスターはそれらをインジェストするために特別なヒストグラム処理コードを追加する必要がありません。さらに例を挙げると、複合データ型はありません。例えば、緯度/経度の地理位置情報型はありません。これは別々のゲージメトリックで実現できるためです。

単位と基本単位

システム間での一貫性と混乱を避けるため、単位は主にSI基本単位に基づいています。基本単位には、秒、バイト、ジュール、グラム、メートル、比率、ボルト、アンペア、セルシウスが含まれます。単位は適用可能な場所で提供されるべきです。

例えば、すべての期間メトリックを秒で持つことで、特定のメトリックがナノ秒、マイクロ秒、ミリ秒、秒、分、時間、日、週のいずれであるかを推測したり、混在する単位を扱う必要がなくなります。接頭辞のない単位を選択することで、複雑なシステムの緊急動作の結果としてキロミリ秒が生じるような状況を避けることができます。

値は浮動小数点数であってもよいため、標準にはサブ基本単位の精度が組み込まれています。

同様に、ビットとバイトを混在させるのは紛らわしいため、バイトが基本単位として選択されています。理論的にはケルビンの方が優れた基本単位ですが、実際にはほとんどの既存のハードウェアはセルシウスを公開しています。キログラムはSI基本単位ですが、キロ接頭辞は問題があるため、グラムが基本単位として選択されています。

可能な限り基本単位を使用すべきですが、ケルビンは確立された単位であり、色や黒体温度など、セルシウスとケルビンのメトリックを比較する可能性が低いユースケースでは、セルシウスの代わりにケルビンを使用してもかまいません。

比率は基本単位であり、パーセンテージではありません。可能な限り、与えられた分子と分母のゲージまたはカウンターの形式で生のデータが公開されるべきです。これは、インジェスターでの分析と集計において、より優れた数学的特性を持っています。

デシベルは基本単位ではありません。まず、デシはSI接頭辞であり、次にベルは対数であるためです。信号/エネルギー/電力比を公開するには、比率を直接公開する方が良いでしょう。可能であれば、生の電力/エネルギーを公開する方がさらに良いでしょう。浮動小数点指数は、極端な科学用途であっても十分に対応できます。電子ボルト(約1e-19 J)から超新星が放出するエネルギー(約1e44 J)まで、63桁の範囲があり、64ビット浮動小数点数は2000桁以上の範囲をカバーできます。

非基本単位を避けられず、変換が現実的でない場合でも、明確にするために実際の単位をメトリック名に含めるべきです。たとえば、ジュールはエネルギーと電力の両方の基本単位であり、ワットはジュール単位のカウンターとして表現できます。実際には、特定のサードパーティシステムはワットのみを公開する可能性があるため、その場合はワットで表現されたゲージが唯一の現実的な選択肢となるでしょう。

すべてのMetricFamilyが単位を持つわけではありません。たとえば、HTTPリクエストのカウントには単位がありません。厳密には単位はHTTPリクエストですが、その意味ではMetricFamily名全体が単位となります。そこまで極端にすると役に立たないでしょう。下流システムで人間が利用できるように、グラフに適切な軸を設定できる可能性は常に念頭に置かれるべきです。

ステートレス性

OpenMetrics で定義されているワイヤーフォーマットは、公開全体でステートレスです。以前に公開された情報が将来の公開に影響を与えてはなりません。各公開は、公開者の現在の状態の自己完結型スナップショットです。

既存のインジェスターと新規のインジェスターには、同じ自己完結型の公開が提供されなければなりません。

主要な設計選択は、公開者は、最近変更や観測がなかったという理由だけで、メトリックを除外してはならないということです。公開者は、インジェスターが公開を消費する頻度についていかなる仮定もしてはなりません。

時間経過とメトリックの進化による公開

メトリックは、時間経過に伴う進化を分析できる場合に最も有用であるため、公開は時間経過に伴って意味をなす必要があります。したがって、単一の公開だけでは有用かつ有効であるには不十分です。メトリックのセマンティクスに対する一部の変更は、下流のユーザーに障害を引き起こす可能性もあります。

パーサーは通常、以前の結果をキャッシュすることで最適化を行います。したがって、ラベルの公開順序を公開間で変更することは、技術的には破壊的ではないものの、避けるべきです。これにより、公開の単体テストを書きやすくなる傾向もあります。

メトリックとサンプルは、公開から公開へと現れたり消えたりすべきではありません。例えば、カウンターは履歴があって初めて有用です。原則として、与えられたメトリックは、プロセスが開始されてから終了するまで公開に存在すべきです。与えられたプロセスのライフタイム中にMetricFamilyがどのようなMetricを持つか(例えば、レイテンシーヒストグラムのラベル値がHTTPパスであり、実行時にエンドユーザーによって提供されるなど)を事前に知ることはしばしば不可能ですが、カウンターのようなMetricが一度公開されたら、プロセスが終了するまで公開され続けるべきです。カウンターが増加しなくても、現在の値を持つことは変わりません。特定のMetricの公開を停止することが理にかなっているケースもあります。データ欠損のセクションを参照してください。

一般的に、MetricFamilyの型を変更したり、そのMetricからラベルを追加または削除したりすると、インジェスターに対して破壊的となります。

注目すべき例外は、Info MetricPoint の値にラベルを追加しても破壊的ではないことです。これは、新しいラベル値を持つまったく新しい情報メトリックを作成することを強制されることなく、既存の Info MetricFamily に追加情報を追加することが理にかなっている場合に対応するためです。インジェスターシステムは、そのような追加に対して堅牢であることを確認すべきです。

MetricFamily のヘルプを変更しても破壊的ではありません。可能な値の場合、浮動小数点数と整数間の切り替えは破壊的ではありません。状態セットに新しい状態を追加しても破壊的ではありません。メトリック名が変更されない場合、単位メタデータを追加しても破壊的ではありません。

ヒストグラムのバケットは、パフォーマンスの問題を引き起こし、インジェスターを破壊する可能性が高いため、公開ごとに変更すべきではありません。同様に、アプリケーションの整合性のとれたバイナリおよび環境からのすべての公開は、特定のヒストグラムMetricFamilyに対して同じバケットを持つべきです。これにより、インジェスターが異なるバケットに対してヒストグラムマージロジックを実装することなく、すべてのインジェスターによって集計できます。例外として、パフォーマンス特性が新しいソフトウェアリリースによって変化する場合に、破壊的と見なされるバケットへの一時的な手動変更が、有効なトレードオフとなる場合があります。

変更が技術的に破壊的でなくても、コストがかかります。例えば、頻繁な変更はインジェスターのパフォーマンス問題を引き起こす可能性があります。公開ごとに異なるヘルプ文字列は、各ヘルプ値が保存される原因となる可能性があります。整数値と浮動小数点値の間で頻繁に切り替えると、効率的な圧縮が妨げられる可能性があります。

NaN

NaN は OpenMetrics において他の数値と同様の数値であり、通常は最近観測がなかったサマリークオンタイルでのゼロ除算などによって発生します。NaN は OpenMetrics において特別な意味を持たず、特に欠損データまたはその他の不良データのマーカーとして使用してはなりません。

欠損データ

データが存在しなくなる正当なケースがあります。例えば、ファイルシステムがアンマウントされ、それによって空きディスク領域のゲージメトリックが存在しなくなる場合があります。この状況に対する特別なマーカーやシグナルはありません。その後の公開には、このメトリックは含まれません。

公開パフォーマンス

メトリックは、妥当な時間枠で収集できる場合にのみ有用です。公開に数分かかるメトリックは有用とは見なされません。

経験則として、公開は1秒を超えないようにすべきです。

OpenMetricsを介してシリアライズされたレガシーシステムからのメトリックは、時間がかかる場合があります。このため、厳密なパフォーマンスの仮定はできません。

公開は最新の状態であるべきです。例えば、公開リクエストを処理するスレッドは、可能な限りキャッシュをバイパスできる範囲で、キャッシュされた値に依存すべきではありません。

並行処理

高可用性とアドホックアクセスには、複数のインジェスターを持つのが一般的なアプローチです。これをサポートするために、並行公開をサポートしなければなりません。並行システムに関するすべてのBCPに従うべきであり、一般的な落とし穴にはデッドロック、競合状態、および並行公開の進行を妨げる過度に粗い粒度のロックが含まれます。

メトリックの命名と名前空間

メトリックとラベルの名前付けにおいて、理解しやすさ、衝突の回避、簡潔さのバランスを目指しています。名前はアンダースコアで区切られているため、メトリック名は「snake_case」になります。

「http_request_seconds」という例は簡潔ですが、多数のアプリケーション間で衝突し、このメトリックが何を測定しているのかも正確には不明瞭です。例えば、複雑なシステムでは認証ミドルウェアの前または後である可能性があります。

メトリック名は、それらがどのコードから来ているかを示すべきです。したがって、A Company Manufacturing Everythingという会社は、コード内のすべてのメトリックに「acme_」というプレフィックスを付け、レイテンシーを測定するHTTPルーターライブラリがある場合、「acme_http_router_request_seconds」のようなメトリックを持ち、Help文字列でそれが全体的なレイテンシーであることを示すことができます。

すべてのアプリケーションで起こりうるすべての衝突を防ぐことを目的としているわけではありません。そのためには、メトリック名前空間のグローバルレジストリやDNSに基づく非常に長い名前空間のような強硬な解決策が必要になるでしょう。むしろ、軽量で非公式なアプローチを維持することを目的としており、特定のアプリケーションにおいては、構成要素となるライブラリ間での衝突が起こる可能性が非常に低いようにしています。

監視システム全体としての特定のデプロイメントにおいて、同じメトリック名が異なる意味を持つ衝突がまれであることを目指しています。例えば、acme_http_router_request_secondsは、A Company Manufacturing Everythingによって開発された数百の異なるアプリケーションに最終的に含まれる可能性がありますが、これは正常です。Another Corporation Making EntitiesもHTTPルーターでacme_http_router_request_secondsというメトリック名を使用したとしても、それは問題ありません。もし両方の会社のアプリケーションが同じ監視システムによって監視されている場合、衝突は望ましくありませんが、許容されます。なぜなら、どのアプリケーションも両方の名前を公開しようとしておらず、どの単一のターゲットも(誤って)同じメトリック名を2回公開しようとしていないからです。もしあるアプリケーションが、My Example CompanyとMega Exciting Companyの両方のHTTPルーターライブラリを含めたい場合、それは問題となり、メトリック名のいずれかを何らかの方法で変更する必要があります。

結果として、ライブラリが公開される度合いが高いほど、そのようなシナリオが発生するリスクを減らすために、そのメトリック名は適切に名前空間化されるべきです。acme_は社内での使用には悪くない選択ですが、これらの企業は、社外で共有されるコードにはacmeverything_やacorpme_のようなプレフィックスを選択することもできます。

会社または組織による名前空間化の後、上記のようなhttp_routerライブラリのように、必要に応じてライブラリ/サブシステム/アプリケーションによってフラクタルに名前空間化と命名を続けるべきです。目標は、コードベースの全体構造に精通していれば、与えられたメトリック名からそのメトリックの計測がどこにあるかをうまく推測できることです。

非常に有名で一般的な既存のソフトウェアの場合、ソフトウェア自体の名前で十分に区別できるかもしれません。例えば、bind_はDNSソフトウェアにはおそらく十分ですが、isc_bind_の方がより一般的な命名でしょう。

scrape_プレフィックスの付いたメトリックは、個々の公開に関連する情報を添付するためにインジェスターによって使用されるため、アプリケーションによって直接公開すべきではありません。すでに消費され、汎用監視システムを通過したメトリックは、その後の公開でそのようなメトリック名を含めることがあります。公開者が個々の公開に関する情報を提供したい場合は、myexposer_scrape_のようなメトリックプレフィックスを使用できます。一般的な例は、myexposer_scrape_duration_secondsというゲージで、その公開が公開者の視点からどれくらいかかったかを示します。

Prometheusエコシステム内では、すべての実装で一貫性のあるプロセスごとのメトリックのセットが出現しており、process_というプレフィックスが付いています。例えば、開いているファイル数の上限については、MetricFamiles process_open_fdsとprocess_max_fdsのゲージが現在値と最大値の両方を提供します。(これらの名前はレガシーであり、今日定義されるとしたら、process_fds_openとprocess_fds_limitと呼ばれる可能性が高いでしょう。)一般的に、このように同一のセマンティクスを持つ名前を得ることは非常に困難であり、そのため異なる計測は異なる名前を使用すべきです。

メトリック名に冗長性を含めないでください。「metric」、「timer」、「stats」、「counter」、「total」、「float64」などの部分文字列は避けてください。OpenMetrics を介して公開される特定の型(および場合によっては単位)を持つメトリックであるという事実により、このような情報はすでに暗黙的に示されているため、明示的に含めるべきではありません。同じ理由で、メトリックのラベル名をメトリック名に含めるべきではありません。さらに、監視システムによるメトリックのその後の集計によって、そのような情報が不正確になる可能性があります。

計測に含まれるメトリック名に、監視システムの他のレイヤーの実装詳細を含めないでください。例えば、MetricFamily名に、現在たまたまOpenMetricsを介して公開されているという理由だけで「openmetrics」という文字列を含めたり、現在の監視システムがPrometheusであるという理由だけで「prometheus」という文字列を含めたりしてはなりません。

ラベルの名前空間化

ラベル名については、会社やライブラリによる明示的な名前空間化は推奨されません。メトリック名からの名前空間化は、ラベル名の長さの増加を考慮すると十分です。しかし、一般的な衝突を避けるための最小限の注意は推奨されます。

region、zone、cluster、availability_zone、az、datacenter、dc、owner、customer、stage、service、team、job、instance、environment、envなどのラベル名は、汎用監視システムが追加するターゲットを識別するために使用されるラベルと衝突する可能性が非常に高いです。これらを避けるように努め、これらのケースでは最小限の名前空間化が適切である可能性があります。

ラベル名「type」は非常に一般的であり、避けるべきです。例えば、HTTP関連のメトリックの場合、GET、POST、PUTリクエストを区別するなら、「method」の方が良いラベル名でしょう。

HELP、TYPE、UNIT のようなメトリック名に関するメタデータはありますが、ラベル名に関するメタデータはありません。これは、わずかな利益のためにフォーマットを肥大化させることになるためです。帯域外ドキュメントは、公開者がインジェスターにこれを提示する方法の1つです。

メトリック名とラベル

MetricFamily 内で複数の Metrics を使用する場合と、複数の MetricFamily を使用する場合の両方が理にかなっているように見える状況があります。MetricFamily の合計または平均は、常に有用でなくても、意味のあるものであるべきです。例えば、電圧とファン速度を混在させることは意味がありません。

改めて言いますが、OpenMetrics はインジェスターがデータを処理し、集計を実行できるという仮定に基づいて構築されています。

合計値を他のメトリックと一緒に公開することは誤りです。これにより、下流のインジェスターでの集計時に二重カウントが発生するためです。

wrong_metric{label="a"} 1
wrong_metric{label="b"} 6
wrong_metric{label="total"} 7

メトリックのラベルは、一意性を確保するために必要な最小限の数であるべきです。余分なラベルが1つ増えるごとに、ユーザーは下流で扱うべきラベルを決定する際に考慮すべき項目が1つ増えるためです。多くのMetricFamilyに適用できるラベルは、データベース{{normalization}}と同様に_infoメトリックに移動させる候補となります。もしMetricのほぼすべてのユーザーがその追加ラベルを望むと予想される場合、すべてのMetricFamilyに追加する方が良いトレードオフとなるかもしれません。例えば、異なるSQLステートメントに関連するMetricFamilyがあり、一意性が完全なSQLステートメントのハッシュを含むラベルによって提供されている場合、人間が読みやすいようにSQLステートメントの最初の500文字を含む別のラベルを持つことは問題ありません。

経験上、下流のインジェスターは、1つの MetricFamily 内で {result="success"} と {result="failure"} のラベルを使用するよりも、個別の合計と失敗の MetricFamilies を扱う方が簡単だと感じています。また、全二重システムが一般的であり、下流のインジェスターはこれらの値を集計ではなく個別に気にかける可能性が高いため、個別の読み書きおよび送受信の MetricFamilies を公開する方が通常は良いです。

これらすべては、聞こえるほど簡単ではありません。公開と公開されるシステムの両方におけるドメイン固有の専門家による経験とエンジニアリングのトレードオフが必要となる分野であり、適切なバランスを見つける必要があります。メトリックとラベル名の文字

OpenMetricsは、既存の広く採用されているPrometheusのテキスト公開形式と、それを中心に形成されたエコシステムに基づいています。下位互換性は主要な設計目標です。Prometheusのテキスト形式がサポートする文字セットを拡張または縮小することは、その目標に反するでしょう。下位互換性を破ると、ワイヤーフォーマットだけでなく、より広範な影響が生じます。特に、Prometheusエコシステム内で送信されるデータを扱うために作成または採用されたクエリ言語は、これらの正確な文字セットに依存しています。ラベル値は完全なUTF-8をサポートしているため、この形式は多言語メトリックを表現できます。

メタデータの種類

メタデータはさまざまなソースから取得できます。長年にわたり、主なソースが2つ出現しました。それらは機能的には同じであることも多いですが、概念的な違いについて話すと理解に役立ちます。

「ターゲットメタデータ」は、通常、エクスポージャーの外部にあるメタデータです。一般的な例としては、サービスディスカバリー、CMDB、または同様のものから来るデータで、データセンターの地域に関する情報、サービスが特定のデプロイメントの一部であるかどうか、または本番環境かテスト環境かなどが挙げられます。これは、エクスポージャーまたはインジェスターが、このメタデータをキャプチャするすべてのメトリックにラベルを追加することで実現できます。インジェスターを通じてこれを行うことが推奨されます。なぜなら、より柔軟でオーバーヘッドが少ないためです。柔軟性について言えば、ハードウェアメンテナンスチームはマシンがどのサーバーラックに設置されているかを気にするかもしれませんが、その同じマシンを使用するデータベースチームは、それが本番データベースのレプリカ番号2を含んでいることを気にするかもしれません。オーバーヘッドについて言えば、この情報をハードコーディングまたは構成するには、追加の配布パスが必要です。

「公開者メタデータ」は、公開者内部から取得されます。一般的な例としては、ソフトウェアバージョン、コンパイラバージョン、GitコミットSHAなどがあります。

プッシュ型およびプル型システムの両方でのターゲットメタデータのサポート

プッシュベースの消費では、公開者が関連するターゲットメタデータをインジェスターに提供するのが一般的です。プルベースの消費では、プッシュベースのアプローチをとることもできますが、より一般的には、インジェスターはマシンデータベースやサービスディスカバリーシステムなどから事前にターゲットのメタデータを知っており、公開を消費するときにそれをメトリックに関連付けます。

OpenMetrics はステートレスであり、すべてのインジェスターに同じ公開を提供します。これはプッシュ型のアプローチと矛盾します。さらに、プッシュ型のアプローチは、望ましくないメタデータが公開されるため、プル型インジェスターを破壊するでしょう。

一つのアプローチとして、プッシュ型インジェスターがオペレーターの設定に基づいてターゲットメタデータを帯域外で、例えばHTTPヘッダーとして提供することが考えられます。これはプッシュ型インジェスターのターゲットメタデータを転送することになり、この標準によって排除されるものではありませんが、プル型インジェスターが独自のターゲットメタデータを使用すべきであっても、公開者自身が認識しているメタデータにアクセスできることがしばしば有用であるという欠点があります。

推奨される解決策は、このターゲットメタデータを公開の一部として提供することですが、公開全体に影響を与えない方法で提供することです。情報MetricFamiliesは、この目的のために設計されています。公開者は、「target」というInfo MetricFamilyを、メタデータを含むラベルなしの単一のMetricで含めることができます。テキスト形式の例は次のとおりです。

# TYPE target info
# HELP target Target metadata
target_info{env="prod",hostname="myhost",datacenter="sdc",region="europe",owner="frontend"} 1

公開者がこの目的のためにこのメトリックを提供する場合、それは公開の最初に置かれるべきです。これは効率のためであり、ターゲットメタデータのためにそれに依存するインジェスターが、その内容に基づいてビジネスロジックを適用する前に、公開の残りの部分をバッファリングする必要がないようにするためです。

公開者は、特定のインジェスターのために明示的に設定されていない限り、公開からのすべてのメトリックにターゲットメタデータラベルを追加してはなりません。公開者は、MetricFamily名にプレフィックスを付けたり、ターゲットメタデータに基づいてMetricFamily名を変更したりしてはなりません。一般的に、同じラベルが公開のすべてのメトリックに表示されるべきではありませんが、これは緊急動作の結果として発生する稀なケースもあります。同様に、非常に小さな公開では、公開者からのすべてのMetricFamily名がたまたまプレフィックスを共有することもあります。例えば、A Company Manufacturing EverythingによってGo言語で書かれたアプリケーションは、acme_、go_、process_というプレフィックスを持つメトリック、および使用されているサードパーティライブラリからのメトリックプレフィックスを含む可能性が高いでしょう。

公開者は、公開者メタデータを情報MetricFamiliesとして公開することができます。

上記の議論は個々の公開者の文脈におけるものです。汎用監視システムからの公開は、多くの個々のターゲットからのメトリックを含む可能性があり、したがって複数のターゲット情報メトリックを公開する可能性があります。メトリックには、取り込みの一部としてターゲットメタデータがラベルとして既に追加されている可能性があります。メトリック名はターゲットメタデータに基づいて変更されてはなりません。例えば、たとえすべてのメトリックがステージング環境のターゲットから発生したとしても、すべてのメトリックがstaging_というプレフィックスで終わるのは不適切でしょう。

クライアントの計算と派生メトリック

公開者は、あらゆる計算をインジェスターに任せるべきです。注目すべき例外は、残念ながら後方互換性のために必要とされるサマリークオンタイルです。公開は、任意の期間にわたって有用な生の値を対象とすべきです。

例えば、過去5分間のカウンターの平均増加率をゲージで公開すべきではありません。インジェスターに公開を通じて消費されたデータポイント間の増加を計算させる方が、数学的特性が優れており、スクレイプの失敗に対してより堅牢です。

もう一つの例は、ヒストグラム/サマリーの平均イベントサイズです。アプリケーションの開始時またはメトリックの作成時からのカウンターの平均増加率を公開することは、前述の例と同様の問題を抱え、さらに集計を妨げます。

標準偏差もこのカテゴリに属します。二乗和をカウンターとして公開するのが正しいアプローチです。64ビット浮動小数点精度では実際にこれが機能するには不十分であるため、この標準にはヒストグラム値として含まれていませんでした。二乗のため、精度に関しては53ビット仮数の半分しか利用できません。例えば、1秒あたり1万イベントを観測するヒストグラムは、2時間以内に精度を失うでしょう。64ビット整数を使用しても、ナノ秒分解能の整数が通常1秒長のイベントを追跡する場合、19回の観測でオーバーフローするため、浮動小数点以下の桁が失われるため、より良いとは言えません。この設計決定は、128ビット浮動小数点数が一般的になったときに再検討することができます。

もう一つの例として、リクエストの失敗率を公開するのではなく、失敗したリクエストと合計リクエストの個別のカウンターを公開すべきです。

数値型

1秒あたり100万回インクリメントされるカウンターの場合、float64は53ビットの仮数を持っているため、精度を失い始めるまでには1世紀以上かかります。しかし、100Gbpsのネットワークインターフェースのオクテットスループットの精度は、float64では約20時間以内に失われ始める可能性があります。100Gbpsのネットワークインターフェースで数年間にわたって1KBの精度を失うことは実際には問題にならない可能性が高いですが、そのような高スループットの整数データにはint64が選択肢となります。

サマリークオンタイルは float64 でなければなりません。なぜなら、それらは推定値であり、根本的に不正確だからです。

タイムスタンプの公開

OpenMetrics の核となる前提の1つは、公開者が公開しているものの最新のスナップショットを公開することです。

公開されたデータにタイムスタンプを付加するユースケースは限られていますが、これらは非常にまれです。以前にタイムスタンプが付加されていたデータ、特に汎用監視システムに取り込まれたデータにはタイムスタンプが含まれる場合があります。ライブデータや生データにはタイムスタンプが含まれるべきではありません。同じメトリックのMetricPoint値を、公開間で同じタイムスタンプで公開することは有効ですが、基盤となるメトリックが欠損している場合は無効です。

時刻同期は難しい問題であり、データは各システム内で内部的に整合していなければなりません。そのため、インジェスターは、公開者デバイスのシステム時刻に基づかずに、自身の視点から現在のタイムスタンプをデータに付加できるべきです。

タイムスタンプ付きのメトリックでは、公開全体でメトリックがいつ欠落したかを一般的に検出することはできません。しかし、タイムスタンプなしのメトリックでは、インジェスターはメトリックが存在しなくなった公開から自身のタイムスタンプを使用できます。

これらすべては、一般的にMetricPointのタイムスタンプは公開すべきではないということを意味しています。なぜなら、インジェスターが取り込むサンプルに独自のタイムスタンプを適用することは、インジェスターの責任であるべきだからです。

メトリックの最終変更時刻の追跡

my_counter というカウンターが初期化され、後に時刻 123 で 1 増分されたと仮定します。これはテキスト形式で公開する正しい方法です。

# HELP my_counter Good increment example
# TYPE my_counter counter
my_counter_total 1

親セクションに従って、インジェスターは自由に独自のタイムスタンプを添付できるため、これは不正確です。

# HELP my_counter Bad increment example
# TYPE my_counter counter
my_counter_total 1 123

カウンターの最終変更の特定の時刻が重要である場合、これが正しい方法です。

# HELP my_counter Good increment example
# TYPE my_counter counter
my_counter_total 1
# HELP my_counter_last_increment_timestamp_seconds When my_counter was last incremented
# TYPE my_counter_last_increment_timestamp_seconds gauge
# UNIT my_counter_last_increment_timestamp_seconds seconds
my_counter_last_increment_timestamp_seconds 123

最終変更のタイムスタンプを独自のゲージとして値に設定することで、インジェスターは両方のメトリックに独自のタイムスタンプを自由に添付できます。

経験上、絶対タイムスタンプ (ここではエポックが絶対と見なされます) を公開する方が、経過時間、秒数などよりも堅牢であることが示されています。どちらの場合も、これらはゲージとなります。例えば

# TYPE my_boot_time_seconds gauge
# HELP my_boot_time_seconds Boot time of the machine
# UNIT my_boot_time_seconds seconds
my_boot_time_seconds 1256060124

よりも優れています。

# TYPE my_time_since_boot_seconds gauge
# HELP my_time_since_boot_seconds Time elapsed since machine booted
# UNIT my_time_since_boot_seconds seconds
my_time_since_boot_seconds 123

逆に、Exemplarsのタイムスタンプにはベストプラクティスの制約はありません。競合状態やデバイス間の時刻同期が完璧でないため、Exemplarのタイムスタンプがインジェスターのシステムクロックや同じ公開からの他のメトリックと比較してわずかに未来に見える可能性があることに留意してください。同様に、MetricPointの「_created」が、同じMetricPointのExemplarまたはサンプルタイムスタンプよりもわずかに遅れて見える可能性もあります。

ナノ秒から秒までの解像度をサポートする監視システムが一般的に使用されていることに留意してください。したがって、秒の解像度に切り捨てたときに同じタイムスタンプを持つ2つのMetricPointがある場合、インジェスターで重複が発生する可能性があります。この場合、最も早いタイムスタンプを持つMetricPointを使用しなければなりません。

閾値

システムの望ましい境界を公開することは意味があるかもしれませんが、適切な注意が必要です。普遍的に真である値については、そのような閾値のゲージメトリックを発行することは意味があるかもしれません。例えば、データセンターのHVACシステムは、現在の測定値、設定点、およびアラート設定点を知っています。それは、望ましいシステム状態のグローバルに有効かつ正しいビューを持っています。反対の例として、一部の閾値は、規模、展開モデル、または時間とともに変化する可能性があります。特定のCPU使用量は、ある設定では許容されますが、別の設定では望ましくない場合があります。値の集計は、許容値をさらに変更する可能性があります。そのようなシステムでは、境界を公開することは逆効果になる可能性があります。

例えば、キューの最大サイズは、現在キューに入っているアイテムの数とともに公開されることがあります。

# HELP acme_notifications_queue_capacity The capacity of the notifications queue.
# TYPE acme_notifications_queue_capacity gauge
acme_notifications_queue_capacity 10000
# HELP acme_notifications_queue_length The number of notifications in the queue.
# TYPE acme_notifications_queue_length gauge
acme_notifications_queue_length 42

サイズ制限

この標準は、単一の公開によって公開されるサンプルの数、存在する可能性のあるラベルの数、状態セットが持つ可能性のある状態の数、情報値のラベルの数、またはメトリック名/ラベル名/ラベル値/ヘルプの文字制限について、特定の制限を規定していません。

特定の制限は、合理的な使用ケースを妨げるリスクがあります。例えば、特定の公開では適切な数のラベルがある場合でも、汎用監視システムを通過した後、いくつかのターゲットラベルが追加されて制限を超えてしまう可能性があります。このような数値の特定の制限は、汎用監視システムにとっての実際のコストを捕捉することにもなりません。したがって、これらのガイドラインは、公開者とインジェスターが何が合理的であるかを理解するのに役立つものです。

一方、ある次元において過度に大きな公開は、公開されるメトリックの恩恵と比較して、重大なパフォーマンス問題を引き起こす可能性があります。したがって、単一の公開のサイズに関する何らかのガイドラインが有用でしょう。

インジェスターは、特に攻撃や停止を防ぐために、自ら制限を課すことを選択するかもしれません。しかし、インジェスターは合理的な使用事例を考慮し、それらに不均衡な影響を与えないように努める必要があります。単一の値/メトリック/公開がそのような制限を超えた場合、その公開全体を拒否しなければなりません。

一般的に、汎用監視システムにおける時系列データの取り込みパフォーマンスに影響を与える要素は3つあります。それは、ユニークな時系列の数、それらの時系列における時間経過にわたるサンプルの数、そしてメトリック名、ラベル名、ラベル値、HELPのようなユニークな文字列の数です。インジェスターは取り込み頻度を制御できるため、その側面はこれ以上考慮する必要はありません。

ユニークな時系列の数は、おおよそテキスト形式のコメント以外の行数に相当します。2020年現在、合計1000万の時系列は大量と見なされ、単一インスタンスのインジェスターの上限のおおよそのオーダーです。単一の公開は、適切な注意を払わずに1万の時系列を超えるべきではありません。一般的な考慮事項の1つは水平スケーリングです。インスタンス数を1桁または2桁増やすとどうなるでしょうか?30年前には、単一のデプロイメントで千台のトップオブラック(ToR)スイッチを想像することは困難だったでしょう。ターゲットがシングルトン(例えば、クラスター全体に関連するメトリックを公開している場合)であれば、数十万の時系列が妥当かもしれません。重要なのは、ユニークなMetricFamiliesの数や個々のラベル/バケット/状態セットのカーディナリティではなく、時系列の合計オーダーです。1つのメトリックを持つ1000個のゲージは、1000個のメトリックを持つ1つのゲージと同じくらいコストがかかります。

もし特定の種類のターゲットがすべて同じ時系列セットを公開しているのであれば、それぞれの追加ターゲットの文字列は、ほとんどの合理的にモダンな監視システムにとって増分コストになりません。しかし、もし各ターゲットがユニークな文字列を持っている場合、そのようなコストが発生します。極端な例を挙げると、多くのターゲットが使用する単一の1万文字のメトリック名それ自体は、実際には問題になる可能性は非常に低いでしょう。それどころか、1000個のターゲットがそれぞれユニークな36文字のUUIDを公開することは、モダンなアプローチを仮定すると、その単一の1万文字のメトリック名よりも文字列の保存コストが3倍以上かかります。さらに、これらの文字列が時間とともに変化する場合、古い文字列は少なくとも一定期間保存される必要があり、追加のコストが発生します。前段落の1000万時系列を仮定すると、1時間あたり100MBのユニークな文字列は、イベントロギングのようなユースケースを示唆しており、メトリック時系列ではないかもしれません。

トレーシングスパンデータやその他のイベントログに機能が悪用されるのを防ぐため、Exemplarの長さに128UTF-8文字の厳しい制限があります。

セキュリティ

実装者は、認証、認可、およびアカウンティングを提供することを選択してもよいですが、その場合は、OpenMetrics の外部で処理すべきです。

すべての公開者実装は、TLS 1.2以降でHTTPトラフィックを保護できるべきです。公開者実装が暗号化をサポートしていない場合、オペレーターは可能な限りリバースプロキシ、ファイアウォール、および/またはACLを使用すべきです。

メトリックの公開は、エンドユーザーに公開される本番サービスとは独立しているべきです。したがって、OpenMetrics を使用する公開サービスに対して、TCP/80、TCP/443、TCP/8080、TCP/8443 などのポートに /metrics エンドポイントを持つことは、一般的に推奨されません。

IANA

Prometheus公開形式のほとんどの実装は現在、{{PrometheusPorts}}の非公式レジストリからのIANA未登録ポートを使用していますが、OpenMetricsは明確に定義されたポートに存在します。

クライアントがデータを公開するためにIANAによって割り当てられたポートは、<歴史的整合性のために9099が要求されています>。

複数のメトリックエンドポイントが共通のIPアドレスとポートで到達可能である必要がある場合、オペレーターは、エクスポージャーとlocalhostアドレスを介して通信するリバースプロキシの使用を検討するかもしれません。多重化を容易にするために、エンドポイントはそのパスに独自の名前を持つべきです。つまり、/node_exporter/metricsです。公開は、「プッシュベースとプルベースの両方のシステムでターゲットメタデータをサポートする」で説明されている理由と、単一障害点なしで独立した取り込みを可能にするために、1つの公開に結合すべきではありません。

OpenMetrics は、application/openmetrics-text および application/openmetrics-proto の 2 つの MIME タイプを登録したいと考えています。

このページの内容