# 帳票設計書 2-ConsoleSink メトリクスレポート

## 概要

本ドキュメントは、Apache Spark の MetricsSystem における ConsoleSink が出力するコンソール形式メトリクスレポートの設計書である。Dropwizard Metrics ライブラリの ConsoleReporter を利用し、Spark の各コンポーネントのメトリクス情報を定期的に標準出力（System.out）へテキスト形式で出力する。

### 本帳票の処理概要

ConsoleSink メトリクスレポートは、Spark の内部メトリクスデータを標準出力にテキスト形式で定期出力する帳票機能である。

**業務上の目的・背景**：Spark アプリケーションの開発・デバッグフェーズにおいて、メトリクス情報をリアルタイムに確認する必要がある。コンソール出力は追加のインフラストラクチャ（ファイルシステム、外部サーバ等）を必要とせず、最も手軽にメトリクスを確認できる手段である。特にローカル開発環境やテスト実行時のメトリクス確認に適している。

**帳票の利用シーン**：(1) ローカル環境での Spark アプリケーション開発時にメトリクスをリアルタイム確認する場合、(2) テスト実行時にパフォーマンスメトリクスを簡易的に監視する場合、(3) 外部監視システムを構築する前の暫定的なメトリクス確認手段として利用する場合。

**主要な出力内容**：
1. Gauge メトリクス（JVM メモリ使用量、アクティブタスク数等）の現在値
2. Counter メトリクス（完了タスク数、失敗タスク数等）の累積値
3. Histogram メトリクス（タスク実行時間分布等）の統計サマリー
4. Meter メトリクス（スループット等）のレート情報
5. Timer メトリクス（API 応答時間等）の統計値とレート

**帳票の出力タイミング**：MetricsSystem の start() 呼び出し時に定期出力が開始され、設定された間隔（デフォルト10秒）で自動的に標準出力へ出力される。report() メソッドにより手動での即時出力も可能。

**帳票の利用者**：Spark アプリケーション開発者、テストエンジニア、デバッグ担当者。

## 帳票種別

メトリクスレポート（コンソール出力型の定期モニタリングレポート）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | 設定ファイル駆動 | N/A | metrics.properties の設定により標準出力へ自動出力 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（標準出力ストリーム） |
| 出力方法 | System.out への定期書き込み |
| 文字コード | システムデフォルト |

### コンソール出力固有設定

| 項目 | 内容 |
|-----|------|
| 時間単位（Duration） | ミリ秒（MILLISECONDS） |
| レート単位 | 秒あたり（SECONDS） |
| 出力フォーマット | Dropwizard ConsoleReporter 標準フォーマット |

## 帳票レイアウト

### レイアウト概要

ConsoleReporter は全メトリクスを種別ごとにグループ化し、一括してテキスト出力する。

```
-- Gauges -------------------------------------------------------
{gauge_name}
             value = {value}

-- Counters -----------------------------------------------------
{counter_name}
             count = {count}

-- Histograms ---------------------------------------------------
{histogram_name}
             count = {count}
               min = {min}
               max = {max}
              mean = {mean}
            stddev = {stddev}
            median = {median}
              75% <= {p75}
              95% <= {p95}
              ...

-- Meters -------------------------------------------------------
{meter_name}
             count = {count}
         mean rate = {mean_rate} events/second
     1-minute rate = {1m_rate} events/second
     ...

-- Timers -------------------------------------------------------
(Histogram + Meter の組み合わせ)
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | タイムスタンプ | 出力日時 | システム時刻 | 日時文字列 |
| 2 | セクション区切り | メトリクス種別の区切り線 | 固定文字列 | "-- {種別} ---" |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | メトリクス名 | メトリクスの識別名 | MetricRegistry のキー | 文字列 | 可変 |
| 2 | メトリクス値 | 各メトリクス固有の値群 | MetricRegistry の各メトリクスオブジェクト | 数値/文字列 | 可変 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| N/A | フッターなし | ConsoleReporter はフッターを出力しない | N/A | N/A |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| MetricRegistry 登録 | MetricRegistry に登録されている全メトリクスが対象 | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | メトリクス種別 | 固定順（Gauges, Counters, Histograms, Meters, Timers） |
| 2 | メトリクス名 | 昇順（SortedMap） |

### 改ページ条件

コンソール出力のため改ページなし。

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照しない。Dropwizard MetricRegistry のインメモリデータを直接参照する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A（MetricRegistry） | メトリクスデータの取得元 | N/A |

### テーブル別参照項目詳細

#### MetricRegistry（インメモリ）

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| Gauges | Gauges セクション | registry.getGauges() | 全 Gauge を出力 |
| Counters | Counters セクション | registry.getCounters() | 全 Counter を出力 |
| Histograms | Histograms セクション | registry.getHistograms() | 全 Histogram を出力 |
| Meters | Meters セクション | registry.getMeters() | 全 Meter を出力 |
| Timers | Timers セクション | registry.getTimers() | 全 Timer を出力 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| レート変換 | 元値 / 秒 | Dropwizard 既定 | convertRatesTo(TimeUnit.SECONDS) |
| Duration変換 | 元値(ns) -> ms | Dropwizard 既定 | convertDurationsTo(TimeUnit.MILLISECONDS) |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[MetricsSystem.start] --> B[ConsoleSink.start]
    B --> C[ConsoleReporter.start - 定期スケジュール登録]
    C --> D{定期タイマー発火}
    D --> E[ConsoleReporter.report]
    E --> F[MetricRegistry からメトリクス取得]
    F --> G[System.out にテキスト出力]
    G --> D
    H[MetricsSystem.stop] --> I[ConsoleSink.stop]
    I --> J[ConsoleReporter.stop - スケジュール停止]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ポーリング間隔エラー | pollUnit と pollPeriod の組み合わせが最小ポーリング間隔（1秒）未満 | IllegalArgumentException: Polling period ... below than minimal polling period | 設定値を1秒以上に変更 |
| 数値変換エラー | period 設定値が数値でない | NumberFormatException | 整数値を設定 |
| TimeUnit 変換エラー | unit 設定値が不正な TimeUnit 名 | IllegalArgumentException | SECONDS, MINUTES 等の有効な値を設定 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | メトリクス数に依存（通常数十〜数百メトリクス） |
| 目標出力時間 | 定期間隔内に完了（デフォルト10秒以内） |
| 同時出力数上限 | 1（単一スレッドでの定期レポート） |

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

- 標準出力への出力であるため、コンソールログの取り扱いに注意が必要
- メトリクスデータにはクラスタの内部状態情報が含まれるため、標準出力がリダイレクトされるログファイルのアクセス権限を適切に管理すること

## 備考

- 設定は `metrics.properties` ファイルで行う。設定例：
  ```
  *.sink.console.class=org.apache.spark.metrics.sink.ConsoleSink
  *.sink.console.period=10
  *.sink.console.unit=SECONDS
  ```
- ConsoleReporter は Dropwizard Metrics ライブラリの機能を利用している
- 大量のメトリクスが登録されている場合、コンソール出力が膨大になる可能性がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Sink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/Sink.scala` | Sink トレイトの3メソッド定義を確認（行20-24） |

