# 画面設計書 19-Batch Detail（バッチ詳細）

## 概要

本ドキュメントは、Apache Spark Application UIのStreamingタブにあるバッチ詳細画面の設計内容を記述する。本画面は特定バッチの出力オペレーション・ジョブ情報・ステージ・タスク状況を表示する。

### 本画面の処理概要

**業務上の目的・背景**：DStreamsストリーミングにおいて特定バッチの処理状況を詳細に確認するための画面である。各バッチは複数のOutput Operation（出力操作）で構成され、それぞれが複数のSpark Jobに対応する。運用者は本画面により、バッチ内の各出力操作の処理時間・ステータス、関連するSparkジョブの完了状況・失敗理由を確認でき、バッチレベルのトラブルシューティングが可能となる。Input Metadataの確認により、バッチに入力されたデータの詳細（Kafkaパーティション情報等）も確認できる。

**画面へのアクセス方法**：DStreamsストリーミング概要画面（No.18）のバッチ時刻リンクまたはタイムライングラフのクリックから遷移する。URLパラメータとしてid（バッチ時刻のミリ秒）が必要。

**主要な操作・処理内容**：
1. バッチサマリー（バッチ期間、入力データサイズ、スケジューリング遅延、処理時間、総遅延）を確認する
2. Input Metadata（入力ストリーム別のメタデータ記述）を確認する
3. Output Operation別のジョブテーブルを確認する
4. 各Spark Jobの実行時間・ステージ進捗・タスク進捗・エラー情報を確認する
5. Job IDリンクからジョブ詳細画面（No.2）へ遷移する
6. Output Operationの「+details」で処理の詳細情報を展開する

**画面遷移**：DStreamsストリーミング概要画面（No.18）から遷移してくる。本画面からジョブ詳細画面（No.2）へ遷移可能。

**権限による表示制御**：ACL設定が有効な場合、閲覧権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定バッチの出力オペレーション・ジョブ情報・ステージ・タスク状況を表示する主処理 |
| 40 | DStreamストリーム処理 | 主機能 | バッチ内のOutput Operation・Spark Job情報を取得して表示 |
| 3 | DAGスケジューラ | 遷移先機能 | バッチに関連するジョブ・ステージ詳細画面へのリンクを提供 |

## 画面種別

詳細

## URL/ルーティング

- パス: `/streaming/batch/`
- パラメータ: `id` (必須) - バッチ時刻（ミリ秒）
- 例: `/streaming/batch/?id=1609459200000`

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| id | 入力（URLパラメータ） | Long | 必須 | バッチ時刻（ミリ秒） |

## 表示項目

### バッチサマリーセクション

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Batch Duration | Duration | バッチインターバル（人間可読形式） |
| Input data size | Long | 入力レコード数 |
| Scheduling delay | Duration | スケジューリング遅延 |
| Processing time | Duration | 処理時間 |
| Total delay | Duration | 総遅延 |

### Input Metadata テーブル（メタデータがある場合のみ表示）

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Input | String | 入力ストリーム名 |
| Metadata | String | 入力メタデータ記述（HTMLエスケープ済み、タブ→スペース変換、改行→BR変換） |

### ジョブテーブル

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Output Op Id | Int | 出力オペレーションID |
| Description | String | 出力オペレーションの説明（+detailsで展開可能） |
| Output Op Duration | Duration | 出力オペレーションの処理時間 |
| Status | String | ステータス（Succeeded / Failed） |
| Job Id | Int | Spark Job ID（ジョブ詳細画面へのリンク） |
| Job Duration | Duration | ジョブの実行時間 |
| Stages: Succeeded/Total | String | ステージの完了数/総数（失敗・スキップ数含む） |
| Tasks: Succeeded/Total | ProgressBar | タスクの進捗バー（Active/Completed/Failed/Skipped/Killed） |
| Error | String | 最後のステージ失敗理由 |

## イベント仕様

### 1-Job IDリンククリック

Job ID列のリンクをクリックすると、ジョブ詳細画面（/jobs/job/?id={jobId}）へ遷移する。

### 2-Output Operation Details展開

Description列の「+details」をクリックすると、出力オペレーションの詳細説明が折りたたみ表示される。

### 3-エラー展開

Error列のFailedステータスで、エラーメッセージの展開表示が可能。UIUtils.failureReasonCellで生成。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | - | SELECT | StreamingJobProgressListenerからバッチデータを取得 |
| ページ表示 | - | SELECT | AppStatusStoreからジョブ・ステージデータを取得 |

本画面はデータベースへの更新操作を行わない。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG-001 | エラー | "Missing id parameter" | idパラメータが未指定の場合 |
| MSG-002 | エラー | "Batch {formattedBatchTime} does not exist" | 指定バッチが存在しない場合 |

## 例外処理

- idパラメータ未指定: IllegalArgumentExceptionがスローされる
- 指定バッチ不存在: IllegalArgumentExceptionで"Batch {time} does not exist"
- ジョブデータ欠損: sparkListenerの制限により破棄されたジョブはJob IDのみ表示し、他セルは"-"表示（generateDroppedJobRow）
- ステージデータ取得失敗: NoSuchElementExceptionをキャッチし、Noneを返す

## 備考

