# ログSDK

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


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

OpenTelemetryの利用者には、OpenTelemetry APIに対する計装からの相互作用が実際にテレメトリーを生成する手段が必要です。OpenTelemetry Logging SDK（以下SDK）は、この機能を利用者に提供するOpenTelemetry APIの実装です。

OpenTelemetryのすべての言語実装は、SDKを提供しなければなりません（MUST）。

## LoggerProvider

`LoggerProvider`は、[リソース](/works/otel-specs-ja/spec/resource/sdk/)を指定できる手段を提供しなければなりません（MUST）。`Resource`が指定された場合、それは`LoggerProvider`のいずれかの`Logger`が生成するすべての`LogRecord`に関連付けられるべきです（SHOULD）。

### LoggerProviderの作成

SDKは、複数の独立した`LoggerProvider`の作成を許可すべきです（SHOULD）。

### Loggerの作成

`Logger`インスタンスは`LoggerProvider`経由でのみ作成可能であるべきです（SHOULD）（[API](/works/otel-specs-ja/spec/logs/api/)を参照）。

`LoggerProvider`は、[LoggerAPIの取得](/works/otel-specs-ja/spec/logs/api/#loggerの取得)を実装しなければなりません（MUST）。

利用者が指定した入力は、作成される`Logger`に保存される[`InstrumentationScope`](/works/otel-specs-ja/spec/common/instrumentation-scope/)インスタンスを作成するために使わなければなりません（MUST）。

無効な`name`（nullまたは空文字列）が指定された場合、nullを返したり例外をスローしたりせず、フォールバックとして機能する`Logger`を返さなければなりません（MUST）。その`name`は元の無効な値を保持すべきで（SHOULD）、指定された値が無効であることを報告するメッセージがログに記録されるべきです（SHOULD）。

**ステータス**: [開発中（Development）](../../document-status/) - `LoggerProvider`は、設定された[LoggerConfigurator](#loggerconfigurator)を使って該当する[LoggerConfig](#loggerconfig)を計算し、その`LoggerConfig`に準拠して振る舞う`Logger`を作成しなければなりません（MUST）。

### Configuration

設定（つまり[LogRecordProcessor](#logrecordprocessor)、および（**開発中**）[LoggerConfigurator](#loggerconfigurator)）は、`LoggerProvider`が所有しなければなりません（MUST）。設定は、適切であれば`LoggerProvider`の作成時に適用してもよい（MAY）です。

`LoggerProvider`は設定を更新するメソッドを提供してもよい（MAY）です。設定が更新された場合（例えば`LogRecordProcessor`の追加）、更新された設定はすでに返却済みのすべての`Logger`にも適用されなければなりません（MUST）（つまり、設定変更の前後どちらに`LoggerProvider`から`Logger`を取得したかは問題になってはなりません（MUST NOT））。注記: 実装としては、`Logger`インスタンスが自身の`LoggerProvider`への参照を持ち、この参照経由でのみ設定にアクセスすることでこれを実現できます。

#### LoggerConfigurator

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

`LoggerConfigurator`は、[Logger](#logger)の[LoggerConfig](#loggerconfig)を計算する関数です。

この関数は次のパラメータを受け付けなければなりません（MUST）。

* `logger_scope`: `Logger`の[`InstrumentationScope`](/works/otel-specs-ja/spec/common/instrumentation-scope/)。

この関数は該当する`LoggerConfig`、または[既定のLoggerConfig](#loggerconfig)を使うべきことを示す何らかの信号を返さなければなりません（MUST）。この信号は、言語にとって慣用的な形に応じて、nil、null、空、または既定の`LoggerConfig`のインスタンスであってもよい（MAY）です。

この関数は`Logger`が最初に作成されるとき、および（更新がサポートされていれば）`LoggerProvider`の`LoggerConfigurator`が更新されたときに存在するすべての`Logger`に対して呼び出されます。したがって、速く返ることが重要です。

`LoggerConfigurator`は柔軟性を最大化するため関数としてモデル化されています。ただし実装は、よくある使用例に対応するための省略記法やヘルパー関数を提供してもよい（MAY）です。

* 名前で1つ以上のロガーを、完全一致またはパターンマッチングで選択する。
* 1つ以上の特定のロガーを無効化する。
* すべてのロガーを無効化し、1つ以上の特定のロガーを選択的に有効化する。
* 特定のロガーまたはロガーパターンに対して最小の重大度レベルを設定する。
* 特定のロガーまたはロガーパターンに対してトレースベースのフィルタリングを有効化する。

### Shutdown

このメソッドは、プロバイダーに必要なクリーンアップを行う手段を提供します。

`Shutdown`は、`LoggerProvider`インスタンスごとに1回だけ呼び出されなければなりません（MUST）。`Shutdown`の呼び出し後、`Logger`を取得する以降の試みは許可されません。SDKは、可能であればこれらの呼び出しに対して有効なno-opの`Logger`を返すべきです（SHOULD）。

`Shutdown`は、成功したか、失敗したか、タイムアウトしたかを呼び出し元に知らせる手段を提供すべきです（SHOULD）。

`Shutdown`は、一定のタイムアウト内に完了または中断すべきです（SHOULD）。`Shutdown`は、ブロッキングAPIとして実装しても、コールバックやイベントを通じて呼び出し元に通知する非同期APIとして実装してもよい（MAY）です。[OpenTelemetry SDK](../../overview/#sdk)の作者は、シャットダウンのタイムアウトを設定可能にするかどうかを決めてもよい（MAY）です。

`Shutdown`は、登録済みのすべての[LogRecordProcessor](#logrecordprocessor)に対して`Shutdown`を呼び出すことで実装しなければなりません（MUST）。

### ForceFlush

このメソッドは、プロバイダーが登録済みの[LogRecordProcessor](#logrecordprocessor)に対して、まだエクスポートされていないすべての`ReadableLogRecord`を直ちにエクスポートするよう通知する手段を提供します。

`ForceFlush`は、成功したか、失敗したか、タイムアウトしたかを呼び出し元に知らせる手段を提供すべきです（SHOULD）。エラー状態がある場合、`ForceFlush`は何らかの**ERROR**ステータスを返すべきで（SHOULD）、エラー状態がない場合は何らかの**NO ERROR**ステータスを返すべきです（SHOULD）。言語実装は、**ERROR**と**NO ERROR**をどうモデル化するかを決めてもよい（MAY）です。

`ForceFlush`は、一定のタイムアウト内に完了または中断すべきです（SHOULD）。`ForceFlush`は、ブロッキングAPIとして実装しても、コールバックやイベントを通じて呼び出し元に通知する非同期APIとして実装してもよい（MAY）です。[OpenTelemetry SDK](../../overview/#sdk)の作者は、フラッシュのタイムアウトを設定可能にするかどうかを決めてもよい（MAY）です。

`ForceFlush`は、登録済みのすべての[LogRecordProcessor](#logrecordprocessor)に対して`ForceFlush`を呼び出さなければなりません（MUST）。

## Logger

**ステータス**: [開発中（Development）](../../document-status/) - `Logger`は、[Loggerの作成](#loggerの作成)時に計算された[LoggerConfig](#loggerconfig)に従って振る舞わなければなりません（MUST）。`LoggerProvider`が[LoggerConfigurator](#loggerconfigurator)の更新をサポートする場合、更新時に`Logger`は新しい`LoggerConfig`に従って振る舞うよう更新されなければなりません（MUST）。

### LoggerConfig

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

`LoggerConfig`は、`Logger`の振る舞いのさまざまな設定可能な側面を定義します。これは次のパラメータから構成されます。

* `enabled`: ロガーが有効かどうかを示すブーリアン値。

  明示的に設定されていない場合、`enabled`パラメータは既定で`true`であるべきです（SHOULD）（つまり`Logger`は既定で有効です）。

  `Logger`が無効化されている場合、[No-op Logger](/works/otel-specs-ja/spec/logs/noop/#logger)と同等に振る舞わなければなりません（MUST）。

* `minimum_severity`: 処理対象とするログレコードの最小の重大度レベルを示す[SeverityNumber](/works/otel-specs-ja/spec/logs/data-model/#field-severitynumber)。

  明示的に設定されていない場合、`minimum_severity`パラメータは既定で`0`にならなければなりません（MUST）。

  ログレコードの[SeverityNumber](/works/otel-specs-ja/spec/logs/data-model/#field-severitynumber)が指定されており（つまり`0`ではない）、設定された`minimum_severity`より小さい場合、そのログレコードは`Logger`によって破棄されなければなりません（MUST）。重大度が指定されていない（つまり`0`の）ログレコードは、このパラメータの影響を受けず、したがって最小重大度によるフィルタリングを回避します。

* `trace_based`: サンプリングされていないトレースに関連付けられたログレコードをロガーが破棄すべきかどうかを示すブーリアン値。

  明示的に設定されていない場合、`trace_based`パラメータは既定で`false`にならなければなりません（MUST）。

  `trace_based`が`false`の場合、ログレコードはこのパラメータによる影響を受けてはなりません（MUST NOT）。

  `trace_based`が`true`の場合、サンプリングされていないトレースに関連付けられたログレコードは`Logger`によって破棄されなければなりません（MUST）。ログレコードは、有効な`SpanId`を持ち、その`TraceFlags`がトレースがサンプリングされていないことを示している場合に、サンプリングされていないトレースに関連付けられているとみなされます。トレースコンテキストに関連付けられていないログレコードは、このパラメータの影響を受けず、したがってトレースベースのフィルタリングを回避します。

これらのパラメータへの変更が`Enabled`の呼び出し元に即座に反映されることを実装が保証する必要はありません。ただし、その変更は最終的には反映されなければなりません（MUST）。

### LogRecordの発行

[Observed Timestamp](/works/otel-specs-ja/spec/logs/data-model/#field-observedtimestamp)が指定されていない場合、実装はそれを現在時刻に設定すべきです（SHOULD）。

[Exception](/works/otel-specs-ja/spec/logs/api/#logrecordの発行)が提供された場合、SDKは既定で、[例外のセマンティック規約](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/exceptions/exceptions-logs.md)に示された規約に従い、その例外から得られる属性を`LogRecord`に設定しなければなりません（MUST）。利用者が指定した属性が優先されなければならず（MUST）、例外由来の属性によって上書きされてはなりません（MUST NOT）。

注記: パフォーマンス最適化のため、SDKは大きな例外属性（例えば`exception.stacktrace`）を生成する際に、設定済みの[属性の制限](#logrecordの制限)を考慮してもよい（MAY）です。これは、どうせ切り捨てられる大きな属性値の不要な処理を避けるのに役立ちます。

**ステータス**: [開発中（Development）](../../document-status/) ログレコードを処理する前に、実装は[LoggerConfig](#loggerconfig)で定義されたフィルタリング規則を適用しなければなりません（MUST）。

1. **Enabled**: `Logger`が有効でない場合（つまり`LoggerConfig.enabled`が`false`の場合）、そのログレコードは破棄されなければなりません（MUST）。

2. **最小重大度**: ログレコードの[SeverityNumber](/works/otel-specs-ja/spec/logs/data-model/#field-severitynumber)が指定されており（つまり`0`ではない）、設定された`minimum_severity`より小さい場合、そのログレコードは破棄されなければなりません（MUST）。

3. **トレースベース**: `trace_based`が`true`であり、そのログレコードが[`SpanId`](/works/otel-specs-ja/spec/logs/data-model/#field-spanid)を持ち、[`TraceFlags`](/works/otel-specs-ja/spec/logs/data-model/#field-traceflags)のSAMPLEDフラグが立っていない場合、そのログレコードは破棄されなければなりません（MUST）。

### Enabled

`Enabled`は、次のいずれかに当てはまる場合、`false`を返さなければなりません（MUST）。

- 登録済みの[`LogRecordProcessor`](#logrecordprocessor)が存在しない。
- **ステータス**: [開発中（Development）](../../document-status/) - `Logger`が無効化されている（[`LoggerConfig.enabled`](#loggerconfig)が`false`）。
- **ステータス**: [開発中（Development）](../../document-status/) - 指定された重大度が指定されており（つまり`0`ではない）、[`LoggerConfig`](#loggerconfig)で設定された`minimum_severity`より小さい。
- **ステータス**: [開発中（Development）](../../document-status/) - [`LoggerConfig`](#loggerconfig)で`trace_based`が`true`であり、現在のコンテキストがサンプリングされていないトレースに関連付けられている。
- 登録済みのすべての`LogRecordProcessor`が[`Enabled`](#enabled-1)を実装しており、それぞれに対する`Enabled`の呼び出しがすべて`false`を返す。

それ以外の場合、`true`を返すべきです（SHOULD）。追加の最適化や機能をサポートするために`false`を返してもよい（MAY）です。

## LogRecordの追加インターフェース

この文書では、`ReadableLogRecord`と`ReadWriteLogRecord`という2つのインターフェースを参照します。それぞれ以下のように定義します。

### ReadableLogRecord

これを引数として受け取る関数は、[LogRecord](/works/otel-specs-ja/spec/logs/data-model/#log-and-event-record-definition)に追加されたすべての情報にアクセスできなければなりません（MUST）。また、`LogRecord`に（暗黙的に）関連付けられた[計装スコープ](/works/otel-specs-ja/spec/logs/data-model/#field-instrumentationscope)と[リソース](/works/otel-specs-ja/spec/logs/data-model/#field-resource)の情報にもアクセスできなければなりません（MUST）。

[トレースコンテキストのフィールド](/works/otel-specs-ja/spec/logs/data-model/#trace-context-fields)は、[発行](/works/otel-specs-ja/spec/logs/api/#logrecordの発行)時に解決された`Context`（明示的に渡された`Context`または現在の`Context`のいずれか）から設定されていなければなりません（MUST）。

収集の制限による属性の切り捨て件数は、[非OTLP形式への変換](/works/otel-specs-ja/spec/common/mapping-to-non-otlp/#dropped-attributes-count)仕様に記載されているとおり、エクスポーターが報告できるように利用可能でなければなりません（MUST）。

注記: 通常、これは新しいインターフェースまたは（イミュータブルな）値型として実装されます。SDKは、`ReadableLogRecord`と`ReadWriteLogRecord`の両方を表現するために単一の型を使ってもよいです。

### ReadWriteLogRecord

ReadWriteLogRecordは、[ReadableLogRecord](#readablelogrecord)のスーパーセットです。

これを引数として受け取る関数は、[LogRecord](/works/otel-specs-ja/spec/logs/data-model/#log-and-event-record-definition)に追加された次の情報についても、追加で変更できなければなりません（MUST）。

* [`Timestamp`](/works/otel-specs-ja/spec/logs/data-model/#field-timestamp)
* [`ObservedTimestamp`](/works/otel-specs-ja/spec/logs/data-model/#field-observedtimestamp)
* [`SeverityText`](/works/otel-specs-ja/spec/logs/data-model/#field-severitytext)
* [`SeverityNumber`](/works/otel-specs-ja/spec/logs/data-model/#field-severitynumber)
* [`Body`](/works/otel-specs-ja/spec/logs/data-model/#field-body)
* [`Attributes`](/works/otel-specs-ja/spec/logs/data-model/#field-attributes)（追加、変更、削除）
* [`TraceId`](/works/otel-specs-ja/spec/logs/data-model/#field-traceid)
* [`SpanId`](/works/otel-specs-ja/spec/logs/data-model/#field-spanid)
* [`TraceFlags`](/works/otel-specs-ja/spec/logs/data-model/#field-traceflags)
* [`EventName`](/works/otel-specs-ja/spec/logs/data-model/#field-eventname)

SDKは、`ReadWriteLogRecord`のディープクローンを作成する操作を提供してもよい（MAY）です。この操作は、並行安全性が要求されないログレコードに対する競合状態を避けるために、[Batching processor](#batching-processor)のような非同期プロセッサーが利用できます。

## LogRecordの制限

`LogRecord`の属性は、[属性の制限に関する共通規則](/works/otel-specs-ja/spec/common/#attribute-limits)に従わなければなりません（MUST）。

SDKが属性の制限を実装する場合、以下のJavaの例のように、利用者が個々の制限を設定できるようにする形で、`LoggerProvider`への設定を通じてこれらの制限を変更できる手段を提供しなければなりません（MUST）。

このオプションは、1つのクラスにまとめてもよい（MAY）です。その場合、そのクラスは`LogRecordLimits`と呼ばれるべきです（SHOULD）。

```java
public interface LogRecordLimits {
  public int getAttributeCountLimit();

  public int getAttributeValueLengthLimit();
}
```

**設定可能なパラメータ:**

* [属性に適用可能なすべての共通オプション](/works/otel-specs-ja/spec/common/#configurable-parameters)

属性がこうした制限によって破棄されたことを利用者に示すメッセージが、SDKのログに出力されるべきです（SHOULD）。過剰なログ出力を防ぐため、このメッセージは（破棄された属性ごとではなく）`LogRecord`ごとに最大1回だけ出力されなければなりません（MUST）。

## LogRecordProcessor

`LogRecordProcessor`は、`LogRecord`の発行に対するフックを可能にするインターフェースです。

組み込みのプロセッサーは、`LogRecord`のバッチ処理と、エクスポート可能な表現への変換、そしてエクスポーターへのバッチの引き渡しを担います。

`LogRecordProcessor`はSDKの`LoggerProvider`に直接登録でき、登録された順序と同じ順序で呼び出されます。

`LoggerProvider`に登録された各プロセッサーは、プロセッサーと任意の[エクスポーター](#logrecordexporter)から構成されるパイプラインの一部です。SDKは、各パイプラインが個別のエクスポーターで終わることを許可しなければなりません（MUST）。

SDKは、利用者が属性によるエンリッチのような高度なシナリオのためにカスタムプロセッサーを実装・設定したり、組み込みのプロセッサーをデコレートしたりできるようにしなければなりません（MUST）。

以下の図は、`LogRecordProcessor`とSDKの他のコンポーネントとの関係を示しています。

```
  +-----+------------------------+   +------------------------------+   +-------------------------+
  |     |                        |   |                              |   |                         |
  |     |                        |   | Batching LogRecordProcessor  |   |    LogRecordExporter    |
  |     |                        +---> Simple LogRecordProcessor    +--->     (OtlpExporter)      |
  |     |                        |   |                              |   |                         |
  | SDK | Logger.emit(LogRecord) |   +------------------------------+   +-------------------------+
  |     |                        |
  |     |                        |
  |     |                        |
  |     |                        |
  |     |                        |
  +-----+------------------------+
```

フィルタリングやファンアウトのような高度なログレコード処理を設定する方法の詳細については、[Supplementary Guidelines](/works/otel-specs-ja/spec/logs/supplementary-guidelines/#advanced-processing)を参照してください。

### LogRecordProcessorの操作

#### OnEmit

`OnEmit`は、`LogRecord`が[発行](/works/otel-specs-ja/spec/logs/api/#logrecordの発行)されたときに呼び出されます。このメソッドは、その`LogRecord`を発行したスレッド上で同期的に呼び出されるため、ブロックしたり例外をスローしたりすべきではありません（SHOULD NOT）。

**パラメータ:**

* `logRecord` - 発行された`LogRecord`に対する[ReadWriteLogRecord](#readwritelogrecord)。
* `context` - 解決済みの`Context`（明示的に渡された`Context`または現在の`Context`）

**戻り値:** `Void`

SDKの`LoggerProvider`に直接登録された`LogRecordProcessor`については、`logRecord`への変更は次に登録されているプロセッサーから見えなければなりません（MUST）。

`LogRecordProcessor`は、`OnEmit`呼び出しの間、`logRecord`を自由に変更できます。ただし、`ReadWriteLogRecord`が並行安全であることはオプションです（OPTIONAL）。したがって、`logRecord`に対する並行的な変更や読み取りは競合状態を引き起こす可能性があります。こうした競合状態を避けるため、実装は、[Batching processor](#batching-processor)のような並行処理を行う場合には`logRecord`のクローンを使うことを利用者に推奨すべきです（SHOULD）。

#### Enabled

`Enabled`は、[`Logger.Enabled`](/works/otel-specs-ja/spec/logs/api/#enabled)経由のフィルタリングをサポートするために、`LogRecordProcessor`が実装してもよい（MAY）操作です。

**パラメータ:**

* 呼び出し元が明示的に渡した、または現在の[コンテキスト](/works/otel-specs-ja/spec/context/)
* `Logger`に関連付けられた[計装スコープ](/works/otel-specs-ja/spec/logs/data-model/#field-instrumentationscope)
* 呼び出し元が渡した[Severity Number](/works/otel-specs-ja/spec/logs/data-model/#field-severitynumber)
* 呼び出し元が渡した[Event Name](/works/otel-specs-ja/spec/logs/data-model/#field-eventname)

**戻り値:** `Boolean`

実装は、与えられたパラメータに対して（もし生成されるとしたら）`LogRecord`がフィルタリングされて除外されるべき場合に`false`を返すべきです。設定待ちのような不確定な状態については、既定で`true`を返すべきです。

`Enabled`の内部でパラメータに加えた変更は、呼び出し元に伝播してはなりません（MUST NOT）。パラメータはイミュータブルであるか、値渡しされます。

この操作は通常同期的に呼び出されるため、ブロックしたり例外をスローするべきではありません。

フィルタリングを担い`Enable`操作をサポートする`LogRecordProcessor`の実装は、[`OnEmit`](#onemit)がフィルタリングを個別に処理することを保証すべきです。APIの利用者は、[LogRecordの発行](/works/otel-specs-ja/spec/logs/api/#logrecordの発行)を呼び出す前に[`Enabled`](/works/otel-specs-ja/spec/logs/api/#enabled)を呼び出すことを期待されていません。さらに、`OnEmit`と`Enabled`のフィルタリングロジックは異なることがあります。

他の`LogRecordProcessor`（フィルタリングを行う場合がある）をラップする`LogRecordProcessor`の実装は、可能であればラップしているプロセッサーの`Enabled`に委譲する形で`Enabled`を実装できます。ただし、そうしたプロセッサーの`OnEmit`の実装は、ラップしているプロセッサーの`Enabled`を呼び出すべきではありません。`OnEmit`はフィルタリングを個別に処理する責任を持つためです。

#### ShutDown

プロセッサーをシャットダウンします。SDKがシャットダウンされるときに呼び出されます。これは、プロセッサーが必要なクリーンアップを行う機会です。

`Shutdown`は、`LogRecordProcessor`インスタンスごとに1回だけ呼び出されるべきです（SHOULD）。`Shutdown`の呼び出し後、`OnEmit`への以降の呼び出しは許可されません。SDKは、可能であればこれらの呼び出しを穏やかに無視すべきです（SHOULD）。

`Shutdown`は、成功したか、失敗したか、タイムアウトしたかを呼び出し元に知らせる手段を提供すべきです（SHOULD）。

`Shutdown`は、`ForceFlush`の効果を含まなければなりません（MUST）。

`Shutdown`は、一定のタイムアウト内に完了または中断すべきです（SHOULD）。`Shutdown`は、ブロッキングAPIとして実装しても、コールバックやイベントを通じて呼び出し元に通知する非同期APIとして実装してもかまいません。OpenTelemetry SDKの作者は、シャットダウンのタイムアウトを設定可能にするかどうかを決めてもかまいません。

#### ForceFlush

これは、`ForceFlush`の呼び出し以前に`LogRecordProcessor`がイベントを受け取っていた`LogRecord`に関連するすべての作業を、このメソッドから戻る前になるべく速やかに完了すべき（SHOULD）ことを示すヒントです。

特に、`LogRecordProcessor`に関連付けられたエクスポーターがある場合、まだエクスポートしていないすべての`LogRecord`についてそのエクスポーターの`Export`を呼び出し、続いてその`ForceFlush`を呼び出すべきです（SHOULD）。[組み込みのLogRecordProcessor](#組み込みのプロセッサー)はそうしなければなりません（MUST）。タイムアウトが指定されている場合（後述）、`LogRecordProcessor`はすべての呼び出しを完了させることよりもタイムアウトを守ることを優先しなければなりません（MUST）。この目標を達成するため、行っている一部またはすべての`Export`や`ForceFlush`の呼び出しをスキップまたは中断してもよい（MAY）です。

`ForceFlush`は、成功したか、失敗したか、タイムアウトしたかを呼び出し元に知らせる手段を提供すべきです（SHOULD）。

`ForceFlush`は、一部のFaaSプロバイダーのように、呼び出し後にプロセスが一時停止される可能性があるが`LogRecordProcessor`が発行済みの`LogRecord`をまだエクスポートしていないような、絶対に必要な場合にのみ呼び出されるべきです（SHOULD）。

`ForceFlush`は、一定のタイムアウト内に完了または中断すべきです（SHOULD）。`ForceFlush`は、ブロッキングAPIとして実装しても、コールバックやイベントを通じて呼び出し元に通知する非同期APIとして実装してもかまいません。OpenTelemetry SDKの作者は、フラッシュのタイムアウトを設定可能にするかどうかを決めてもかまいません。

### 組み込みのプロセッサー

標準のOpenTelemetry SDKは、以下に説明するシンプルプロセッサーとバッチプロセッサーの両方を実装しなければなりません（MUST）。

その他の一般的な処理シナリオについては、まず[OpenTelemetry Collector](../../overview/#collector)でのプロセス外実装を検討すべきです（SHOULD）。

この文書で定義される追加のプロセッサーは、SDKパッケージによって提供されるべきです（SHOULD）。

#### Simple processor

これは、完了したログを渡し、完了した時点でエクスポート用の`ReadableLogRecord`表現を設定済みの[LogRecordExporter](#logrecordexporter)に渡す`LogRecordProcessor`の実装です。

このプロセッサーは、`LogRecordExporter`の`Export`への呼び出しを同期化し、並行して呼び出されないことを保証しなければなりません（MUST）。

**設定可能なパラメータ:**

* `exporter` - `LogRecord`が送られるエクスポーター。

#### Batching processor

これは、`LogRecord`のバッチを作成し、エクスポート用の`ReadableLogRecord`表現を設定済みの`LogRecordExporter`に渡す`LogRecordProcessor`の実装です。

このプロセッサーは、`LogRecordExporter`の`Export`への呼び出しを同期化し、並行して呼び出されないことを保証しなければなりません（MUST）。

**設定可能なパラメータ:**

* `exporter` - `LogRecord`が送られるエクスポーター。
* `maxQueueSize` - 最大キューサイズ。このサイズに達すると、ログは破棄されます。既定値は`2048`です。
* `scheduledDelayMillis` - 連続する2回のエクスポートの間隔（ミリ秒）。既定値は`1000`です。
* `exportTimeoutMillis` - エクスポートがキャンセルされるまでに実行できる時間。既定値は`30000`です。
* `maxExportBatchSize` - 各エクスポートの最大バッチサイズ。`maxQueueSize`以下でなければなりません。既定値は`512`です。

#### Event to span event bridge

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

これは、[Event](/works/otel-specs-ja/spec/logs/data-model/#events)を現在のスパン上のスパンイベントに変換する`LogRecordProcessor`の実装です。

このプロセッサーはSDKによって提供されるべきです（SHOULD）。

このプロセッサーは、以下の条件すべてが満たされる場合、かつその場合にのみ、`LogRecord`をスパンイベントにブリッジしなければなりません（MUST）。

* その`LogRecord`が空でない[Event Name](/works/otel-specs-ja/spec/logs/data-model/#field-eventname)を持つ。
* その`LogRecord`が有効な[TraceId](/works/otel-specs-ja/spec/logs/data-model/#field-traceid)と[SpanId](/works/otel-specs-ja/spec/logs/data-model/#field-spanid)を持つ。
* 解決済みの[コンテキスト](/works/otel-specs-ja/spec/context/)が、`IsRecording`が`true`である現在のスパンを含む。
* その`LogRecord`の`TraceId`と`SpanId`が、解決済みの`Context`における現在のスパンの`TraceId`と`SpanId`に等しい。

これらの条件のいずれかが満たされない場合、そのプロセッサーは何もしてはなりません（MUST）。

`LogRecord`がブリッジされる場合、そのプロセッサーは以下のマッピングでちょうど1つのスパンイベントを追加しなければなりません（MUST）。

* スパンイベント名は、`LogRecord`の[Event Name](/works/otel-specs-ja/spec/logs/data-model/#field-eventname)でなければなりません（MUST）。
* `LogRecord`に[Timestamp](/works/otel-specs-ja/spec/logs/data-model/#field-timestamp)が設定されている場合、それがスパンイベントのタイムスタンプとして使われなければなりません（MUST）。そうでなく、`LogRecord`に[ObservedTimestamp](/works/otel-specs-ja/spec/logs/data-model/#field-observedtimestamp)が設定されている場合は、それがスパンイベントのタイムスタンプとして使われなければなりません（MUST）。
* すべての`LogRecord`の[Attributes](/works/otel-specs-ja/spec/logs/data-model/#field-attributes)は、スパンイベントの属性としてスパンイベントにコピーされなければなりません（MUST）。

`LogRecord`をスパンイベントにブリッジすることは、その`LogRecord`が通常のログ処理パイプラインを継続して通過することを妨げてはなりません（MUST NOT）。

**設定可能なパラメータ:** なし。

## LogRecordExporter

`LogRecordExporter`は、OpenTelemetry SDKに組み込んでテレメトリーデータの送信をサポートできるようにするために、プロトコル固有のエクスポーターが実装しなければならないインターフェースを定義します。

このインターフェースの目標は、プロトコル依存のテレメトリーエクスポーターの実装負担を最小化することです。プロトコルエクスポーターは、主にシンプルなテレメトリーデータのエンコーダーおよび送信者であることが期待されます。

各実装は、SDKがエクスポーターに要求する並行性の特性を文書化しなければなりません（MUST）。

### LogRecordExporterの操作

`LogRecordExporter`は、以下の関数をサポートしなければなりません（MUST）。

#### Export

[ReadableLogRecord](#readablelogrecord)のバッチをエクスポートします。この関数を実装するプロトコルエクスポーターは、通常データをシリアライズして宛先に送信することが期待されます。

`Export`は、同一のエクスポーターインスタンスに対する他の`Export`呼び出しと並行して呼び出されるべきではありません（SHOULD NOT）。

実装によっては、エクスポートの結果は`Export`呼び出しの戻り値ではなく、非同期タスクの完了を通知するための言語固有の方法でプロセッサーに返されることがあります。つまり、あるエクスポーターのインスタンスに対して`Export`が並行して呼び出されるべきではないとしても、エクスポートというタスク自体を並行して行えないということではありません。これをどのように行うかは、この仕様の範囲外です。

`Export`は無期限にブロックしてはならず（MUST NOT）、その呼び出しがエラー結果（`Failure`）でタイムアウトするまでの合理的な上限がなければなりません（MUST）。

並行リクエストとリトライロジックはエクスポーターの責任です。既定のSDKの`LogRecordProcessor`はリトライロジックを実装すべきではありません（SHOULD NOT）。必要なロジックは、ログの送信先である特定のプロトコルとバックエンドに大きく依存する可能性が高いためです。例えば、[OpenTelemetry Protocol（OTLP）仕様](https://opentelemetry.io/docs/specs/otlp/)は、並行リクエストの送信とリクエストのリトライの両方についてロジックを定義しています。

**パラメータ:**

* `batch` - [ReadableLogRecord](#readablelogrecord)のバッチ。バッチの正確なデータ型は言語固有であり、典型的にはリストなどの何らかの型です。例えばJavaのログでは、典型的には`Collection<LogRecordData>`になります。

**戻り値:** `ExportResult`

`Export`の戻り値は実装固有です。その言語にとって慣用的な方法で、エクスポーターは`ExportResult`をプロセッサーに送らなければなりません。`ExportResult`は`Success`または`Failure`のいずれかの値を持ちます。

* `Success` - バッチが正常にエクスポートされました。プロトコルエクスポーターの場合、これは通常データがワイヤー上で送信され、宛先サーバーに配信されたことを意味します。
* `Failure` - エクスポートが失敗しました。バッチは破棄されなければなりません。例えば、バッチに不正なデータが含まれていてシリアライズできない場合にこれが起こり得ます。

例えば、Javaでは`Export`の戻り値は、完了時に`ExportResult`オブジェクトを返すFutureになります。一方Erlangでは、エクスポーターは特定のバッチに対する`ExportResult`を含むメッセージをプロセッサーに送ります。

#### ForceFlush

これは、`ForceFlush`の呼び出し以前にエクスポーターが受け取っていた[ReadableLogRecord](#readablelogrecord)のエクスポートを、このメソッドから戻る前になるべく速やかに完了すべき（SHOULD）ことを示すヒントです。

`ForceFlush`は、成功したか、失敗したか、タイムアウトしたかを呼び出し元に知らせる手段を提供すべきです（SHOULD）。

`ForceFlush`は、一部のFaaSプロバイダーのように、呼び出し後にプロセスが一時停止される可能性があるが、エクスポーターが発行済みの`ReadableLogRecord`をまだエクスポートしていないような、絶対に必要な場合にのみ呼び出されるべきです（SHOULD）。

`ForceFlush`は、一定のタイムアウト内に完了または中断すべきです（SHOULD）。`ForceFlush`は、ブロッキングAPIとして実装しても、コールバックやイベントを通じて呼び出し元に通知する非同期APIとして実装してもよい（MAY）です。[OpenTelemetry SDK](../../overview/#sdk)の作者は、フラッシュのタイムアウトを設定可能にするかどうかを決めてもよい（MAY）です。

#### Shutdown

エクスポーターをシャットダウンします。SDKがシャットダウンされるときに呼び出されます。これは、エクスポーターが必要なクリーンアップを行う機会です。

Shutdownは、`LogRecordExporter`インスタンスごとに1回だけ呼び出されるべきです（SHOULD）。`Shutdown`の呼び出し後、以降の`Export`の呼び出しは許可されず、Failure結果を返すべきです（SHOULD）。

`Shutdown`は、（宛先が利用できずデータのフラッシュを試みる場合などに）無期限にブロックすべきではありません（SHOULD NOT）。[OpenTelemetry SDK](../../overview/#sdk)の作者は、シャットダウンのタイムアウトを設定可能にするかどうかを決めてもよい（MAY）です。

- [OTEP0150 ロギングライブラリSDKプロトタイプ仕様](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.60.0/oteps/logs/0150-logging-library-sdk.md)

## 並行処理に関する要件

**ステータス**: [安定（Stable）](../../document-status/)

並行実行をサポートする言語では、Logging SDKは特定の保証と安全性を提供します。

**LoggerProvider** - Loggerの作成、`ForceFlush`、`Shutdown`は並行して呼び出しても安全でなければなりません（MUST）。

**Logger** - すべてのメソッドは並行して呼び出しても安全でなければなりません（MUST）。

**LogRecordExporter** - `ForceFlush`と`Shutdown`は並行して呼び出しても安全でなければなりません（MUST）。

## Self-observability

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

Logs SDKは、[SDKのself-observability](/works/otel-specs-ja/spec/self-observability/)をサポートすべきです（SHOULD）。

