# スキーマ

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


**ステータス**: [Stable](/works/otel-specs-ja/spec/document-status/)

## 背景

計装済みアプリケーションのようなテレメトリーの送信元と、オブザーバビリティバックエンドのようなテレメトリーの利用者は、送出されるテレメトリーについて暗黙の前提を置くことがあります。両者は、テレメトリーが特定の属性を含んでいる、あるいはデータの特定の形状や構成を持っていることを前提にします（このドキュメントではこれを「テレメトリースキーマ」と呼びます）。

これにより、利用者を壊すことなく送出されるテレメトリーデータの構成を変更することが難しく、あるいは不可能になります。例えば、計装ライブラリが生成するスパンの属性名を変更すると、バックエンドがその名前で属性を見つけることを期待している場合、バックエンドが壊れてしまいます。

セマンティック規約は、この問題の重要な一部です。セマンティック規約は、スパン属性やメトリック名、その他のフィールドにどの名前と値を使うかを定義します。セマンティック規約が変更されると、既存の実装（テレメトリーの送信元または利用者）も対応して変更する必要があります。さらに問題を悪化させるのは、変更されたセマンティック規約に依存し、連携して動作するテレメトリーの送信元の実装と利用者の実装は、同時に変更する必要があるという点です。そうしなければ、それらの実装は正しく連携して動作しなくなります。

要するに、3つの当事者、すなわち（1）OpenTelemetryのセマンティック規約、（2）テレメトリーの送信元、（3）テレメトリーの利用者の間には結合関係があります。この結合が、これら3者の独立した進化を複雑にしています。

私たちは、以下のニーズを認識しています。

- OpenTelemetryのセマンティック規約は、時間の経過とともに進化する必要があります。規約が最初に定義されたときには誤りが生じる可能性があり、私たちはその誤りを後から修正したいと考えることがあります。また、属性の分類体系についての理解が深まるにつれて、規約を変更して属性を異なる名前空間に再編成したいと考えることもあります。

- テレメトリーの送信元は、時間の経過とともに送出するテレメトリーのスキーマを変更したいと考える場合があります。これは、例えばセマンティック規約が進化し、新しく導入された規約にテレメトリーを合わせたいためかもしれません。

- オブザーバビリティシステムには、異なるテレメトリースキーマに準拠するデータを生成するテレメトリーの送信元が同時に存在することがあります。これは、異なる送信元が異なる速度で進化し、異なる主体によって実装・管理されているためです。

- テレメトリーの利用者は、受信した特定のテレメトリーがどのスキーマに準拠しているかを理解する必要があります。利用者は、異なるテレメトリースキーマを使うテレメトリーデータを解釈できる方法も必要とします。

