# 概要

> Source: https://www.ymotongpoo.com/works/otel-specs-ja/spec/overview/


このドキュメントはOpenTelemetryプロジェクトの概要を示し、重要な基本用語を定義します。

その他の用語定義は[用語集](../glossary/)にあります。

## OpenTelemetryクライアントのアーキテクチャ

![Cross cutting concerns](https://raw.githubusercontent.com/open-telemetry/opentelemetry-specification/v1.60.0/internal/img/architecture.png)

もっとも高いアーキテクチャレベルでは、OpenTelemetryクライアントは[**シグナル**](../glossary/#signals)を軸に構成されています。各シグナルは特化した形のオブザーバビリティを提供します。例えば、トレーシング、メトリクス、バゲージは3つの独立したシグナルです。シグナルは**コンテキスト伝搬**という共通のサブシステムを共有しますが、それぞれ独立して機能します。

各シグナルは、ソフトウェアが自身を記述する仕組みを提供します。Webフレームワークやデータベースクライアントといったコードベースは、自身を記述するために各種のシグナルに依存します。そうしてOpenTelemetryの計装コードは、そのコードベース内の他のコードに混ぜ込まれます。これによってOpenTelemetryは[**cross-cutting concern**](https://en.wikipedia.org/wiki/Cross-cutting_concern)（横断的関心事）になります。cross-cutting concernとは、価値を提供するために多くの他のソフトウェアに混ぜ込まれるソフトウェアの一片です。cross-cutting concernは、その性質上、関心の分離というコアな設計原則に反します。そのため、OpenTelemetryクライアントの設計では、これらの横断的関心事のAPIに依存するコードベースに問題を生じさせないよう、特別な配慮と注意が必要です。

OpenTelemetryクライアントは、各シグナルのうちcross-cutting concernとしてインポートしなければならない部分と、独立して管理できる部分とを分離するように設計されています。また、OpenTelemetryクライアントは拡張可能なフレームワークとしても設計されています。これらの目標を達成するため、各シグナルはAPI、SDK、セマンティック規約、Contribという4種類のパッケージから構成されます。

### API

APIパッケージは、計装に使われるcross-cuttingな公開インターフェースから構成されます。サードパーティのライブラリやアプリケーションコードにインポートされるOpenTelemetryクライアントの部分は、すべてAPIの一部とみなされます。

### SDK

SDKは、OpenTelemetryプロジェクトが提供するAPIの実装です。アプリケーション内では、SDKは[アプリケーション所有者](../glossary/#application-owner)によってインストールおよび管理されます。SDKには、cross-cutting concernではないためAPIパッケージの一部とはみなされない追加の公開インターフェースが含まれることに注意してください。これらの公開インターフェースは[コンストラクタ](../glossary/#constructors)と[プラグインインターフェース](../glossary/#sdk-plugins)として定義されます。アプリケーション所有者はSDKコンストラクタを使い、[プラグイン作者](../glossary/#plugin-author)はSDKプラグインインターフェースを使います。[計装作者](../glossary/#instrumentation-author)は、いかなる種類のSDKパッケージも直接参照してはならず（MUST NOT）、APIのみを参照するものとします。

### セマンティック規約

**セマンティック規約**は、アプリケーションが使用する一般的な概念、プロトコル、操作を記述するキーと値を定義します。

セマンティック規約は現在、独自のリポジトリに置かれています。
[https://github.com/open-telemetry/semantic-conventions](https://github.com/open-telemetry/semantic-conventions)

CollectorとクライアントライブラリはいずれもSHOULD、セマンティック規約のキーと列挙値を定数（あるいは言語に応じた等価な形式）へ自動生成するものとします。生成された値は、セマンティック規約が安定するまで、安定版パッケージで配布すべきではありません。[YAML](https://github.com/open-telemetry/semantic-conventions/tree/main/model)ファイルは生成の際の信頼できる情報源としてMUST使用されるものとします。各言語の実装はSHOULD、[コードジェネレーター](https://github.com/open-telemetry/weaver)に言語固有のサポートを提供するものとします。

さらに、仕様書が要求する属性は[こちら](/works/otel-specs-ja/spec/semantic-conventions/)に一覧化されます。

### コアパッケージ

**コアパッケージ**は追加のパッケージ種別ではありません。この用語は、これらのカテゴリ（**API**パッケージ、**SDK**パッケージ、そしてエクスポーターやプロパゲーターなどのプラグインパッケージ）にわたって仕様が定義するコンポーネントを実装するOpenTelemetryクライアントパッケージを指します。

コアパッケージはOpenTelemetryのSIGによって保守され、オプションであるContribパッケージとは区別されます。この用語は仕様が定義するデリバラブルを表すものであり、言語実装ごとの特定のリポジトリ、パッケージ、モジュール、アーティファクト、リリースバンドルのレイアウトを規定するものではありません。

### Contribパッケージ

OpenTelemetryプロジェクトは、最新のWebサービスをオブザーブする上で重要と判断された人気のOSSプロジェクトとの統合を保守しています。API統合の例としては、Webフレームワーク、データベースクライアント、メッセージキュー向けの計装があります。SDK統合の例としては、人気の分析ツールやテレメトリーストレージシステムへのテレメトリーのエクスポートを行うプラグインがあります。

一部のプラグイン、例えばOTLPエクスポーターやTraceContextプロパゲーターは、OpenTelemetryの仕様によって定義されていることに注意してください。これらのプラグインは**コアパッケージ**と呼ばれます。

SDKとは別にオプションで提供されるプラグインや計装パッケージは**Contrib**パッケージと呼ばれます。**API Contrib**はAPIのみに依存するパッケージを指し、**SDK Contrib**はSDKにも依存するパッケージを指します。

Contribという用語は、OpenTelemetryプロジェクトが保守するプラグインと計装の集合のみを指し、他所でホストされるサードパーティのプラグインを指すものではありません。

### バージョニングと安定性

OpenTelemetryは安定性と後方互換性を重視しています。詳細は[バージョニングと安定性のガイド](../versioning-and-stability/)を参照してください。

## トレーシングシグナル

分散トレースとは、単一の論理的な操作の結果として発生し、アプリケーションの様々なコンポーネントを横断して集約された、イベントの集合です。分散トレースには、プロセス、ネットワーク、セキュリティの境界を越えるイベントが含まれます。分散トレースは、あるサイトで何かの操作を開始するためにボタンが押されたときに開始される場合があります。この例では、トレースはこのボタン押下によって開始された一連のリクエストを処理する、下流のサービス間で行われた呼び出しを表します。

### トレース

OpenTelemetryにおける**トレース**は、その**スパン**によって暗黙的に定義されます。特に、**トレース**は**スパン**の有向非巡回グラフ（DAG）と考えることができ、**スパン**間のエッジは親子関係として定義されます。

例えば、以下は6つの**スパン**からなる**トレース**の例です。

```
Causal relationships between Spans in a single Trace

        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `child` of Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F]
```

**トレース**は、下図のように時間軸で可視化するとわかりやすい場合もあります。

```
Temporal relationships between Spans in a single Trace

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··········································]
      [Span D······································]
    [Span C····················································]
         [Span E·······]        [Span F··]
```

### スパン

スパンは、トランザクション内の1つの操作を表します。各**スパン**は以下の状態をカプセル化します。

- 操作名
- 開始と終了のタイムスタンプ
- [**属性**](/works/otel-specs-ja/spec/common/#attribute): キーと値のペアのリスト
- ゼロ個以上の**イベント**の集合。各イベント自体は（タイムスタンプ、名前、[**属性**](/works/otel-specs-ja/spec/common/#attribute)）のタプルです。名前は文字列でなければなりません。
- 親の**スパン**識別子
- 因果関係を持つゼロ個以上の**スパン**への[**リンク**](#スパン間のリンク)（それらの関連する**スパン**の**SpanContext**を介する）
- **スパン**を参照するために必要な**SpanContext**情報。以下を参照。

### SpanContext

**トレース**内で**スパン**を識別するすべての情報を表し、子スパンへ、そしてプロセス境界を越えてMUST伝搬されるものとします。**SpanContext**には、親から子の**スパン**へ伝搬されるトレース識別子と各種のオプションが含まれます。

- **TraceId**はトレースの識別子です。16バイトのランダムに生成されたバイト列として作られるため、実用上十分な確率で世界的に一意です。TraceIdは、すべてのプロセスにわたって、特定のトレースに属するすべてのスパンをグループ化するために使われます。
- **SpanId**はスパンの識別子です。8バイトのランダムに生成されたバイト列として作られるため、実用上十分な確率で全体的に一意です。子スパンに渡されると、この識別子は子**スパン**の親スパンIDになります。
- **TraceFlags**はトレースのオプションを表します。1バイト（ビットマップ）として表現されます。
  - サンプリングビット - トレースがサンプリングされているかどうかを表すビット（マスク `0x1`）。
- **Tracestate**は、トレーシングシステム固有のコンテキストをキーと値のペアのリストで運びます。**Tracestate**は、異なるベンダーが追加の情報を伝搬し、それぞれのレガシーなID形式と相互運用できるようにします。詳細は[こちら](https://www.w3.org/TR/trace-context/#tracestate-header)を参照してください。

### スパン間のリンク

**スパン**は、因果関係を持つゼロ個以上の他の**スパン**（**SpanContext**によって定義される）にリンクできます。**リンク**は、単一の**トレース**内のスパンにも、異なる**トレース**をまたいだスパンにも張れます。**リンク**は、バッチ処理された操作を表現するために使うことができます。この場合、**スパン**はバッチ内で処理されている個々の受信項目をそれぞれ表す複数の起点となる**スパン**によって開始されます。

**リンク**を使う別の例として、起点となるトレースとそれに続くトレースの関係を宣言する用途があります。これは、**トレース**がサービスの信頼境界に入り、サービスのポリシーが受信したトレースコンテキストを信頼するのではなく新しいトレースの生成を要求する場合に使えます。この新しくリンクされたトレースは、複数の高速な受信リクエストの1つによって開始された、長時間実行される非同期のデータ処理操作を表す場合もあります。

scatter/gather（fork/joinとも呼ばれる）パターンを使う場合、ルート操作は複数の下流の処理操作を開始し、それらはすべて単一の**スパン**に集約されます。この最後の**スパン**は、それが集約する多くの操作にリンクします。それらはすべて同一のトレースからの**スパン**です。そして**スパン**のParentフィールドと似ています。しかし、このシナリオでは**スパン**の親を設定しないことが推奨されます。なぜなら、意味的にはParentフィールドは単一の親というシナリオを表し、また多くの場合親**スパン**は子**スパン**を完全に包含するためです。scatter/gatherとバッチのシナリオでは、これは当てはまりません。

## メトリックシグナル

OpenTelemetryは、生の測定値、または事前に定義された集約と[属性の集合](/works/otel-specs-ja/spec/common/#attribute)を伴うメトリクスを記録できます。

OpenTelemetry APIを使って生の測定値を記録することで、エンドユーザーは特定のメトリクスに対する集約アルゴリズムを選択する柔軟性を得られます。この機能は、gRPCのようなクライアントライブラリで特に有用です。gRPCでは、"server_latency"や"received_bytes"のような生の測定値を記録できます。エンドユーザーは、これらの生の測定値に対する集約方法を、単純な平均から、より複雑なヒストグラム計算まで、自分の裁量で決められます。

### 生の測定値の記録

OpenTelemetry APIを使って生の測定値を記録する際に関わる主要なコンポーネントは、`Measurement`、`Instrument`、`Meter`です。`Meter`は`MeterProvider`から取得され、`Instrument`を作成するために使われます。`Instrument`は、続いて[測定値](../metrics/api/#measurement)を捕捉する責務を持ちます。

```
+------------------+
| MeterProvider    |                 +-----------------+             +--------------+
|   Meter A        | Measurements... |                 | Metrics...  |              |
|     Instrument X +-----------------> In-memory state +-------------> MetricReader |
|     Instrument Y |                 |                 |             |              |
|   Meter B        |                 +-----------------+             +--------------+
|     Instrument Z |
|     ...          |                 +-----------------+             +--------------+
|     ...          | Measurements... |                 | Metrics...  |              |
|     ...          +-----------------> In-memory state +-------------> MetricReader |
|     ...          |                 |                 |             |              |
|     ...          |                 +-----------------+             +--------------+
+------------------+
```

#### Instrument

[Instrument](../metrics/api/#instrument)は`Measurement`を報告するために使われ、名前、種別、説明、値の単位によって識別されます。

特定の用途向けに複数の種類のメトリックInstrumentがあります。値を増分するカウンター、現在の値を捕捉するゲージ、測定値の分布を捕捉するヒストグラムなどです。Instrumentは同期的にすることもできます。これはアプリケーションロジックによってインラインで呼び出されることを意味します。あるいは非同期にすることもできます。この場合、ユーザーはコールバック関数を登録し、SDKによって必要に応じて呼び出されます。

### メトリクスのデータモデルとSDK

メトリクスのデータモデルは[こちらで規定されて](/works/otel-specs-ja/spec/metrics/data-model/)おり、[metrics.proto](https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto)に基づいています。このデータモデルは3つのセマンティクスを定義します。APIが使うEventモデル、SDKとOTLPが使うin-flightデータモデル、そしてエクスポーターがin-flightモデルをどのように解釈すべきかを示すTimeSeriesモデルです。

エクスポーターごとに、異なる能力（例えばどのデータ型をサポートするか）と異なる制約（例えば属性キーにどの文字を使えるか）があります。メトリクスは、どこでもサポートされる最小公倍数ではなく、可能なことすべての上位集合となることを意図しています。すべてのエクスポーターは、OpenTelemetry SDKで定義されたMetric Producerインターフェースを介してメトリクスのデータモデルからデータを消費します。

このため、メトリクスはデータ（例えばキーで使える文字）に対する制約を最小限にとどめており、メトリクスを扱うコードは検証やサニタイズを避けるべきです。代わりに、データをバックエンドへ渡し、バックエンドに検証を任せて、バックエンドからのエラーを呼び出し元に返すようにします。

詳細は[メトリクスのデータモデル仕様](/works/otel-specs-ja/spec/metrics/data-model/)を参照してください。

#### View

[View](/works/otel-specs-ja/spec/metrics/sdk/#view)は、`Instrument`からのデータをどのように処理、集約、エクスポートするかを指定する設定です。`MeterProvider`を通じて設定できます。`View`により、既定の収集動作を超えて、特定の集約、変換、フィルタリングをメトリクスデータに適用できます。

## ログシグナル

### データモデル

[Log Data Model](/works/otel-specs-ja/spec/logs/data-model/)は、OpenTelemetryがログとイベントをどのように理解するかを定義します。

## バゲージシグナル

トレースの伝搬に加えて、OpenTelemetryは`Baggage`と呼ばれる名前と値のペアを伝搬するためのシンプルな仕組みを提供します。`Baggage`は、あるサービスで発生したオブザーバビリティイベントに、同一トランザクション内の先行するサービスから提供された属性でインデックスを付けることを意図しています。これは、これらのイベント間の因果関係を確立する助けになります。

`Baggage`は他のcross-cutting concernを試作するために使えますが、この仕組みは主にOpenTelemetryのオブザーバビリティシステムのための値を伝えることを意図しています。

これらの値は`Baggage`から取り出して、メトリクスの追加の属性や、ログとトレースの追加のコンテキストとして使えます。いくつかの例を示します。

- Webサービスは、どのサービスがリクエストを送信したかに関するコンテキストを含めることで利益を得られる
- SaaSプロバイダーは、リクエストの責任を負うAPIユーザーやトークンに関するコンテキストを含められる
- 特定のブラウザバージョンが画像処理サービスの障害と関連していることを判定できる

OpenTracingとの後方互換性のため、OpenTracingブリッジを使用する際、BaggageはBaggageとして伝搬されます。異なる基準を持つ新たな関心事は、W3Cのエンコーディング形式を活かしつつも新しいHTTPヘッダーでデータを分散トレース全体に伝えるという、新たなcross-cutting concernの作成を検討すべきです。

## リソース

`Resource`は、テレメトリーが記録される対象のエンティティに関する情報を捕捉します。例えば、Kubernetesのコンテナから公開されるメトリクスは、クラスタ、名前空間、Pod、コンテナ名を指定するリソースに結び付けられます。

`Resource`は、エンティティ識別の階層全体を捕捉することがあります。クラウド上のホストと、プロセス内で実行されている特定のコンテナやアプリケーションを記述する場合もあります。

プロセス識別情報の一部は、OpenTelemetry SDKによって自動的にテレメトリーに関連付けられることがあることに注意してください。

## コンテキスト伝搬

トレースやメトリクスといったOpenTelemetryのすべてのcross-cutting concernは、分散トランザクションの寿命にわたって状態を保存しデータにアクセスするための、基盤となる`Context`の仕組みを共有します。

詳細は[Context](/works/otel-specs-ja/spec/context/)を参照してください。

## プロパゲーター

OpenTelemetryは`Propagator`を使って、`Span`（通常は`SpanContext`部分のみ）や`Baggage`といったcross-cutting concernの値をシリアライズおよびデシリアライズします。異なる`Propagator`の種類は、特定のトランスポートによって課される制約を定義し、あるデータ型に結び付けられます。

Propagators APIは現在1つの`Propagator`の種類を定義しています。

- `TextMapPropagator`は、値をキャリアに対してテキストとして注入し、また抽出します。

## Collector

OpenTelemetry Collectorは、OpenTelemetryまたは他の監視・トレーシングライブラリ（Jaeger、Prometheusなど）で計装されたプロセスからトレース、メトリクス、そして将来的には他のテレメトリーデータ（ログなど）を収集し、集約とスマートサンプリングを行い、トレースとメトリクスを1つ以上の監視・トレーシングのバックエンドへエクスポートする一連のコンポーネントです。Collectorは、収集したテレメトリーを（追加の属性を付与したり個人情報を除去したりして）拡充・変換できるようにします。

OpenTelemetry Collectorには主に2つの動作モードがあります。Agent（アプリケーションと一緒にローカルで動くデーモン）とCollector（スタンドアロンで動く常駐サービス）です。

詳細はOpenTelemetry Collectorの[長期的なビジョン](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/vision.md)を参照してください。

## Instrumentation Library

このプロジェクトの発想は、すべてのライブラリとアプリケーションにOpenTelemetry APIを直接呼び出させることで、標準で（out of the box）オブザーバブルにすることです。しかし、多くのライブラリにはそのような統合がないため、そうした呼び出しを注入する別のライブラリが必要になります。これには、インターフェースのラッピング、ライブラリ固有のコールバックへの登録、既存のテレメトリーのOpenTelemetryモデルへの変換といった仕組みが使われます。

あるライブラリに対してOpenTelemetryによるオブザーバビリティを可能にするライブラリは、[Instrumentation Library](../glossary/#instrumentation-library)と呼ばれます。

Instrumentation Libraryは、計装対象のライブラリの命名規則に従って名付けるべきです（例えば、Webフレームワークであれば'middleware'とする）。

OpenTelemetryのリポジトリでホストされる計装については、"opentelemetry-instrumentation"というプレフィックスに、計装対象のライブラリ名自体を続けることが推奨されます。例を示します。

* opentelemetry-instrumentation-flask（Python）
* @opentelemetry/instrumentation-grpc（JavaScript）

OpenTelemetryでホストされていないInstrumentation Libraryは、OpenTelemetryでホストされているパッケージとの名前の衝突を避けるべきです。例えば、自社名やプロジェクト名を計装パッケージ名にプレフィックスとして付けることが考えられます。

* {company}-opentelemetry-instrumentation-{component}（Python）
* @{company}/opentelemetry-instrumentation-{component}（JavaScript）

詳細は[Instrumentation Library](../glossary/#instrumentation-library)を参照してください。

