# 機能設計書 65-OpenTelemetryメトリクスレポーター

## 概要

本ドキュメントは、Apache FlinkのOpenTelemetryメトリクスレポーター機能（flink-metrics-otel モジュール）の設計仕様を記載する。

### 本機能の処理概要

OpenTelemetryメトリクスレポーターは、Flinkランタイムで収集されたメトリクス（Counter、Gauge、Histogram、Meter）をOpenTelemetry Protocol（OTLP）経由でエクスポートする機能である。

**業務上の目的・背景**：OpenTelemetryはCNCF（Cloud Native Computing Foundation）が推進する観測可能性のオープンスタンダードであり、多くの監視ベンダー（Jaeger、Prometheus、Grafana、各種クラウドベンダー等）が対応している。本機能によりベンダーロックインを避けつつ、様々な監視バックエンドとの連携が可能になる。

**機能の利用シーン**：
- クラウドネイティブ環境での標準化された観測可能性の実現
- 複数の監視バックエンドへの柔軟な切り替え
- トレーシング・メトリクス・ログの統合観測
- マイクロサービスアーキテクチャでの分散監視

**主要な処理内容**：
1. メトリクスの登録・削除通知の受信とメタデータの生成
2. 定期的なレポート間隔でのメトリクス収集とOTLP形式への変換
3. gRPCまたはHTTP経由でのOTLPエクスポート
4. Counter用のデルタ計算（差分送信）

**関連システム・外部連携**：
- OpenTelemetry Collector
- 各種OTLPバックエンド（Jaeger、Prometheus等）
- OpenTelemetry SDK（io.opentelemetry）

**権限による制御**：エンドポイントによる認証（設定依存）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面を持たないバックエンド処理機能 |

## 機能種別

データ連携（メトリクスのOpenTelemetryへのエクスポート）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| exporter.endpoint | String | Yes | OTLPエンドポイントURL | 空不可 |
| exporter.protocol | Enum(gRPC/HTTP) | No | エクスポートプロトコル | デフォルト: gRPC |
| exporter.timeout | Duration | No | エクスポートタイムアウト | Duration形式 |
| service.name | String | No | サービス名（リソース属性） | - |
| service.version | String | No | サービスバージョン（リソース属性） | - |

### 入力データソース

- Flinkランタイムから通知されるメトリクス（Counter、Gauge、Histogram、Meter）
- 設定ファイル（flink-conf.yaml）からのレポーター設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name | String | メトリクス名（flink.プレフィックス付き論理スコープ） |
| attributes | Map<String, String> | メトリクス属性（job_id、task_name等） |
| value | Number | メトリクス値 |
| startTimeUnixNano | Long | 収集開始時刻（ナノ秒） |
| timeUnixNano | Long | 収集時刻（ナノ秒） |

### 出力先

OTLPエンドポイント（gRPCまたはHTTP）

## 処理フロー

### 処理シーケンス

```
1. レポーター初期化（open）
   └─ リソース属性の設定（service.name/version）
   └─ プロトコルに応じたエクスポーター生成
   └─ エンドポイント/タイムアウトの設定

2. メトリクス登録（notifyOfAddedMetric）
   └─ 論理スコープ名の生成（flink.プレフィックス）
   └─ 変数からの属性マップ生成
   └─ MetricMetadataの作成と登録

3. 定期レポート（report）
   └─ collectAllMetrics()でOTLP形式に変換
   └─ exporter.export()で非同期送信
   └─ 完了コールバックでログ出力

4. メトリクス削除（notifyOfRemovedMetric）
   └─ 内部マップからの削除
   └─ lastValueSnapshotsからの削除

5. シャットダウン（close）
   └─ exporter.flush()
   └─ 最終レポート待機
   └─ exporter.close()
```

### フローチャート

