# 機能設計書 12-メトリクスシステム

## 概要

本ドキュメントは、Apache SparkのメトリクスシステムについてCoda Haleメトリクスライブラリに基づくパフォーマンス指標の収集・報告の仕組みを記述した機能設計書である。

### 本機能の処理概要

Sparkアプリケーション内の各コンポーネント（master, worker, executor, driver等）のパフォーマンス指標を「Source」から収集し、設定された「Sink」へ定期的に報告する仕組みを提供する。

**業務上の目的・背景**：分散処理システムの運用において、各コンポーネントの健全性やパフォーマンスをリアルタイムに把握することが重要である。メトリクスシステムは、JVMメトリクス、Executor統計、シャッフル情報など多様な指標を一元的に収集し、Prometheus、Graphite、JMX等の外部監視システムへ報告する基盤を提供する。

**機能の利用シーン**：(1) 運用監視ダッシュボードでのリアルタイムメトリクス表示、(2) アラート設定によるパフォーマンス異常検知、(3) キャパシティプランニングのためのリソース使用量トレンド分析、(4) Web UIでのメトリクスAPI（/metrics/json、/metrics/prometheus）エンドポイント提供。

**主要な処理内容**：
1. MetricsConfigによる設定ファイル（metrics.properties）の読み込みと解析
2. Source（メトリクス生成元）の登録とMetricRegistryへの紐付け
3. Sink（メトリクス出力先）の登録と定期的なポーリング起動
4. MetricsServlet/PrometheusServletによるHTTPエンドポイント提供
5. インスタンス（master, worker, executor, driver等）ごとのメトリクス名前空間管理

**関連システム・外部連携**：Prometheus、Graphite、JMX、CSV、Slf4j等のSink出力先。Web UIのメトリクスエンドポイント。

**権限による制御**：特になし。メトリクスエンドポイントはWeb UIのセキュリティ設定に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | All Jobs（全ジョブ一覧） | 補助機能 | ジョブのタスク完了数・失敗数等のメトリクスを収集し進捗バーとして表示 |
| 4 | Stage Detail（ステージ詳細） | 補助機能 | タスクメトリクスの分布（パーセンタイル）をサマリーテーブルとして表示 |
| 9 | Environment（環境情報） | 補助機能 | メトリクスプロパティ（metrics.properties）をテーブル表示 |
| 10 | Executors（エグゼキュータ一覧） | 補助機能 | Executor Peak Memory Metricsを取得・表示 |

## 機能種別

データ収集 / 監視基盤

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| instance | String | Yes | メトリクスシステムのインスタンス種別 | master/worker/executor/driver/applications/shuffleService/applicationMaster |
| spark.metrics.conf | String | No | メトリクス設定ファイルパス | デフォルト: metrics.properties |
| spark.metrics.namespace | String | No | メトリクス名前空間 | - |
| [instance].source.[name].class | String | No | カスタムSourceクラス | 完全修飾クラス名 |
| [instance].sink.[name].class | String | No | Sinkクラス | 完全修飾クラス名 |

### 入力データソース

各コンポーネント内部のSource実装（JvmSource, MasterSource, WorkerSource, ExecutorSource等）からメトリクスを取得。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| メトリクス値 | Gauge/Counter/Histogram/Timer/Meter | Coda Haleメトリクスの各種型 |
| JSONメトリクス | String | /metrics/jsonエンドポイント経由のJSON出力 |
| Prometheusメトリクス | String | /metrics/prometheusエンドポイント経由のPrometheus形式出力 |

### 出力先

設定されたSinkに応じた出力先（Prometheus、Graphite、JMX、CSVファイル、Slf4jロガー、HTTPエンドポイント等）。

## 処理フロー

### 処理シーケンス

```
1. MetricsSystemの生成
   └─ createMetricsSystem(instance, conf)でインスタンス生成、MetricsConfig初期化
2. start()の呼び出し
   └─ StaticSourcesの登録、カスタムSourceの登録、Sinkの登録と開始
3. Sourceの登録
   └─ registerSource()でMetricRegistryにSourceを登録
4. メトリクス収集・報告サイクル
   └─ 各Sinkが設定されたポーリング間隔でSourceからメトリクスを取得し出力
5. stop()の呼び出し
   └─ 全Sinkの停止とMetricRegistryのクリーンアップ
```

### フローチャート

