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


# OTEP-0119: システム／ランタイムメトリクス計装器の標準名

本OTEPは、OpenTelemetryにおける一般的なシステム／ランタイムメトリクス計装器のための、標準的な名前、ラベル、セマンティック規約の集合を提案します。
ここで提案する計装器名は、サポートされるオペレーティングシステムおよびランタイム環境を通じて共通のものです。
また、特定のOSやランタイムに固有ではないものも含めて、システム／ランタイムメトリクスのための一般的なセマンティック規約も含まれています。

本OTEPは、主にOpenTelemetry Collectorの[Host Metrics Receiver](https://github.com/open-telemetry/opentelemetry-collector/tree/1ad767e62f3dff6f62f32c7360b6fefe0fbf32ff/receiver/hostmetricsreceiver)における既存の実装に基づいています。
提案する名前は、システム／ランタイムメトリクスを曖昧さなく、簡単に発見できるようにすることを目指しています。
追加の動機については、[OTEP #108](https://github.com/open-telemetry/oteps/pull/108/files)を参照してください。

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

メトリクス計装器に名前を付ける際には、発見のしやすさと曖昧さとの間にトレードオフがあります。
たとえば、`system.cpu.load_average` というメトリクスは非常に発見しやすいものですが、このメトリクスの意味は曖昧です。
[Load average](https://en.wikipedia.org/wiki/Load_(computing))はUNIXではきちんと定義されていますが、Windowsでは標準的なメトリクスではありません。
発見のしやすさは重要ですが、名前は曖昧であってはなりません。

## 先行技術 {#prior-art}

OpenTelemetryには、システムおよび／またはランタイムメトリクスを収集するいくつかの実装がすでに存在します。

- **[OTEP #108](https://github.com/open-telemetry/oteps/pull/108/files)**
  * メトリクス計装器の命名に関するハイレベルなガイドラインを提供しています。
  * システムメトリクスに関する[以前の提案](https://docs.google.com/spreadsheets/d/1WlStcUe2eQoN1y_UF7TOd6Sw7aV_U0lFcLk5kBNxPsY/edit#gid=0)から生まれたものでしょうか。
- **Collector**
  * [Host Metrics Receiver](https://github.com/open-telemetry/opentelemetry-collector/tree/1ad767e62f3dff6f62f32c7360b6fefe0fbf32ff/receiver/hostmetricsreceiver)は、エージェントとして実行された際にホストシステムに関するメトリクスを生成します。
  * 現時点でもっとも包括的な実装です。
  * CPU、メモリ、スワップ、ディスク、ファイルシステム、ネットワーク、ロードに関するシステムメトリクスを収集します。
  * CPU、メモリ、ディスクI/Oに関するプロセスメトリクスを収集する計画があります。
  * 個々のメトリクスを定義するのではなく、ラベルをうまく活用しています。
  * [収集されるメトリクスの概要](https://docs.google.com/spreadsheets/d/11qSmzD9e7PnzaJPYRFdkkKbjTLrAKmvyQpjBjpJsR2s/edit)。

- **Go**
  * Goには、GC、ヒープ使用量、ゴルーチンに関するランタイムメトリクスを収集する[計装](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/runtime)があります。
  * このパッケージはラベル付きでメトリクスをエクスポートせず、代わりに個々のメトリクスをエクスポートします。
  * [収集されるメトリクスの概要](https://docs.google.com/spreadsheets/d/1r50cC9ass0A8SZIg2ZpLdvZf6HmQJsUSXFOu-rl4yaY/edit#gid=0)。
- **Python**
  * Pythonには、一部のシステムおよびランタイムメトリクスを収集する[計装](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-system-metrics)があります。
  * システムのCPU、メモリ、ネットワークメトリクスを収集します。
  * ランタイムのCPU、メモリ、GCメトリクスを収集します。
  * Collectorと同様に、ラベルを活用しています。
  * [収集されるメトリクスの概要](https://docs.google.com/spreadsheets/d/1r50cC9ass0A8SZIg2ZpLdvZf6HmQJsUSXFOu-rl4yaY/edit#gid=0)。

## セマンティック規約 {#semantic-conventions}

以下のセマンティック規約は、命名の一貫性を保つことを目的としています。
これらの規約は、考えられるすべてのメトリクスを網羅しているわけではありませんが、本提案のほとんどのケースに対するガイドラインを提供します。

- **usage** - 既知の合計量のうち使用された量を測定する計装器は、`entity.usage` と呼ぶべきです。
  たとえば、使用済みのディスク容量には `system.filesystem.usage` を使います。
  無制限のリソースが消費された量を測定するものは、**usage** とは区別されます。
  これは時間やデータ量などが該当します。
- **utilization** - 使用率の *値の比率*（パーセンテージのようなものですが、`[0, 1]` の範囲になります）を測定する計装器は、`entity.utilization` と呼ぶべきです。
  たとえば、使用中のメモリの比率には `system.memory.utilization` を使います。
- **time** - 経過時間を測定する計装器は、`entity.time` と呼ぶべきです。
  たとえば、`system.cpu.time` は、idle、userなどのさまざまな値を取る `state` ラベルとともに使われます。
- **io** - 双方向のデータフローを測定する計装器は、`entity.io` と呼ばれ、方向を表すラベルを持つべきです。
  たとえば、`system.network.io` が該当します。
- 上記の説明に当てはまらないその他の計装器は、より自由に命名してかまいません。
  たとえば、`system.swap.page_faults` や `system.network.packets` が該当します。
  単位は計装器の作成時に含まれるため、名前の中で指定する必要はありませんが、曖昧さがある場合には追加してもかまいません。

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

システム／ランタイムメトリクスを計装するライブラリでは、以下の標準的なメトリクス計装器を使用するべきです（以下の表をまとめた[スプレッドシート](https://docs.google.com/spreadsheets/d/1r50cC9ass0A8SZIg2ZpLdvZf6HmQJsUSXFOu-rl4yaY/edit#gid=973941697)はこちらです）。

以下の表において、単位が `1` であるものは、常に `[0, 1]` の範囲を取る比率の値を指します。
何かの整数カウントを測定する計装器は、`packets`、`errors`、`faults` などのセマンティックな単位を使用します。

### システム標準メトリクス - `system.` {#standard-system-metrics---system}

---

#### `system.cpu.` {#systemcpu}

**説明:** システムレベルのプロセッサメトリクスです。

|名前                  |単位   |計装器の種類     |値の型   |ラベルキー|ラベル値                          |
|----------------------|-------|-----------------|----------|---------|-----------------------------------|
|system.cpu.time       |seconds|SumObserver      |Double    |state    |idle, user, system, interrupt, etc.|
|                      |       |                 |          |CPU      |1 - #cores                         |
|system.cpu.utilization|1      |UpDownSumObserver|Double    |state    |idle, user, system, interrupt, etc.|
|                      |       |                 |          |CPU      |1 - #cores                         |

#### `system.memory.` {#systemmemory}

**説明:** システムレベルのメモリメトリクスです。

|名前                     |単位 |計装器の種類     |値の型   |ラベルキー|ラベル値                |
|-------------------------|-----|-----------------|----------|---------|------------------------|
|system.memory.usage      |bytes|UpDownSumObserver|Int64     |state    |used, free, cached, etc.|
|system.memory.utilization|1    |UpDownSumObserver|Double    |state    |used, free, cached, etc.|

#### `system.swap.` {#systemswap}

**説明:** システムレベルのスワップ／ページングメトリクスです。

|名前                        |単位      |計装器の種類     |値の型   |ラベルキー|ラベル値    |
|----------------------------|----------|-----------------|----------|---------|------------|
|system.swap.usage           |pages     |UpDownSumObserver|Int64     |state    |used, free  |
|system.swap.utilization     |1         |UpDownSumObserver|Double    |state    |used, free  |
|system.swap.page\_faults    |faults    |SumObserver      |Int64     |type     |major, minor|
|system.swap.page\_operations|operations|SumObserver      |Int64     |type     |major, minor|
|                            |          |                 |          |direction|in, out     |

#### `system.disk.` {#systemdisk}

**説明:** システムレベルのディスクパフォーマンスメトリクスです。

|名前                        |単位      |計装器の種類|値の型   |ラベルキー|ラベル値    |
|----------------------------|----------|---------------|----------|---------|------------|
|system.disk.io<!--notlink-->|bytes     |SumObserver    |Int64     |device   |(identifier)|
|                            |          |               |          |direction|read, write |
|system.disk.operations      |operations|SumObserver    |Int64     |device   |(identifier)|
|                            |          |               |          |direction|read, write |
|system.disk.time            |seconds   |SumObserver    |Double    |device   |(identifier)|
|                            |          |               |          |direction|read, write |
|system.disk.merged          |1         |SumObserver    |Int64     |device   |(identifier)|
|                            |          |               |          |direction|read, write |

#### `system.filesystem.` {#systemfilesystem}

**説明:** システムレベルのファイルシステムメトリクスです。

|名前                         |単位 |計装器の種類     |値の型   |ラベルキー|ラベル値            |
|-----------------------------|-----|-----------------|----------|---------|--------------------|
|system.filesystem.usage      |bytes|UpDownSumObserver|Int64     |device   |(identifier)        |
|                             |     |                 |          |state    |used, free, reserved|
|system.filesystem.utilization|1    |UpDownSumObserver|Double    |device   |(identifier)        |
|                             |     |                 |          |state    |used, free, reserved|

#### `system.network.` {#systemnetwork}

**説明:** システムレベルのネットワークメトリクスです。

|名前                           |単位       |計装器の種類     |値の型   |ラベルキー|ラベル値                                                                                       |
|-------------------------------|-----------|-----------------|----------|---------|----------------------------------------------------------------------------------------------|
|system.network.dropped\_packets|packets    |SumObserver      |Int64     |device   |(identifier)                                                                                  |
|                               |           |                 |          |direction|transmit, receive                                                                             |
|system.network.packets         |packets    |SumObserver      |Int64     |device   |(identifier)                                                                                  |
|                               |           |                 |          |direction|transmit, receive                                                                             |
|system.network.errors          |errors     |SumObserver      |Int64     |device   |(identifier)                                                                                  |
|                               |           |                 |          |direction|transmit, receive                                                                             |
|system<!--notlink-->.network.io|bytes      |SumObserver      |Int64     |device   |(identifier)                                                                                  |
|                               |           |                 |          |direction|transmit, receive                                                                             |
|system.network.connections     |connections|UpDownSumObserver|Int64     |device   |(identifier)                                                                                  |
|                               |           |                 |          |protocol |tcp, udp, [others](https://en.wikipedia.org/wiki/Transport_layer#Protocols)                   |
|                               |           |                 |          |state    |[e.g. for tcp](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation)|

#### OS固有システムメトリクス - `system.{os}.` {#os-specific-system-metrics---systemos}

特定のオペレーティングシステムに固有のシステムレベルメトリクスの計装器名には、`system.{os}.` というプレフィックスを付け、CPU、メモリ、ネットワークなどの各エンティティについて、上記に挙げた階層構造に従うべきです。
たとえば、Linuxのマージされたディスク操作の数をカウントする計装器（[こちら](https://unix.stackexchange.com/questions/462704/iostat-what-is-exactly-the-concept-of-merge)と[こちら](https://man7.org/linux/man-pages/man1/iostat.1.html)を参照）は、上で提案した `disk` という名前を再利用して、`system.linux.disk.merged_operations` と名付けることができます。

### ランタイム標準メトリクス - `runtime.` {#standard-runtime-metrics---runtime}

---

ランタイム環境は、用語、実装、そして特定のメトリクスに対する相対的な値において、大きく異なります。
たとえば、GoとPythonはどちらもガベージコレクションを行う言語ですが、2つのランタイム間でヒープ使用量を直接比較することには意味がありません。
このため、本OTEPは、トップレベルの標準ランタイムメトリクス計装器を一切提案しません。
追加の議論については、[OTEP #108](https://github.com/open-telemetry/oteps/pull/108/files)を参照してください。

#### ランタイム固有メトリクス - `runtime.{environment}.` {#runtime-specific-metrics---runtimeenvironment}

特定のランタイム環境に固有のランタイムレベルメトリクスには、`runtime.{environment}.` というプレフィックスを付け、[セマンティック規約](#semantic-conventions)に概説されたセマンティック規約に従うべきです。
たとえば、Goのランタイムメトリクスは `runtime.go.` をプレフィックスとして使用します。

プログラミング言語の中には、実装が大きく異なる複数のランタイム環境を持つものがあります。
たとえば、[Pythonには多くの実装があります](https://www.python.org/download/alternatives)。
このような言語では、曖昧さを避けるために、`runtime.cpython.` や `runtime.pypy.` のような、特定の `environment` プレフィックスを使用することを検討してください。

## 未解決の疑問 {#open-questions}

- 個々のランタイムは、仕様の中に独自の命名規約を持つべきでしょうか。
- OS（またはOSファミリー）に固有の計装器を、曖昧さがない限りトップレベルのプレフィックスの下に含めてもよいのでしょうか。
  たとえば、inode関連の計装器を命名する場合、以下のどれが好ましいでしょうか。
  1. トップレベル: `system.filesystem.inodes.*`
  2. UNIXファミリーレベル: `system.unix.filesystem.inodes.*`
  3. UNIX系OSごとに個別: `system.linux.filesystem.inodes.*`、`system.freebsd.filesystem.inodes.*`、`system.netbsd.filesystem.inodes.*` など

