OTEP-0201: スコープ属性の導入

このOTEPは、テレメトリーエミッター(Tracer、Meter、LogEmitterなど)のスコープに属性を追加します。

動機

スコープ属性を追加することが良いアイデアである理由はいくつかあります。

  • スコープ属性が特定の問題を解決できる、既知の2つのユースケースがあります。
    • Meterの「short_name」のサポートを追加します。 これはMeterのスコープの属性として表現されます。
    • 異なるデータドメインに属するスコープから発せられるデータの種類を区別するためのサポートを追加します。 たとえば、LogRecordとして発せられるプロファイリングデータや、LogRecordとして発せられるクライアントサイドのデータは、バックエンドで容易に異なるルーティング・処理ができるように区別する必要があります。 現在、私たちはこれを扱う良い方法を持っていません。 データの種類は、Loggerのスコープの属性として記録できます。
  • これにより、スコープが他の主要なデータ型(Resource、Span、Metric、LogRecord)と一貫性を持つようになります。

追加の議論はこちらを参照してください。

サマリー

提案する変更のサマリーは以下のとおりです。

  • OpenTelemetry APIを拡張し、Tracer、MeterまたはLogEmitterを取得する際にスコープ属性を指定できるようにします。 スコープ属性は任意です。
  • OTLPのInstrumentationScopeメッセージにattributesフィールドを追加します。
  • スコープ付きのTracer、MeterまたはLogEmitterを経由して発せられるテレメトリーは、そのスコープの属性と関連付けられることを規定します。
  • OTLP ExporterがInstrumentationScopeメッセージにその属性を記録することを規定します。
  • 仕様書内にスコープ属性のセマンティック規約のためのセクションを作成します。

内部の詳細

API変更

Tracer

Get a Tracer APIは、以下のパラメーターを追加するように拡張されます。

- `attributes`(任意): 発せられるテレメトリーに関連付ける計装スコープ属性を指定します。

この属性は任意であるため、これは後方互換性のある変更です。

以下の条項を修正します。

It is unspecified whether or under which conditions the same or different
`Tracer` instances are returned from this functions.

これを以下に置き換えます。

The implementation MUST NOT return the same `Tracer` when called repeatedly with
different values of parameters. The only exception to this rule is no-op `Tracer`, the
implementation MAY return the same instance regardless of parameter values.

It is unspecified whether or under which conditions the same or different
`Tracer` instances are returned from this functions when the same 
(name,version,schema_url,attributes) parameters are used.

これまで未定義だった振る舞いをより厳密に定義することになるため、これは後方互換性のある変更です。

Meter

Get a Meter APIは、以下のパラメーターを追加するように拡張されます。

- `attributes`(任意): 発せられるテレメトリーに関連付ける計装スコープ属性を指定します。

以下の条項を修正します。

It is unspecified whether or under which conditions the same or different
`Meter` instances are returned from this functions.

これを以下に置き換えます。

The implementation MUST NOT return the same `Meter` when called repeatedly with
different values of parameters. The only exception to this rule is no-op `Meter`, the
implementation MAY return the same instance regardless of parameter values.

It is unspecified whether or under which conditions the same or different
`Meter` instances are returned from this functions when the same 
(name,version,schema_url,attributes) parameters are used.

LogEmitter

Get LogEmitter SDK呼び出しは、以下のように変更されます。

Accepts the instrumentation scope name and optional version and attributes and
returns a LogEmitter associated with the instrumentation scope.

The implementation MUST NOT return the same `LogEmitter` when called repeatedly with
different values of parameters. The only exception to this rule is no-op `LogEmitter`, the
implementation MAY return the same instance regardless of parameter values.

It is unspecified whether or under which conditions the same or different
`LogEmitter` instances are returned from this functions when the same
(name,version,attributes) parameters are used.

OTLP変更

OTLPのInstrumentationScopeメッセージは、2つの新しいフィールド、attributesとdropped_attributes_countを追加するように変更されます。

message InstrumentationScope {
  string name = 1;
  string version = 2;
  repeated KeyValue attributes = 3;
  uint32 dropped_attributes_count = 4;
}

この変更は、OTLPの相互運用性の観点から後方互換性があります。 古いOTLPバージョンの受信者はスコープ属性を認識せず、それらを無視しますが、これは相互運用性の観点から許容できると考えます。 これは、テレメトリーの送信元が古い受信者が理解できない新しいデータを 追加 したときに何が起こるかについての、私たちの一般的な立場と一致しています。 すなわち、新しいデータは安全に無視されることを期待するというものです。

属性値の優先順位

同じ属性がSpan/Metric/LogRecordとスコープの両方に指定されている場合、Span/Metric/LogRecordにおける属性値が優先されます。

この規則は、SDKにおける非OTLPエクスポーター、Collectorにおける OTLPから非OTLP形式への変換、および受信データ内の属性を解釈する必要があるOTLPの受信者に適用されます。

非OTLPへのエクスポート

SDKの非OTLP Exporterと、スコープに相当する概念を持たない形式へのCollectorのエクスポーターは、その属性を対応する形式内でもっとも適切な場所、典型的にはSpan、MetricまたはLogRecordに相当する場所に記録します。

先行技術と代替技術

Meterの「short_name」PRには、「short_name」をInstrumentationScopeへの唯一の属性として追加するという代替アプローチがありました。 このOTEPの提案はこれを一般化し、任意の属性を許可することで、それらをユースケースに利用できるようにします。

異なるデータドメインに属するスコープから発せられるデータの種類を区別することは、代替案としてSpan、MetricまたはLogRecordに属性を記録することでも可能です。 しかし、これは同じ属性をワイヤー上で繰り返し指定する必要があるため、効率が落ちます。 また、Span、MeterまたはLogEmitterを取得する際に一度だけ属性を指定するのとは異なり、SpanやMetric、LogRecordを作成するたびに呼び出し元にそのような属性を常に指定することを求めるのは煩雑です。

コードでの使用方法

以下は、LogEmitterを使用してクライアントサイドのログレコードを発する例です(擬似コードです)。

// Obtain loggers once, at startup.
appLogger = LogEmitterProvider.GetLogEmitter("mylibrary", "1.0.0")
loggerForUserEvents = LogEmitterProvider.GetLogEmitter("mylibrary", "1.0.0", KeyValue("otel.clientside", true))

// Somewhere later in the code when the user clicks a UI element. This should
// export telemetry with otel.clientside=true Scope attribute set.
loggerForUserEvents.emit(LogRecord{Body:"click", Attributes:...})

// Somewhere else in the code, not related to user interactions. This should
// export telemetry without any Scope attributes.
appLogger.emit(LogRecord{Body:"Error occurred while processing the file", Attributes:...})

LogRecordの多重化

以下は、プロファイリングデータ、クライアントサイドイベントおよび通常のログを表現するためにLogRecordが使用される例です。 スコープ属性は、LogRecordの多重化とルーティングに使用されます。

LogRecordの多重化

未解決の疑問

  • Span/Metric/LogRecordの属性をスコープレベルで記録することを許可・推奨すべきでしょうか。 代替案としては、これを許可せず、スコープ属性専用に許可される完全に別のセマンティック規約のセットを持つという方法があります。
  • すべての言語における既存のAPIは、任意の属性の追加が破壊的変更にならないように安全に修正できるでしょうか。 (スコープを導入したときに非常によく似た変更を行っているため、安全であるはずです。)

将来の可能性

このOTEPが承認された場合、前述の2つのユースケースを実現するために、関連するセマンティック規約を導入する必要があります。