- listenerオブジェクトのsynchronizedブロックでrender全体を実行し、データの一貫性を保証
- バッチ時刻はformatBatchTimeメソッドで人間可読形式にフォーマット
- 出力オペレーションは複数のSpark Jobに対応可能。最初のジョブ行にrowspanで出力操作情報をまとめて表示
- ジョブがないOutput Operationは"-"セルで表示（generateOutputOpRowWithoutSparkJobs）
- Spark Jobデータが破棄されている場合（sparkListenerの保持上限超過）、generateDroppedJobRowでJob IDのみ表示
- Output Operationのステータスは、failureReasonの有無で判定。失敗時はcreateOutputOperationFailureForUIでUI用メッセージに変換
- エラーメッセージのHTML表示ではStringEscapeUtils.escapeHtml4でエスケープ処理を実施
- ページタイトルは"Details of batch at {formattedBatchTime}"

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | BatchUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/UIData.scala` | BatchUIDataクラスのフィールド。outputOperations、streamIdToInputInfo、outputOpIdSparkJobIdPairs |
| 1-2 | OutputOperationUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/UIData.scala` | 出力オペレーションデータ（id, name, description, startTime, endTime, failureReason） |
| 1-3 | SparkJobIdWithUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | 行30: Spark Job IDとJobDataのペア |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StreamingTab.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingTab.scala` | 行37: attachPage(new BatchPage(this)) |
| 2-2 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | 行32: WebUIPage("batch")でURLパスを設定 |

**主要処理フロー**:
1. **行321-322**: renderメソッドでbatchTimeパラメータをTime型に変換
2. **行326-327**: バッチ時刻のフォーマット
3. **行329-331**: streamingListener.getBatchUIData(batchTime)でバッチデータ取得
4. **行333-337**: Scheduling Delay/Processing Time/Total Delayのフォーマット
5. **行339-341**: Input Metadataの抽出
6. **行342-373**: サマリーHTML生成
7. **行375**: summary + generateJobTable(request, batchUIData)で最終コンテンツ生成

#### Step 3: ジョブテーブル生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | 行289-319: generateJobTableメソッド。outputOpIdToSparkJobIdsマッピング、outputOpsの生成、テーブルHTML組み立て |
| 3-2 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | 行94-160: generateNormalJobRowメソッド。ジョブデータがある場合の行生成。Duration/Stage進捗/Task進捗/Error |
| 3-3 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | 行166-201: generateDroppedJobRowメソッド。ジョブデータが破棄された場合の行生成 |

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

```
StreamingTab [行28]
    |
    +-- BatchPage (WebUIPage("batch")) [行37]
            |
            +-- render(request) [行321] (listener.synchronized)
                    |
                    +-- streamingListener.getBatchUIData(batchTime) [行329]
                    |
                    +-- サマリーHTML生成 [行342-373]
                    |       |
                    |       +-- Input Metadata抽出・テーブル生成 [行339-341]
                    |
                    +-- generateJobTable(request, batchUIData) [行375]
                            |
                            +-- outputOpIdToSparkJobIds マッピング [行292-296]
                            |
                            +-- generateOutputOpIdRow() [行203-241] (各Output Operation)
                                    |
                                    +-- generateJobRow() [行51-66] (各Spark Job)
                                    |       |
                                    |       +-- generateNormalJobRow() [行94-160]
                                    |       |       |
                                    |       |       +-- store.job(sparkJobId) [行257-263]
                                    |       |       +-- store.lastStageAttempt(stageId) [行265-271]
                                    |       |       +-- UIUtils.makeProgressBar() [行149-155]
                                    |       |
                                    |       +-- generateDroppedJobRow() [行166-201]
                                    |
                                    +-- generateOutputOpRowWithoutSparkJobs() [行68-88]
```

### データフロー図

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

id (batchTime) ──────────> BatchPage.render() (synchronized)
(URLパラメータ)                    |
                                   +---> StreamingJobProgressListener
                                   |     .getBatchUIData(batchTime)
                                   |           |
                                   |     BatchUIData <──
                                   |           |
                                   +---> サマリーHTML ──────────────> バッチ基本情報
                                   |     (Duration/Input/Delay)
                                   |
                                   +---> generateJobTable()
                                   |     |
                                   |     +---> outputOperations
                                   |     |     + sparkJobIds
                                   |     |           |
                                   |     +---> store.job(id) ──────> JobData
                                   |     +---> store.lastStageAttempt()
                                   |     |                           ──> StageData
                                   |     |
                                   |     +---> ジョブテーブルHTML ──> Output Operation別ジョブ一覧
                                   |
                                   +---> headerSparkPage() ────────> 完成ページHTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | ソース | メイン画面ページクラス |
| StreamingTab.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingTab.scala` | ソース | タブ定義 |
| StreamingJobProgressListener.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingJobProgressListener.scala` | ソース | バッチデータリスナー |
| UIData.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/UIData.scala` | ソース | BatchUIData/OutputOperationUIDataデータモデル |
| UIUtils.scala (streaming) | `streaming/src/main/scala/org/apache/spark/streaming/ui/UIUtils.scala` | ソース | failureReasonCell等のユーティリティ |
| AppStatusStore | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | ソース | ジョブ・ステージデータストア |
