設定SDK

この記事は英語の原文を日本語に翻訳したものです。原文: https://opentelemetry.io/docs/specs/otel/configuration/sdk/

翻訳元: open-telemetry/opentelemetry-specification v1.60.0(コミット 29ae8c7

ステータス: 安定(Stable)(別途明記されている箇所を除く)

概要

設定SDKは、宣言的設定インターフェースの一部です。

SDKは、計装設定APIと、その他の利用者向けの宣言的設定ケーパビリティの実装です。これは以下の主要なコンポーネントから構成されます。

In-Memory configuration model

SDKは、設定モデルのインメモリ表現をSHOULD提供するものとします。 ConfigPropertiesが任意のマッピングノードのスキーマレスな表現であるのに対し、In-Memory configuration modelは設定モデルのスキーマをSHOULD反映するものとします。

SDKは、このインメモリ表現を自身の言語にとってイディオマティックな方法で提供することが推奨されます。SDKがクラスやインターフェースを公開する必要がある場合、Configurationという名前がRECOMMENDEDです。

ConfigProvider

ステータス: Development

ConfigProviderのSDK実装は、設定モデル.instrumentationマッピングノードを表すConfigPropertiesを使ってMUST作成されるものとします。

SDK extension components

SDKは、「拡張プラグインインターフェース」とも呼ばれる、さまざまなプラグインコンポーネントをサポートし、利用者とライブラリがサンプリング、処理、データのエクスポートを含む振る舞いをカスタマイズできるようにします。

設定データモデルは、これらのプラグインコンポーネントの組み込み実装に対して特定の型をSHOULD定義するものとします。例えば、BatchSpanProcessor型は、組み込みのバッチ処理を行うSpanProcessorを参照します。

このスキーマは、ライブラリや利用者によって定義されたプラグインコンポーネントのカスタム実装を指定する能力をSHOULDサポートするものとします。例えば、カスタムのspan exporterは以下のように設定できます。

tracer_provider:
  processors:
    - batch:
        exporter:
          my-exporter:
            config-parameter: value

ここでは、tracer providerがバッチspanプロセッサーを持ち、それがmy-exporterという名前のカスタムspanエクスポーターと組み合わされていることを指定しています。このエクスポーターはconfig-parameter: valueで設定されています。この設定が成功するには、type: SpanExporterかつname: my-exporterPluginComponentProvider登録されていなければなりません。parseが呼び出されると、実装はmy-exporterに遭遇し、対応する設定を同等のConfigProperties表現(すなわちproperties: {config-parameter: value})へ変換します。createが呼び出されると、実装はmy-exporterに遭遇し、parseの際に決定されたConfigPropertiesを使って、登録済みのPluginComponentProviderに対してcreate componentを呼び出します。

言語間の本質的な違いを踏まえると、拡張コンポーネントの機構の詳細は、OpenTelemetryが定義する他のAPIよりも大きく異なる可能性が高くなります。これは想定されたことであり、実装が定義された振る舞いを実現する限りは許容されます。

PluginComponentProvider

PluginComponentProviderは、設定を解釈し、特定の種類のSDKプラグインコンポーネントの実装を返す責任を負います。

PluginComponentProviderは、registerを介して設定のSDK実装に登録されます。これは、言語のエコシステムにおいて何が可能でイディオマティックかに応じて、自動的に行われても、利用者による手動の介入を要求してもかまいません(MAY)。例えばJavaでは、PluginComponentProviderサービスプロバイダインターフェース(SPI)機構を使って自動的に登録される場合があります。

PluginComponentProviderの使用法を設定モデルの解釈の中で詳しく説明したcreateを参照してください。

サポートされるSDKプラグインコンポーネント

以下の表は、設定データモデルにおけるすべてのSDKプラグインコンポーネントの現在のステータスを一覧にしたものです。

SDKプラグインコンポーネント宣言的設定における型
リソース検出器ExperimentalResourceDetection
text mapプロパゲーターTextMapPropagator
span exporterSpanExporter
span processorSpanProcessor
samplerSampler
ID generatorIdGenerator
pull metric readerPullMetricExporter
push metric exporterPushMetricExporter
metric producerMetricProducer
exemplar reservoirまだ利用できません(#189
log record exporterLogRecordExporter
log record processorLogRecordProcessor
PluginComponentProviderの操作

PluginComponentProviderは以下の関数をMUST提供するものとします。

Create Component

設定を解釈して、SDKプラグインコンポーネントのインスタンスを作成します。

パラメータ:

戻り値: 設定済みのSDKプラグインコンポーネント。

プラグインコンポーネントは、オプションまたは必須のプロパティを持ち、型や形式について特定の要求事項を持つことがあります。PluginComponentProviderが受け付けるプロパティの集合は、その要求レベルと期待される型とともに、設定スキーマを構成します。PluginComponentProviderは、自身の設定スキーマを文書化し、例を含めるべきです(SHOULD)。

Create Componentが呼び出されると、PluginComponentProviderpropertiesを解釈し、自身の設定スキーマに従ってデータを抽出しようとします。これが失敗する場合(例えば必須のプロパティが存在しない、型が一致しないなど)、Create Componentはエラーを返すべきです(SHOULD)。

SDK operations

設定のSDK実装は以下の操作をMUST提供するものとします。

注記: これらの操作は状態を持たない純粋な関数であるため、型やクラス、インターフェースなどの一部として定義されているわけではありません。SDKはこれらを言語にとってイディオマティックな方法で自由に構成してかまいません。

Parse

設定ファイルを解析し、検証します。

パラメータ:

  • file: 解析対象の設定ファイル。これはファイルパス、言語固有のファイルデータ構造、あるいはファイルの内容のストリームでもかまいません(MAY)。
  • file_format: fileのファイル形式(例えばYAML)。実装はfile_formatパラメータを受け付けても、ファイルの拡張子から推論しても、あるいはparseYaml(file)のようなファイル形式固有のparseのオーバーロードを含めてもかまいません(MAY)。parsefile_formatを受け付ける場合、そのAPIは利用者がそれを提供するよう義務付けられる形にSHOULD構造化されるものとします。

戻り値: 設定モデル

ParseはMUST環境変数の置換を実行するものとします。

Parseは、存在しないプロパティと、存在するがnullであるプロパティをMUST区別するものとします。例えば、以下のスニペットを考えてみましょう。.meter_provider.views[0].stream.dropが存在するがnullである点に注意してください。

meter_provider:
  views:
    - selector:
        name: some.metric.name
      stream:
        aggregation:
          drop:

その結果、このviewのstreamはdrop集約で設定されるべきです。一部の集約には追加の引数がありますが、dropにはないことに注意してください。利用者は、こうした場合に空のオブジェクト(すなわちdrop: {})を指定するよう要求されてはなりません(MUST NOT)。

SDKに組み込まれていないSDK extension componentへの参照に遭遇した場合、Parseは、対応する設定を、Create Componentで説明されている通りの汎用的なConfigProperties表現へMUST解決するものとします。

Parseは、以下の場合にエラーをSHOULD返すものとします。

  • fileが存在しない、あるいは無効である場合
  • 解析されたfileの内容が設定モデルのスキーマに準拠しない場合。これには、スキーマに組み込まれたすべての制約の強制(例えば必須プロパティが存在すること、プロパティが指定された型に準拠していることなど)が含まれることに注意してください。

Create

設定モデルを解釈し、SDKコンポーネントを返します。

パラメータ:

戻り値: トップレベルのSDKコンポーネント。

これら複数の戻り値は、タプルやコンポーネントをカプセル化した何らかのデータ構造を使って返してもかまいません(MAY)。

デフォルトおよびnullの振る舞いに関するCreateの要求事項は以下に記述します。defaultBehaviornullBehaviorは設定データモデルの中で定義されている点に注意してください。

  • プロパティが存在し、その値がnullである場合、CreateはnullBehaviorを使わなければならず(MUST)、nullBehaviorが設定されていなければdefaultBehaviorを使わなければなりません(MUST)。
  • プロパティが必須であり、かつ存在しない場合、CreateはエラーをMUST返すものとします。

いくつかの例で説明します。

  • BatchSpanProcessorを設定する際、schedule_delayが存在しないか存在するがnullである場合、そのコンポーネントはdefaultBehaviorである5000に従って設定されます。
  • SpanExporterを設定する際、consoleが存在してnullである場合、consoleがnullableであるため、そのコンポーネントはデフォルト設定のconsoleエクスポーターで設定されます。

設定モデルは、標準のJSON schemaのキーワードでは符号化できないプロパティのセマンティクスを捕捉するために、JSON schemaのdescriptionアノテーションを使います。Createは、プロパティのdescriptionに従って無効な値に遭遇した場合、エラーをSHOULD返すものとします。例えば、HttpTlsを設定する際、ca_fileがプロパティの説明で定義されている絶対ファイルパスでない場合、エラーを返します。

SDKに組み込まれていないSDK plugin componentへの参照に遭遇した場合、Createは、registerに使われた対応するtypenameを持つPluginComponentProviderCreate Componentを使って、parseの際に決定された設定propertiesを引数として含めて、そのコンポーネントをMUST解決するものとします。そのtypenameで登録されたPluginComponentProviderが存在しない場合、CreateはエラーをSHOULD返すものとします。Create Componentがエラーを返す場合、CreateはそのエラーをSHOULD伝播するものとします。

これは、初期化におけるエラー処理の原則に従って、configurationの中でエラーに遭遇した場合(すなわちfail fast)、エラーをSHOULD返すものとします。

ステータス: Development SDKの実装は、Createによって初期化されるコンポーネントのプログラマティックなカスタマイズを可能にするオプションを提供してもかまいません(MAY)。これにより、設定モデルではまだ表現できない、あるいは今後も表現できないかもしれない概念の設定が可能になります。例えば、JavaのOTLPエクスポーターはExecutorServiceの設定を許容します。これはニッチですが、スレッドプールを厳密に制御する必要があるアプリケーションにとって重要なオプションです。このプログラマティックなカスタマイズは、Createにオプションのコールバックを渡す形をとる場合があります。このコールバックは、初期化される各SDKサブコンポーネント(またはSDKコンポーネント型のサブセット)とともに呼び出されます。例えば、以下のスニペットを考えてみましょう。

file_format: 1.0
tracer_provider:
  processors:
    - batch:
        exporter:
          otlp_http:

このコールバックは、OTLP HTTPエクスポーター、Batch SpanProcessor、Tracer ProviderのSDK表現とともに呼び出されます。このパターンは、解決済みのトップレベルのSDKコンポーネントから特定のコンポーネントまでたどる必要なく、より低レベルの部分をプログラマティックに設定する機会を提供します。

Register PluginComponentProvider

SDKは、PluginComponentProviderを登録する仕組みをMUST提供するものとします。この仕組みは、言語固有かつ自動的なものでもかまいません(MAY)。例えばJavaの実装では、特定のインターフェースの実装をPluginComponentProviderとして登録するためにサービスプロバイダインターフェース機構を使う場合があります。

パラメータ:

  • plugin_component_provider - PluginComponentProvider
  • type - それが提供するプラグインコンポーネントの型(例えばSpanExporter、Samplerなど)。
  • name - コンポーネントの型を識別するために使われる名前。これは、対応するcomponent_providerがそのコンポーネントを提供することを指定するために設定モデルの中で使われます。

typenameは一意のキーを構成します。同じtypenameの組み合わせで複数回呼び出された場合、RegisterはエラーをMUST返すものとします。

SDKは、自身の言語にとってイディオマティックな方法でtypeをSHOULD表現するものとします。例えば、クラスリテラルや列挙型などです。 サポートされるtypeの値の集合については、サポートされるSDK拡張プラグインを参照してください。

Examples

Via configuration API

設定のParseCreateの操作は、Configuration Modelとともに、単純または複雑な設定目標を達成するためにさまざまな方法で組み合わせられます。

例えば単純なケースでは、設定ファイルを指定してParseを呼び出し、その結果をCreateに渡すことで設定済みのSDKコンポーネントを得ます。

OpenTelemetry openTelemetry = OpenTelemetry.noop();
try {
    // Parse configuration file to configuration model
    OpenTelemetryConfiguration configurationModel = parse(new File("/app/sdk-config.yaml"));
    // Create SDK components from configuration model
    openTelemetry = create(configurationModel);
} catch (Throwable e) {
    log.error("Error initializing SDK from configuration file", e);
}

// Access SDK components and install instrumentation
TracerProvider tracerProvider = openTelemetry.getTracerProvider();
MeterProvider meterProvider = openTelemetry.getMeterProvider();
LoggerProvider loggerProvider = openTelemetry.getLoggerProvider();
ContextPropagators propagators = openTelemetry.getPropagators();
ConfigProvider configProvider = openTelemetry.getConfigProvider();

より複雑なケースでは、異なるソースから複数の設定ファイルを解析し、カスタムロジックを使ってそれらをマージし、マージされた設定モデルからSDKコンポーネントを作成する場合があります。

OpenTelemetry openTelemetry = OpenTelemetry.noop();
try {
    // Parse local and remote configuration files to configuration models
    OpenTelemetryConfiguration localConfigurationModel = parse(new File("/app/sdk-config.yaml"));
    OpenTelemetryConfiguration remoteConfigurationModel = parse(getRemoteConfiguration("http://example-host/config/my-application"));

    // Merge the configuration models using custom logic
    OpenTelemetryConfiguration resolvedConfigurationModel = merge(localConfigurationModel, remoteConfigurationModel);

    // Create SDK components from resolved configuration model
    openTelemetry = create(resolvedConfigurationModel);
} catch (Throwable e) {
    log.error("Error initializing SDK from configuration file", e);
}

// Access SDK components and install instrumentation
TracerProvider tracerProvider = openTelemetry.getTracerProvider();
MeterProvider meterProvider = openTelemetry.getMeterProvider();
LoggerProvider loggerProvider = openTelemetry.getLoggerProvider();
ContextPropagators propagators = openTelemetry.getPropagators();
ConfigProvider configProvider = openTelemetry.getConfigProvider();

Via OTEL_CONFIG_FILE

OTEL_CONFIG_FILE環境変数を設定すると(それをサポートする言語では)、言語固有の設定の詳細を学んだり多数の環境変数を使ったりする必要なく、OpenTelemetryコンポーネントを初期化する便利な方法を利用者に提供します。設定済みのコンポーネントへアクセスして計装へインストールするパターンは言語ごとに異なります。例えばJavaでの使用法は以下のようになります。

# Set the required env var to the location of the configuration file
export OTEL_CONFIG_FILE="/app/sdk-config.yaml"
// Initialize SDK using autoconfigure model, which recognizes that OTEL_CONFIG_FILE is set and configures the SDK accordingly
OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();

// Access SDK components and install instrumentation
TracerProvider tracerProvider = openTelemetry.getTracerProvider();
MeterProvider meterProvider = openTelemetry.getMeterProvider();
LoggerProvider loggerProvider = openTelemetry.getLoggerProvider();
ContextPropagators propagators = openTelemetry.getPropagators();
ConfigProvider configProvider = openTelemetry.getConfigProvider();

自動計装を使う場合、この初期化のフローは自動的に発生する場合があります。

References