これらのニーズに対応するために提案・採用されたのが、[OTEP0152](https://github.com/open-telemetry/oteps/blob/main/text/0152-telemetry-schemas.md)によるテレメトリースキーマです。

## スキーマの仕組み

私たちは、上記の3つの当事者が、正しく連携して動作する能力を継続的に保持しながら、時間の経過とともに独立して進化できると考えています。

テレメトリースキーマは、これを可能にする中心的な仕組みです。以下にスキーマの仕組みの概要を示します。

- OpenTelemetryは、テレメトリースキーマを定義するための[ファイル形式](/works/otel-specs-ja/spec/schemas/file_format_v1.1.0/)を定義します。

- テレメトリースキーマはバージョン管理されます。時間の経過とともにスキーマは進化し、テレメトリーの送信元はより新しいバージョンのスキーマに準拠したデータを送出することがあります。

- テレメトリースキーマは、そのような変換が可能である場合に限り、スキーマの異なるバージョン間でテレメトリーデータを変換するために必要な変換を明示的に定義します。変換が不可能な場合、それはバージョン間の破壊的変更を構成します。

- テレメトリースキーマは、各スキーマバージョンで一意なSchema URLによって識別されます。

- テレメトリーの送信元（計装ライブラリなど）は、送出するテレメトリーにSchema URLを含めます。

- テレメトリーの利用者は、受信したテレメトリーのスキーマに注意を払います。必要であれば、テレメトリーの利用者は、利用時点で想定されているスキーマバージョン（例えばダッシュボードが想定するスキーマバージョンを定義するなど）へ、受信したスキーマバージョンからテレメトリーデータを変換してもかまいません。

- OpenTelemetryは、仕様書の一部としてテレメトリースキーマを公開します。このスキーマには、セマンティック規約が経てきた変換の一覧が含まれます。スキーマは、よく知られたURL`https://opentelemetry.io/schemas/<version>`（`<version>`は仕様書のバージョン番号に一致）で参照・ダウンロードできるようになっています。

- OpenTelemetryの計装ライブラリは、送出するすべてのテレメトリーにOpenTelemetry Schema URLを含めます。これは現在進行中の作業であり、[こちらが](https://github.com/open-telemetry/opentelemetry-go/blob/8ba6da8f3e5380629fcd72057fe0f827a9e23493/sdk/resource/os.go#L50)Go SDKのResource検出器でどのように行われているかを示す例です。

- OTLPは、送出するテレメトリーにSchema URLを含めることを許容します。

- サードパーティのライブラリ、計装、アプリケーションは、それらがOpenTelemetryのスキーマと完全に異なる場合、自身のテレメトリースキーマを定義・公開する（あるいはOpenTelemetryのスキーマを使う）ことと、送出するテレメトリーにSchema URLを含めることが推奨されます。

## スコープ外の事項

- スキーマという概念は、テレメトリーの形状を完全に記述しようとするものではありません。例えば、スキーマは属性のすべての有効な値やメトリクスの期待されるデータ型などを定義しません。これは目標ではありません。私たちの目標は、次の問題、すなわちOpenTelemetryのセマンティック規約が時間の経過とともに進化できるようにすることのみを解決するように、狭く定義されています。そのため、このドキュメントはスキーマの*全体の状態*ではなく、スキーマへの*変更*に関心を持ちます。しかし、これを完全に排除するわけではありません。スキーマファイル形式は拡張可能であり、将来的にはスキーマの全体の状態を定義できるようになるかもしれません。

- 私たちは、私たちが近い将来OpenTelemetryのセマンティック規約に必要になると考える、最も一般的な変更を扱うために必要な最小限にスキーマの変換の種類を意図的に制限します。将来的には、より多くの種類の変換が提案される可能性があります。この提案は、想像しうるスキーマへのすべての変更に対応できる、包括的な変換の種類の集合をサポートしようとするものではありません。それはあまりに複雑であり、おそらく余計なものになるでしょう。新しい変換の種類は、それがOpenTelemetryの進化にとって必要であるという証拠がある場合に、将来的にスキーマファイル形式へMUST提案・追加されるものとします。

## ユースケース

このセクションでは、テレメトリースキーマにとって興味深いいくつかのユースケースを示します（他のユースケースも考えられ、これは網羅的な一覧ではありません）。

### 完全なスキーマ認識

スキーマを認識するオブザーバビリティシステムの例を示します。

![完全なスキーマ認識](https://raw.githubusercontent.com/open-telemetry/opentelemetry-specification/v1.60.0/specification/schemas/img/0152-otel-schema.png)

テレメトリーデータが送出され、配送され、保存される際に、テレメトリーの送信元とバックエンドの組で何が起きるかをもう少し詳しく見てみましょう。

![送信元とバックエンド](https://raw.githubusercontent.com/open-telemetry/opentelemetry-specification/v1.60.0/specification/schemas/img/0152-source-and-backend.png)

この例では、テレメトリーの送信元は、"deployment.environment"属性を使ってスパンが本番環境から来ていることを記録する、OpenTelemetryスキーマのバージョン1.2.0に準拠したスパンを生成します。

テレメトリーの利用者は、OpenTelemetryスキーマのバージョン1.1.0でテレメトリーを保存したいと考えています。スキーマトランスレーターは、受信したスパンのschema_urlと目的のスキーマを比較し、バージョン変換が必要であることを認識します。次に、スキーマファイルに記述されている変更を適用し、スパンを保存する前に属性名を"deployment.environment"から"environment"へ変更します。

さらに、保存されたデータに対するクエリでスキーマがどのように使われるかの例を示します。

![クエリの変換](https://raw.githubusercontent.com/open-telemetry/opentelemetry-specification/v1.60.0/specification/schemas/img/0152-query-translate.png)

### Collectorによるスキーマ変換の支援

これとは少し異なるユースケースを示します。ここではバックエンドはスキーマを認識せず、OpenTelemetry Collectorに依存してバックエンドが期待するスキーマへテレメトリーを変換します。「Schema Translate Processor」が設定され、目的のschema_urlが指定されると、Collectorを通過するすべてのテレメトリーデータがその目的のスキーマへ変換されます。

![Collector](https://raw.githubusercontent.com/open-telemetry/opentelemetry-specification/v1.60.0/specification/schemas/img/0152-collector.png)

## Schema URL

Schema URLはスキーマの識別子です。このURLは、（URIではなく）URLであるため、HTTPまたはHTTPSプロトコルを使って取得できる[スキーマファイル](/works/otel-specs-ja/spec/schemas/file_format_v1.1.0/)の場所を指定します。

指定されたURLの取得はHTTPリダイレクトのステータスコードを返す場合があります。取得側は、HTTP標準にMUST従い、リダイレクトのレスポンスをMUST尊重し、リダイレクト先のURLからファイルをMUST取得するものとします。

URLパスの最後の部分は、スキーマのバージョン番号です。

```
http[s]://server[:port]/path/<version>
```

`<version>`より前のURLの部分はSchema Family識別子と呼ばれます。同一のSchema Familyに属するすべてのスキーマは、同一のSchema Family識別子を持ちます。

スキーマの新しいバージョンを作成するには、そのSchema Familyの最後のバージョンのスキーマファイルをコピーし、新しいバージョンの定義を追加します。新しいバージョンに対応するスキーマファイルは、新しいURLでMUST取得可能であるものとします。

重要：スキーマファイルは公開されると不変になります。スキーマファイルを取得した後は、永続的にキャッシュすることが推奨されます。スキーマファイルは、それを必要とする可能性のあるソフトウェアと一緒にビルド時にパッケージ化されることもあります（例えば、最新のOpenTelemetryスキーマファイルをOpenTelemetry Collectorのスキーマ変換プロセッサーと一緒にビルド時にパッケージ化するなど）。

## スキーマのバージョン番号

バージョン番号は、SemVer 2.0と同様のMAJOR.MINOR.PATCH形式に従います。

バージョン番号は、SemVer 2.0仕様で定義される[順序付けの規則](https://semver.org/#spec-item-11)を使います。この順序付けがどのように使われるかについては、[変換の順序](/works/otel-specs-ja/spec/schemas/file_format_v1.1.0/#変換の順序)を参照してください。順序付けの規則以外に、スキーマのバージョン番号はその他のセマンティックな意味を持ちません。

OpenTelemetryのスキーマバージョン番号は、OpenTelemetryの[セマンティック規約](https://opentelemetry.io/docs/specs/otel/semantic-conventions/)のバージョン番号に一致します。詳細は[こちら](#opentelemetryスキーマ)を参照してください。

## OTLPのサポート

送出されるテレメトリーでSchema URLを伝えられるようにするため、OTLPはメッセージにschema_urlフィールドを含みます。

- ResourceSpans、ResourceMetrics、ResourceLogsメッセージのschema_urlフィールドは、含まれるResource、Span、SpanEvent、Metric、LogRecordのメッセージに適用されます。

- InstrumentationLibrarySpansメッセージのschema_urlフィールドは、含まれるSpanとSpanEventのメッセージに適用されます。

- InstrumentationLibraryMetricsメッセージのschema_urlフィールドは、含まれるMetricメッセージに適用されます。

- InstrumentationLibraryLogsメッセージのschema_urlフィールドは、含まれるLogRecordメッセージに適用されます。

- Resource\*メッセージと、それに含まれるInstrumentationLibrary\*メッセージの両方でschema_urlフィールドが空でない場合、InstrumentationLibrary\*メッセージの値が優先されます。

## APIのサポート

OpenTelemetry APIは、Schema URLに関連付けられた[Tracer](/works/otel-specs-ja/spec/trace/api/#tracerの取得)や[Meter](/works/otel-specs-ja/spec/metrics/api/#meterの取得)を取得できるようにします。

## OpenTelemetryスキーマ

OpenTelemetryは、自身のスキーマを[opentelemetry.io/](https://opentelemetry.io/)schemas/<_version_>で公開します。このスキーマのバージョン番号は、そのスキーマを公開するsemantic-conventionsのバージョン番号と同じです。semantic-conventionsの新しいバージョンがリリースされるたびに、対応する新しいスキーマがMUST同時にリリースされるものとします。semantic-conventionsのリリースで変更が導入されなかった場合、スキーマファイル内の対応するバージョンの「変更」セクションは空になります。

- [スキーマファイル形式 1.0.0](/works/otel-specs-ja/spec/schemas/file_format_v1.0.0/)
- [スキーマファイル形式 1.1.0](/works/otel-specs-ja/spec/schemas/file_format_v1.1.0/)
