> Source: https://www.ymotongpoo.com/works/otel-specs-ja/spec/entities/entity-propagation/


**ステータス**: [Development](../../document-status/)

## 概要

Entity Propagationは、環境変数を使ってプロセス境界を越えてEntity情報を渡す仕組みを提供します。これにより、分散システムでトレースコンテキストが伝搬される方法と同様に、親プロセスと子プロセスの間でEntityを共有できます。この方式は、外部のプロセスが、子プロセス自身が発見できる以上の情報を子Entityについて把握している場合に特に有用です。

Entity Propagationが有効な典型的な場面には、以下のようなものがあります。

- オーケストレーターがコンテナのメタデータを把握しているコンテナオーケストレーションシステム
- ビルドツールがジョブや環境の詳細を把握しているCI/CDパイプライン
- スケジューラーがタスクのコンテキストを把握しているバッチ処理システム
- 特定のEntityコンテキストを与えて起動されるコマンドラインツール

環境変数は、子プロセスに自動的に継承され、プロセスの初期化時に利用できるため、こうした伝搬のための信頼性の高い、プラットフォームを問わない仕組みを提供します。

## 環境変数によるEntity情報の指定

OpenTelemetryの実装間で標準化されたEntity Propagationを可能にするため、本仕様は`OTEL_ENTITIES`環境変数の形式と処理要件を定義します。

環境変数にアクセスできるSDKは、`OTEL_ENTITIES`環境変数を使って定義済みのEntityを発見し、それをResourceに関連付ける`EnvEntityDetector`を提供しなければなりません（MUST）。

`OTEL_ENTITIES`環境変数には、人間が読みやすく簡潔に表現できるよう設計されたコンパクトな形式で、Entityの一覧が含まれます。

### 形式仕様

各Entityは以下の構造に従います。

```
type{id_key1=id_value1,id_key2=id_value2}[desc_key1=desc_value1,desc_key2=desc_value2]@schema_url
```

各要素は次のとおりです。

- `type`はEntityの種別です（必須。例: "service"、"host"、"container"）。
- `{...}`には識別属性をカンマ区切りのkey=valueペアとして含めます（必須。少なくとも1組）。
- `[...]`には記述属性をカンマ区切りのkey=valueペアとして含めます（任意）。
- `@schema_url`はEntityのSchema URLを指定します（任意）。

複数のEntityはセミコロン（`;`）で区切ります。

### 文法

```
entities      := entity (";" entity)*
entity        := type id_attrs desc_attrs? schema_url? | ""
type          := [a-zA-Z][a-zA-Z0-9._-]*
id_attrs      := "{" key_value_list "}"
desc_attrs    := "[" key_value_list "]"
schema_url    := "@" url_string
key_value_list := key_value ("," key_value)*
key_value     := key "=" value
key           := [a-zA-Z][a-zA-Z0-9._-]*
value         := [^{}[\]@;,=]*
url_string    := [^;]*
```

### 例

```bash
# Single service entity
OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]"

# Multiple entities with schema URL
OTEL_ENTITIES="service{service.name=my-app,service.instance.id=instance-1}[service.version=1.0.0]@https://opentelemetry.io/schemas/1.21.0;host{host.id=host-123}[host.name=web-server-01]"

# Kubernetes pod entity
OTEL_ENTITIES="k8s.pod{k8s.pod.uid=pod-abc123}[k8s.pod.name=my-pod,k8s.pod.label.app=my-app]"

# Container with host (minimal descriptive attributes)
OTEL_ENTITIES="container{container.id=cont-456};host{host.id=host-789}[host.name=docker-host]"

# Minimal entity (only required fields)
OTEL_ENTITIES="service{service.name=minimal-app}"

# Empty strings are allowed (leading, trailing, and consecutive semicolons are ignored)
OTEL_ENTITIES=";service{service.name=app1};;host{host.id=host-123};"
```

### パースアルゴリズム

1. 入力文字列をセミコロン（`;`）で分割し、個々のEntity定義を取得する。
2. 各Entity定義について、以下を行う。
   a. Entity定義が空であればスキップする（連続するセミコロンや先頭・末尾のセミコロンを許容する）。
   b. Entityの種別を抽出する（最初の`{`より前の部分すべて）。
   c. `{...}`ブロックから識別属性を抽出する。
   d. `[...]`ブロックが存在する場合は、そこから記述属性を抽出する。
   e. `@...`の部分が存在する場合は、そこからSchema URLを抽出する。