```mermaid
flowchart TD
    A[MetricsSystem生成] --> B[MetricsConfig初期化]
    B --> C[start]
    C --> D[StaticSources登録]
    D --> E[カスタムSource登録]
    E --> F[Sink登録]
    F --> G{Sink種別判定}
    G -->|servlet| H[MetricsServlet生成]
    G -->|prometheusServlet| I[PrometheusServlet生成]
    G -->|その他| J[通常Sink生成・開始]
    H --> K[Web UIハンドラとして公開]
    I --> K
    J --> L[定期ポーリング開始]
    L --> M[Source → Sink メトリクス転送]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-12-01 | インスタンス別設定 | メトリクス設定はインスタンス（master, worker等）ごとに独立して適用 | 全インスタンス |
| BR-12-02 | ワイルドカード設定 | "*"で全インスタンスに共通設定を適用可能 | 設定ファイル記述時 |
| BR-12-03 | メトリクス名構築 | driver/executorの場合は「appId.executorId.sourceName」形式 | driver/executorインスタンス |
| BR-12-04 | 最小ポーリング間隔 | Sinkのポーリング間隔は1秒以上であること | Sink設定時 |
| BR-12-05 | Servlet特別扱い | MetricsServletとPrometheusServletは通常のSinkとは別管理 | servlet/prometheusServlet設定時 |

### 計算ロジック

メトリクス名の構築ルール: `MetricRegistry.name(metricsNamespace, executorId, sourceName)` でドライバー/Executorの場合に名前空間を付与。それ以外のインスタンスではsourceNameのみを使用。

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IllegalArgumentException | メトリクスが既に登録済み | logInfoで記録し処理続行 |
| - | Exception | Sourceクラスのインスタンス化失敗 | logErrorで記録し処理続行 |
| - | Exception | Sinkクラスのインスタンス化失敗 | logErrorで記録し例外をスロー |
| - | IllegalArgumentException | ポーリング間隔が最小値未満 | 例外をスロー |
| - | IllegalStateException | 起動前にgetServletHandlersを呼び出し | requireで例外スロー |
| - | IllegalStateException | 既に起動中のMetricsSystemを再起動 | requireで例外スロー |

### リトライ仕様

リトライは行わない。Sourceの登録失敗時はログ出力のみで処理を続行する。Sinkの登録失敗時は例外をスローし起動を中断する。

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

該当なし

## パフォーマンス要件

メトリクス収集はポーリング方式で行われ、最小ポーリング間隔は1秒。メトリクスの登録・取得はCoda HaleのMetricRegistryを通じてスレッドセーフに行われる。

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

メトリクスエンドポイント（/metrics/json, /metrics/prometheus）はWeb UIのセキュリティ設定（ACL、SSL等）に従う。

## 備考

- MetricsSystemInstancesオブジェクトでインスタンス名の定数（MASTER, WORKER, EXECUTOR, DRIVER等）が定義されている
- Sinkコンストラクタは2引数版（Properties, MetricRegistry）をまず試行し、失敗時に3引数版（+SecurityManager）にフォールバック

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Source.scala | `core/src/main/scala/org/apache/spark/metrics/source/Source.scala` | Sourceトレイトの定義（sourceName, metricRegistry） |
| 1-2 | Sink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/Sink.scala` | Sinkトレイトの定義（start, stop, report） |

**読解のコツ**: Coda Hale（Dropwizard）Metricsライブラリの`MetricRegistry`がメトリクスの中央リポジトリ。Gauge, Counter, Histogram, Timer, Meterの5種類のメトリクス型を理解しておくとよい。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MetricsSystem.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala` | メインクラス。start(), registerSource(), registerSinks()の処理フロー |

**主要処理フロー**:
1. **71-72行目**: コンストラクタでinstance名とSparkConfを受け取る
2. **95行目**: MetricsConfigの初期化
3. **97-106行目**: start()でSource登録→Sink登録→Sink開始
4. **131-155行目**: buildRegistryName()でメトリクス名を構築
5. **161-171行目**: registerSource()でMetricRegistryにSourceを登録
6. **199-239行目**: registerSinks()でSinkをリフレクションで生成

#### Step 3: 設定管理層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MetricsConfig.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsConfig.scala` | metrics.propertiesの読み込みとインスタンス別設定の解析 |

#### Step 4: Sink実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MetricsServlet.scala | `core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala` | JSONメトリクスエンドポイントの実装 |
| 4-2 | PrometheusServlet.scala | `core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala` | Prometheus形式エンドポイントの実装 |

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

```
SparkEnv / SparkContext
    │
    ├─ MetricsSystem.createMetricsSystem(instance, conf)
    │      ├─ MetricsConfig.initialize() ─ metrics.properties読み込み
    │      │
    │      ├─ start()
    │      │    ├─ StaticSources.allSources.foreach(registerSource)
    │      │    ├─ registerSources() ─ リフレクションでカスタムSource生成
    │      │    │    └─ registerSource(source) ─ MetricRegistryに登録
    │      │    └─ registerSinks() ─ リフレクションでSink生成
    │      │         ├─ MetricsServlet (servlet)
    │      │         ├─ PrometheusServlet (prometheusServlet)
    │      │         └─ 通常Sink (start()で定期報告開始)
    │      │
    │      ├─ getServletHandlers() ─ Web UIにハンドラ提供
    │      │
    │      └─ stop()
    │           └─ Sink停止 + Registry全クリア
    │
    └─ 各Source (JvmSource, ExecutorSource等)
         └─ metricRegistry に各種メトリクス登録
```

### データフロー図

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

JVM情報              ───▶ JvmSource              ───▶ MetricRegistry
Executor統計         ───▶ ExecutorSource          ───▶      │
Master/Worker統計    ───▶ MasterSource等          ───▶      │
                                                              │
MetricRegistry ───▶ 各Sink ───▶ Prometheus / Graphite / JMX / CSV / HTTP
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MetricsSystem.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala` | ソース | メトリクスシステムのメインクラス |
| MetricsConfig.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsConfig.scala` | ソース | メトリクス設定の読み込み・管理 |
| Source.scala | `core/src/main/scala/org/apache/spark/metrics/source/Source.scala` | ソース | Sourceトレイト定義 |
| Sink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/Sink.scala` | ソース | Sinkトレイト定義 |
| MetricsServlet.scala | `core/src/main/scala/org/apache/spark/metrics/sink/MetricsServlet.scala` | ソース | JSONメトリクスHTTPエンドポイント |
| PrometheusServlet.scala | `core/src/main/scala/org/apache/spark/metrics/sink/PrometheusServlet.scala` | ソース | Prometheus形式HTTPエンドポイント |
| StaticSources.scala | `core/src/main/scala/org/apache/spark/metrics/source/StaticSources.scala` | ソース | JVM等の静的Source定義 |