**読解のコツ**: ConsoleSink は CsvSink と同じ Sink トレイトを実装しており、基本構造は同一である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MetricsSystem.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala` | registerSinks()（行199-240）での Sink インスタンス化と、start()（行97-106）での起動処理を確認 |

**主要処理フロー**:
1. **行199-240**: 設定ベースで ConsoleSink をリフレクション経由でインスタンス化
2. **行97-106**: sinks.foreach(_.start()) で ConsoleSink.start() を呼び出す

#### Step 3: ConsoleSink の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ConsoleSink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/ConsoleSink.scala` | クラス全体（行27-63）を通読。CsvSink との差異は出力先が標準出力であること、directory 設定が不要であること |

**主要処理フロー**:
- **行27-28**: Properties と MetricRegistry をコンストラクタ引数として受け取る
- **行29-33**: デフォルト値と設定キーの定義（period=10, unit=SECONDS）
- **行35-43**: Properties から period と unit を読み込み
- **行45**: MetricsSystem.checkMinimalPollingPeriod() でポーリング間隔を検証
- **行47-50**: ConsoleReporter.forRegistry() でレポーターを構築。Duration はミリ秒、Rate は秒単位。build() に引数なし（System.out がデフォルト出力先）
- **行52-54**: start() で ConsoleReporter の定期レポートを開始
- **行56-58**: stop() で定期レポートを停止
- **行60-62**: report() で即時レポートを実行

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

```
MetricsSystem.start()
    |
    +-- registerSinks()
    |       +-- Utils.classForName("ConsoleSink")
    |       +-- ConsoleSink.<init>(properties, registry)
    |               +-- MetricsSystem.checkMinimalPollingPeriod()
    |               +-- ConsoleReporter.forRegistry(registry).build()
    |
    +-- sinks.foreach(_.start())
            +-- ConsoleSink.start()
                    +-- ConsoleReporter.start(pollPeriod, pollUnit)
                            +-- [定期スケジュール] ConsoleReporter.report()
                                    +-- MetricRegistry.getGauges/getCounters/...
                                    +-- System.out.println(...)
```

### データフロー図

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

MetricRegistry         ConsoleSink                  標準出力 (System.out)
(Gauges,               +-- ConsoleReporter           -- Gauges --
 Counters,                 +-- forRegistry()          {name} = {value}
 Histograms,               +-- convertDurations(ms)  -- Counters --
 Meters,                   +-- convertRates(/s)      {name} count = {n}
 Timers)                   +-- build()               ...

Properties             設定読み込み
(period, unit)         +-- pollPeriod, pollUnit
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Sink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/Sink.scala` | ソース | Sink トレイト定義 |
| ConsoleSink.scala | `core/src/main/scala/org/apache/spark/metrics/sink/ConsoleSink.scala` | ソース | コンソール出力 Sink の実装 |
| MetricsSystem.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsSystem.scala` | ソース | Sink の登録・管理・起動 |
| MetricsConfig.scala | `core/src/main/scala/org/apache/spark/metrics/MetricsConfig.scala` | ソース | metrics.properties の読み込み |