```mermaid
flowchart TD
    A[開始: report] --> B[collectAllMetrics]
    B --> C[Counter変換（デルタ計算）]
    C --> D[Gauge変換]
    D --> E[Meter変換（デルタ計算）]
    E --> F[Histogram変換]
    F --> G[exporter.export]
    G --> H{送信結果}
    H -->|成功| I[デバッグログ]
    H -->|失敗| J[警告ログ]
    I --> K[スナップショット更新]
    J --> K
    K --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | エンドポイント必須 | exporter.endpointは必須設定 | open()時 |
| BR-02 | デルタ計算 | CounterとMeterは差分値を送信 | collectAllMetrics時 |
| BR-03 | デフォルトgRPC | プロトコル未指定時はgRPCを使用 | open()時 |
| BR-04 | 論理スコープ名 | メトリクス名は"flink."プレフィックス付き論理スコープ | 登録時 |
| BR-05 | 変数名正規化 | 変数名から角括弧を除去 | タグ生成時 |

### 計算ロジック

Counter/Meterのデルタ計算:
- currentValue - lastValue = delta
- 初回はlastValue = 0として計算
- lastValueSnapshotsマップで前回値を保持

## データベース操作仕様

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | 設定エラー | エンドポイント未設定 | 設定を修正 |
| Exception | エクスポートエラー | export()呼び出し失敗 | エラーログ出力 |
| CompletableResultCode失敗 | 送信エラー | 非同期送信失敗 | 警告ログ出力 |

### リトライ仕様

- リトライは実装されていない
- 失敗時は次回のレポートサイクルで再送信

## トランザクション仕様

- 非同期送信のため、CompletableResultCodeで完了を追跡
- close()時は最大1分待機

## パフォーマンス要件

- 非同期エクスポートによる低レイテンシ
- デルタ計算により送信データ量を最適化
- バッチ送信（Collection<MetricData>）

## セキュリティ考慮事項

- gRPC/HTTPSによる暗号化通信をサポート
- エンドポイントの認証は外部設定に依存
- service.name/versionによるリソース識別

## 備考

- OpenTelemetry SDK（io.opentelemetry）に依存
- トレースレポーター（OpenTelemetryTraceReporter）も同モジュールに含まれる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MetricMetadata.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/MetricMetadata.java` | メトリクス名と属性マップを保持 |
| 1-2 | OpenTelemetryReporterOptions.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/OpenTelemetryReporterOptions.java` | 設定オプション定義 |

**読解のコツ**: MetricMetadataはシンプルなデータクラス。OpenTelemetryReporterOptionsはConfigOptionを使った型安全な設定定義。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | OpenTelemetryMetricReporterFactory.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/OpenTelemetryMetricReporterFactory.java` | ファクトリクラス |

**主要処理フロー**:
1. **29-32行目**: createMetricReporter()でOpenTelemetryMetricReporterインスタンスを生成

#### Step 3: 基底クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | OpenTelemetryReporterBase.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/OpenTelemetryReporterBase.java` | リソース設定の共通処理 |

**主要処理フロー（OpenTelemetryReporterBase.java）**:
- **41-43行目**: コンストラクタでデフォルトリソース設定
- **45-68行目**: open()でservice.name/versionの設定

#### Step 4: メインレポーター実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | OpenTelemetryMetricReporter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/OpenTelemetryMetricReporter.java` | メインレポーター実装 |

**主要処理フロー（OpenTelemetryMetricReporter.java）**:
- **93-122行目**: open()でプロトコル判定とエクスポーター生成
- **135-174行目**: notifyOfAddedMetric()でメトリクス登録
- **214-256行目**: collectAllMetrics()でOTLP変換
- **272-296行目**: report()で非同期エクスポート

#### Step 5: メトリクス変換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | OpenTelemetryMetricAdapter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/OpenTelemetryMetricAdapter.java` | OTLP形式への変換 |
| 5-2 | VariableNameUtil.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/VariableNameUtil.java` | 変数名正規化 |

### プログラム呼び出し階層図

```
OpenTelemetryMetricReporterFactory.createMetricReporter()
    │
    └─ new OpenTelemetryMetricReporter()
           │
           ├─ OpenTelemetryReporterBase（継承）
           │      └─ open() → Resource設定
           │
           ├─ open() → Exporter生成
           │      ├─ OtlpHttpMetricExporter.builder()
           │      └─ OtlpGrpcMetricExporter.builder()
           │
           ├─ notifyOfAddedMetric()
           │      └─ MetricMetadata生成
           │
           └─ report() [Scheduled]
                  │
                  ├─ collectAllMetrics() [MetricProducer]
                  │      ├─ OpenTelemetryMetricAdapter.convertCounter()
                  │      ├─ OpenTelemetryMetricAdapter.convertGauge()
                  │      ├─ OpenTelemetryMetricAdapter.convertMeter()
                  │      └─ OpenTelemetryMetricAdapter.convertHistogram()
                  │
                  └─ exporter.export(Collection<MetricData>)
```

### データフロー図

```
[入力]                         [処理]                              [出力]

Flink Metrics          ┌─────────────────────────┐
  (Counter/Gauge/      │ OpenTelemetryMetricReporter │     OTLP Endpoint
   Histogram/Meter) ──▶│                         │──▶  (gRPC/HTTP)
                       │   ┌─────────────────┐   │
                       │   │ MetricAdapter   │   │
Config                 │   │   OTLP変換      │   │
  (endpoint, protocol) │   └─────────────────┘   │
           ────────────▶   ┌─────────────────┐   │
                       │   │ MetricExporter  │   │
                       │   └─────────────────┘   │
                       └─────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| OpenTelemetryMetricReporter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | メインレポーター実装 |
| OpenTelemetryMetricReporterFactory.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | ファクトリクラス |
| OpenTelemetryReporterBase.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | 基底クラス |
| OpenTelemetryReporterOptions.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | 設定オプション |
| OpenTelemetryMetricAdapter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | OTLP変換 |
| MetricMetadata.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | メタデータ |
| VariableNameUtil.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/metrics/otel/` | ソース | 変数名ユーティリティ |
| OpenTelemetryTraceReporter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/traces/otel/` | ソース | トレースレポーター |
| OpenTelemetryEventReporter.java | `flink-metrics/flink-metrics-otel/src/main/java/org/apache/flink/events/otel/` | ソース | イベントレポーター |