3. カンマ（`,`）を区切り文字、等号（`=`）を代入としてkey-valueリストをパースする。
4. 各Entityが空でない種別と、少なくとも1つの識別属性を持つことを検証する。
5. Entityオブジェクトを作成し、Resourceに関連付ける。

### 文字エンコーディング

すべての属性値は文字列として扱わなければならず（MUST）、`baggage-octet`の範囲外の文字は[W3C Baggage](https://www.w3.org/TR/baggage/#header-content)仕様に従ってパーセントエンコードされなければなりません（MUST）。

予約文字`{}[]@;,=`が属性値内にリテラルとして現れる場合は、パーセントエンコードされなければなりません（MUST）。

- `{` → `%7B`
- `}` → `%7D`
- `[` → `%5B`
- `]` → `%5D`
- `@` → `%40`
- `;` → `%3B`
- `,` → `%2C`
- `=` → `%3D`

**例:**

```bash
# Entity with reserved characters in attribute values
OTEL_ENTITIES="service{service.name=my%2Capp,service.instance.id=inst-1}[config=key%3Dvalue%5Bprod%5D]"
# Resolves to: service.name="my,app", config="key=value[prod]"
```

### 検証要件

- Entityの種別は空であってはならず（MUST NOT）、パターン`[a-zA-Z][a-zA-Z0-9._-]*`に一致しなければなりません（MUST）。
- `{...}`ブロックには少なくとも1つの識別属性が存在しなければなりません（MUST）。
- 属性キーは空であってはならず（MUST NOT）、OpenTelemetryセマンティック規約に従うべきです（SHOULD）。
- Schema URLが存在する場合、それは有効なURIでなければなりません（MUST）。
- Entityの種別は、既存のOpenTelemetryのEntity命名規則（例: "service"、"host"、"container"、"k8s.pod"）に従うべきです（SHOULD）。

### エラー処理

SDKは、不正な入力に対して耐性を持つべきであり（SHOULD）、以下のエラー処理規則に従います。

1. **不正な構文**: 環境変数に不正な構文が含まれる場合、SDKは警告をログに記録し、有効な部分を処理しつつ不正な部分を無視すべきです（SHOULD）。

   例: `OTEL_ENTITIES="service{service.name=app1};invalid{syntax;service{service.name=app2}"`は、最初の有効なEntityを処理し、不正な部分をスキップします。

2. **必須フィールドの欠落**: あるEntityが必須フィールド（種別または識別属性）を欠いている場合、SDKは警告をログに記録し、そのEntityをスキップすべきです（SHOULD）。

   例: `OTEL_ENTITIES="service{};host{host.id=123}"`は、（識別属性を持たない）serviceのEntityをスキップし、hostのEntityを処理します。

3. **Entityの重複**: 同一の種別で識別属性が同一の複数のEntityが定義されている場合、SDKは最後に出現したものを使い、警告をログに記録すべきです（SHOULD）。

   例: `OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app1}[version=2.0]"`は`version=2.0`を使います。

4. **Schema URLの検証**: Schema URLが存在するが無効な場合、SDKは警告をログに記録し、そのEntityを処理する際にそのURLを無視すべきです（SHOULD）。

   例: `OTEL_ENTITIES="service{service.name=app1}@invalid-url"`は、そのEntityを処理しつつ無効なURLを無視します。

5. **識別属性の競合**: 同一種別の2つのEntityが同じ識別属性キーに異なる値を定義している場合、SDKは警告をログに記録し、最後のEntityのみを保持すべきです（SHOULD）。

   例: `OTEL_ENTITIES="service{service.name=app1};service{service.name=app2}"`は、`service.name=app2`のEntityのみを作成します。

6. **記述属性の競合**: 2つのEntityが同じ記述属性キーに異なる値を定義している場合、SDKは最後に定義されたEntityの値を使うべきであり（SHOULD）、警告をログに記録すべきです（SHOULD）。競合した属性は、最後のEntity以外には記録されるべきではありません（SHOULD NOT）。

   例: `OTEL_ENTITIES="service{service.name=app1}[version=1.0];service{service.name=app2}[version=2.0]"`は、`version`属性を持たないapp1のserviceと、`version=2.0`を持つapp2のserviceになります。

## EnvEntityDetector

TODO: fill out

