# リソースSDK

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


**ステータス**: [安定（Stable）](../../document-status/)（別途明記されている箇所を除く）

[リソース](../../overview/#リソース)は、テレメトリーが生成される対象となる観測対象エンティティのイミュータブルな表現であり、[属性](/works/otel-specs-ja/spec/common/#attribute)として表現されます。例えば、Kubernetes上のコンテナで実行されているプロセスにはPod名があり、名前空間内にあり、場合によっては同様に名前を持つDeploymentの一部でもあります。これら3つの属性すべてを`Resource`に含められます。なお、[定められた意味を持つ属性](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/README.md)が存在することに注意してください。

SDKにおいてリソースを第一級の概念として設ける主な目的は、リソース情報の検出をエクスポーターから分離することです。これにより、独立した開発が可能になり、クローズドソースの環境と統合する必要がある利用者にとっての容易なカスタマイズが可能になります。SDKは、`Resource`を作成し、それをテレメトリーに関連付けられるようにしなければなりません（MUST）。

分散トレーシングで使う場合、リソースは`TracerProvider`の作成時にその[TracerProvider](/works/otel-specs-ja/spec/trace/api/#tracerprovider)に関連付けられます。その関連付けは後から変更できません。`TracerProvider`に関連付けられると、そのプロバイダーのいずれかの`Tracer`が生成するすべての`Span`は、この`Resource`に関連付けられなければなりません（MUST）。

トレーシングと同様に、メトリクスで使う場合、リソースは`MeterProvider`に関連付けられます。[`MeterProvider`](/works/otel-specs-ja/spec/metrics/api/#meterprovider)に関連付けられると、そのプロバイダーのいずれかの`Meter`が生成するすべてのメトリクスは、この`Resource`に関連付けられます。

同様に、ログで使う場合、リソースは`LoggerProvider`に関連付けられます。[`LoggerProvider`](/works/otel-specs-ja/spec/logs/api/#loggerprovider)に関連付けられると、そのプロバイダーのいずれかの`Logger`が生成するすべてのログレコードは、この`Resource`に関連付けられます。

## SDKが提供するリソース属性

SDKは、少なくとも[SDKが既定値を提供するセマンティック属性](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/README.md#semantic-attributes-with-sdk-provided-default-value)に列挙された属性を持つリソースへのアクセスを提供しなければなりません（MUST）。このリソースは、別のリソースが明示的に指定されなかった場合、`TracerProvider`、`MeterProvider`、または`LoggerProvider`に関連付けられなければなりません（MUST）。

注記: これは、SDKが提供する属性の一部またはすべてを持たないリソースを作成し、関連付けることが可能であることを意味します。ただし、これは既定では起こりません。利用者がカスタム属性を既定のリソースと組み合わせたい場合、カスタムのリソースに対して[`Merge`](#merge)を使うか、明示的にリソースを関連付ける代わりに[カスタムのリソース検出器を実装する](#環境からのリソース情報の検出)ことで自分の属性を指定できます。

## リソースの作成

SDKは、新しいリソースをインスタンス化する2つの方法をサポートしなければなりません。それらは以下のとおりです。

### Create

このインターフェースは、新しいリソースを作成する手段を提供しなければなりません（MUST）。例としては、リソースオブジェクトのファクトリーメソッドやコンストラクタが挙げられます。キャッシュされたオブジェクトのサポートを可能にするため、ファクトリーメソッドが推奨されます。

パラメータ:

- [`Attributes`](/works/otel-specs-ja/spec/common/#attribute)
- （1.4.0以降）`schema_url`（オプション）: 発行されるリソースに記録すべきSchema URLを指定します。`schema_url`パラメータが指定されない場合、作成されるリソースのSchema URLは空になります。
- **ステータス**: [開発中（Development）](../../document-status/)（1.60.0以降） - `Entities`（オプション）: 発行されるリソースに記録すべき[エンティティ](/works/otel-specs-ja/spec/resource/data-model/)を指定します。`entities`パラメータが指定されない場合、作成されるリソースにはエンティティが含まれません。

`Entities`と`Attributes`の両方がcreateメソッドに渡された場合、システムは、`Attributes`だけで作成されたリソースが、`Entities`だけで作成された別のリソースとマージされたかのように振る舞わなければなりません（MUST）。

### Merge

このインターフェースは、既存のリソースと更新用のリソースを新しいリソースにマージする手段を提供しなければなりません（MUST）。

注記: これは、環境変数やホスト・コンテナから抽出されたメタデータなど、異なる発生源から得られた属性を持つリソースをマージするために利用されることを意図しています。

必須パラメータ:

- 既存のリソース
- 属性が優先される、更新用のリソース

いずれかのリソースが`Entities`を含む場合、[エンティティを伴うマージの振る舞い](#エンティティを伴うマージの振る舞い)を使わなければならず（MUST）、そうでない場合は[エンティティを伴わないマージの振る舞い](#エンティティを伴わないマージの振る舞い)を使わなければなりません（MUST）。

#### エンティティを伴わないマージの振る舞い

結果のリソースは、2つの入力リソースいずれかにあるすべての属性を持たなければなりません（MUST）。あるキーが既存のリソースと更新用のリソースの両方に存在する場合、更新用のリソースの値が選ばれなければなりません（MUST）（更新後の値が空であっても）。

結果のリソースのSchema URLは、以下のように計算されます。

- 既存のリソースのSchema URLが空であれば、結果のリソースのSchema URLは更新用のリソースのSchema URLに設定されます。
- そうでなく、更新用のリソースのSchema URLが空であれば、結果のリソースのSchema URLは既存のリソースのSchema URLに設定されます。
- そうでなく、既存のリソースと更新用のリソースのSchema URLが同一であれば、それが結果のリソースのSchema URLになります。
- そうでない場合（既存のリソースと更新用のリソースのSchema URLがいずれも空でなく、かつ互いに異なる場合）はマージエラーです。結果のリソースは未定義であり、その内容は実装依存です。

#### エンティティを伴うマージの振る舞い

**ステータス**: [開発中（Development）](../../document-status/)

いずれかのリソースがエンティティを含む場合、マージ操作は[リソースデータモデルのマージアルゴリズム](/works/otel-specs-ja/spec/resource/data-model/#リソースのマージ)に従わなければなりません（MUST）。

結果の`SchemaURL`は、マージアルゴリズムで定義された振る舞いに一致しなければなりません（MUST）。

> [!NOTE]
> Resourceの`SchemaURL`は、後方互換性のための措置として保持されています。複数の`SchemaURL`が`Resource`に適用され得るエンティティ対応システムでは使われません。

### 空のリソース

推奨（ただし必須ではありません）されるのは、空のリソースを速やかに作成する手段を提供することです。

### 環境からのリソース情報の検出

汎用プラットフォーム（Docker、Kubernetesなど）やベンダー固有の環境（EKS、AKS、GKEなど）に関するカスタムのリソース検出器は、SDKとは別のパッケージとして実装しなければなりません（MUST）。

リソース検出器パッケージは、リソースを返すメソッドを提供しなければなりません（MUST）。これは、上述のとおり`TracerProvider`、`MeterProvider`、または`LoggerProvider`のインスタンスに関連付けられます。

リソース検出器パッケージは、複数のあり得る発生源からリソース情報を検出し、上述の`Merge`操作を使って結果をマージしてもよい（MAY）です。

リソース検出のロジックは、アプリケーションの初期化時に実行されるコードであるため、速やかに完了することが期待されます。エラーは[エラー処理の原則](/works/otel-specs-ja/spec/error-handling/#エラー処理の基本原則)に指定されているとおりに処理されるべきです（SHOULD）。なお、リソース情報の検出に失敗すること自体はエラーとみなされてはなりません（MUST NOT）が、リソース情報の検出を試みる過程で発生するエラーはエラーとみなされるべきです（SHOULD）。

OpenTelemetryのセマンティック規約に従ってリソース属性を設定するリソース検出器は、そのセマンティック規約に一致する値にリソースのSchema URLが設定されていることを保証しなければなりません（MUST）。検出器がセマンティック規約を持つ既知の属性でリソースを設定しない場合、または検出器がどの属性を設定するか分からない場合（例えば環境変数から属性を読み取る検出器はどのSchema URLを使うべきか分かりません）は、空のSchema URLが使われるべきです（SHOULD）。複数の検出器が組み合わされ、それらの検出器が異なる、空でないSchema URLを使う場合、それはエラーでなければなりません（MUST）。そのようなリソースをマージすることは不可能だからです。結果のリソースは未定義であり、その内容は実装固有です。

#### リソース検出器の名前

**ステータス**: [開発中（Development）](../../document-status/)

リソース検出器は、設定内で参照するための一意な名前を持つべきです（SHOULD）。例えば、利用者は[宣言的設定](/works/otel-specs-ja/spec/configuration/#宣言的設定)において名前で個々のリソース検出器を一覧・設定します。名前は[スネークケース](https://en.wikipedia.org/wiki/Snake_case)であるべきで（SHOULD）、小文字の英数字と`_`から構成され、これによって宣言的設定の[プロパティ名の要件](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#property-name-case)に準拠することが保証されます。

リソース検出器の名前は、それが設定する属性の[ルート名前空間](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/naming.md#general-naming-considerations)を反映すべきです（SHOULD）。例えば、`os`という名前のリソース検出器は`os.*`属性を設定します。複数のルート名前空間から属性を設定するリソース検出器は、その目的を適切に伝える名前を選ぶべきです（SHOULD）。

同じ名前を持つ複数のリソース検出器を識別したSDKは、エラーを報告すべきです（SHOULD）。衝突を抑えるため、リソース検出器は容易に見つけられる方法でその名前を文書化すべきです（SHOULD）。リソース検出器の作者は、対象の名前が既に使われていないかを既存のリソース検出器で確認すべきです。加えて、以下の検出器名は、言語SDKと共に公開される組み込みのリソース検出器のために予約されています。

* `container`: [container.*](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/container.md)属性を設定します。
* `host`: [host.*](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md)属性と[os.*](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/os.md)属性を設定します。
* `process`: [process.*](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/process.md)属性を設定します。
* `service`: [OTEL_SERVICE_NAME](/works/otel-specs-ja/spec/configuration/sdk-environment-variables/#一般的なsdk設定)環境変数に基づいて`service.name`を設定し、[ここで定義されている](https://github.com/open-telemetry/semantic-conventions/blob/mainhttps://opentelemetry.io/docs/specs/semconv/registry/attributes/service/#service-attributes)とおりに`service.instance.id`を設定します。

### 環境変数によるリソース情報の指定

SDKは、`OTEL_RESOURCE_ATTRIBUTES`環境変数から情報を抽出し、利用者が提供したリソース情報と、二次的なリソースとして[マージ](#merge)しなければなりません（MUST）。つまり、利用者が提供したリソース情報のほうが優先度が高くなります。

`OTEL_RESOURCE_ATTRIBUTES`環境変数は、`key1=value1,key2=value2`のように表現されるキーと値の組の一覧を含みます。すべての属性値は文字列として扱われなければなりません（MUST）。キーと値に含まれる`,`と`=`の文字はパーセントエンコードされなければなりません（MUST）。ANSI文字セット外の値のような他の文字は、[パーセントエンコード](https://datatracker.ietf.org/doc/html/rfc3986#section-2.1)されてもよい（MAY）です。

デコード処理中の失敗など、何らかのエラーが発生した場合、環境変数の値全体が破棄されるべきで（SHOULD）、[エラー処理の原則](/works/otel-specs-ja/spec/error-handling/#エラー処理の基本原則)に従ってエラーが報告されるべきです（SHOULD）。

## リソースの操作

リソースはイミュータブルです。したがって、リソースの作成に加えて、以下の操作のみが提供されるべきです。

### 属性の取得

SDKは、リソースに関連付けられた属性の読み取り専用のコレクションを取得する手段を提供すべきです。

属性の順序を保証する必要はありません。

エンティティが有効化されており、そのリソースに存在する場合、この一覧には、エンティティに関連付けられた属性を含むすべての属性が含まれなければなりません（MUST）。

属性を取得する際に最も一般的な操作は、それらを列挙することです。そのため、特定のキーを持つ属性の値を素早く取得する手段などの他の考慮事項よりも、列挙が高速になるように結果のコレクションを最適化することが推奨されます。

### エンティティの取得

**ステータス**: [開発中（Development）](../../document-status/)

SDKは、リソースに関連付けられたエンティティを取得する手段を提供すべきです（SHOULD）。

エンティティの順序を保証する必要はありません。

### 未関連付けの属性の取得

**ステータス**: [開発中（Development）](../../document-status/)

SDKは、リソース内でエンティティに関連付けられていない属性を取得する手段を提供すべきです（SHOULD）。

属性の順序を保証する必要はありません。

