> Source: https://www.ymotongpoo.com/works/oteps/metrics/otep-0080/


# OTEP-0080: メトリクスAPIのGauge計装器を削除する

[Observer計装器](./0072-metric-observer.md)は、メトリクスのGauge計装器と意味的に同一ですが、コールバック経由で報告される点だけが異なり、同期的なAPI呼び出しは行いません。
実装の経験から、Gauge計装器は考え方が難しいことがわかっています。
これは、「最終値」アグリゲーターの意味論が、状態管理、つまりSDKが過去の値を記憶しておく能力について疑問を投げかけるからです。
Observer計装器では、収集期間ごとに1回だけ報告されるため、アグリゲーターにおける「すべての値」について考えるのが容易になり、こうした懸念のいくつかを回避できます。

## 動機 {#motivation}

Observer計装器は、既存のGauge計装器と比べて、最終値を集約したデータの集合に対して、明確に定義された合計値・平均値のアグリゲーションを計算する能力を向上させます。
Observer計装器のデータを使えば、現在のすべての値の合計や、平均値を定義するために必要な、明確に異なる値の数についての問いを簡単に立てることができます。

同期的なGauge計装器で同じことを行うには、SDKが単一の収集ウィンドウを超えて状態を保持する必要が生じる可能性があり、メモリ管理が複雑になります。
SDKは、クエリの評価間隔にわたって、明確に異なるすべてのラベルの集合についての状態を保持する必要があります。

問題は、SDKがgaugeの値をどれくらいの期間覚えておくべきか、ということです。
Observer計装器では、観測がアプリケーションではなく収集と同期されるため、この複雑さは生じません。

Gauge計装器とは異なり、Observer計装器は単一の収集期間についての現在のすべての値の集合を自然に定義します。
そのため、クエリの評価間隔に言及することなく、また、暗黙のうちに追加の状態管理を必要とすることなく、合計値・平均値のアグリゲーションが可能になります。

## 解説 {#explanation}

Gauge計装器のもっとも重要な特徴は、その測定間隔が任意であり、`Set()` への明示的で同期的な呼び出しを通じてアプリケーションによって制御される点です。
これは同期的な文脈で現在の値を報告するために使われます。
つまり、そのメトリクスイベントは、なんらかの「リクエスト」によって決定されるラベルの集合と関連付けられます。

本提案は、Gauge値を同期的に報告する処理は常に、他の3種類の計装器のいずれかを使って実現できると推奨します。

仕様では _すでに_ 、計装器が自然に合計されるべき値を報告するのであれば、そもそもCounterを使うべきだと推奨されていました。
これらは報告された時点では実際には「現在の」値ではなく、合計に対する現在の寄与分です。
この場合は引き続きCounterを推奨します。

gaugeが、明確に異なるラベルの集合にわたって最終値を自然に平均するべき値を報告するのであれば、Measure計装器を使ってください。
その計装器を最終値のアグリゲーションを行うように設定してください。
最終値のアグリゲーションはMeasure計装器のデフォルトではないため、これは標準的でなく、追加の設定が必要になります。

gaugeが、明確に異なるラベルの集合にわたって最終値を自然に合計するべき値を報告するのであれば、Observer計装器を使ってください。
現在のエンティティの集合（たとえば、シャードやアクティブユーザーなど）は、合計されるべき最終値に寄与します。
これらはCounter計装器とは異なります。なぜなら、私たちが関心を持っているのは時間にわたる合計ではなく、明確に異なるインスタンスにわたる合計だからです。

### 例: リクエストごとのCPU使用率を報告する {#example-reporting-per-request-cpu-usage}

CPU使用率のように、時間にわたって自然に合計される量を報告するにはcounterを使ってください。

### 例: シャードごとのメモリ保有量を報告する {#example-reporting-per-shard-memory-holdings}

広く使われているライブラリによって、変動する量のメモリを保有する現在のシャードが多数存在するとします。
Observer計装器を使って、シャードごとの現在の割り当て量を観測してください。
これらは、たとえばクラスタ全体でのシャードごとのメモリ保有量を計算するために、複数のホストにわたって集約できます。

複数の期間にわたるメモリ保有量の合計を計算することには意味がありません。これらは加算可能な量ではないからです。
一方、ホストにわたって最終値を合計することには意味があります。

### 例: リクエストごとの最終的な口座残高を報告する {#example-reporting-a-per-request-finishing-account-balance}

銀行口座の残高のように、上昇したり下降したりする数値があるとします。
これはすべてのトランザクションの完了時に `Set()` されていました。
これをMeasure計装器に置き換え、最終値を `Record()` してください。

同様のケースとして、リクエストに関連付けられたCPU負荷、特定の温度、ファンの回転速度、高度の測定値の報告が挙げられます。

## 内部の詳細 {#internal-details}

Gauge計装器は、Observer計装器が追加されるのと同時に仕様から削除されます。
これにより、多くの場合、本文中でObserver計装器がGauge計装器を単純に置き換えるだけになるため、移行が容易になります。

## トレードオフと緩和策 {#trade-offs-and-mitigations}

Gauge計装器を削除することによってユーザーが失うものはそれほど多くありません。

Observer計装器が自然な選択であるにもかかわらず、Observerのコールバックを実行するためにメトリクスSDKによって割り込まれることが望ましくない状況もあり得ます。
Observerの意味論が正しい（CounterでもMeasureでもない）ものの、同期的なAPIの方が受け入れやすいという状況は、非常にまれであると考えられます。

このようなまれなケースに対処するために、次の2つの可能性があります。

1. Observer計装器に裏打ちされたGauge Set計装器を実装します。
Gauge Setの役割は、現在のラベルの集合（たとえば、明示的に管理される、あるいは時間制限による）とその最終値を保持し、収集間隔ごとにObserverによって報告できるようにすることです。
2. アプリケーションがSDKと収集間隔について同期できるようにする、アプリケーション固有のメトリクス収集APIを実装します。
たとえば、アプリケーションがObserver計装器の観測を同期的に報告するBEGINとENDを行えるようにする、トランザクション的なAPIです。

## 先行技術と代替技術 {#prior-art-and-alternatives}

既存の多くのメトリクスライブラリは、同期的なGaugeライクな計装器と非同期的なGaugeライクな計装器の両方をサポートしています。

[Spec issue 412](https://github.com/open-telemetry/opentelemetry-specification/issues/412)での最初の議論を参照してください。

