# 帳票設計書 27-BatchPage（DStream）

## 概要

本ドキュメントは、Apache Spark Web UI における DStream ストリーミングの個別バッチ詳細ページ（BatchPage）の帳票設計書である。特定バッチの出力操作（Output Operation）と関連 Spark ジョブの詳細情報を表示する HTML レポートページの仕様を定義する。

### 本帳票の処理概要

BatchPage は StreamingPage（No.26）のバッチ一覧からリンクされる個別バッチの詳細ページであり、バッチの基本情報（処理時間、レコード数）および各出力操作に紐づく Spark ジョブの実行状況（ステージ進捗、タスク進捗、エラー情報）を表示する。

**業務上の目的・背景**：ストリーミングバッチの処理遅延が発生した場合、どの出力操作（Output Operation）のどのジョブがボトルネックになっているかを特定する必要がある。本帳票により、バッチ内の処理構造を詳細に分析し、問題箇所を迅速に特定できる。

**帳票の利用シーン**：StreamingPage のバッチ一覧から特定のバッチをクリックして遷移する詳細ページとして利用される。バッチ処理遅延の原因調査、ジョブ失敗の診断、ステージ・タスクレベルの問題特定に使われる。

**主要な出力内容**：
1. バッチ基本情報（Batch Duration、Input data size、Scheduling delay、Processing time、Total delay）
2. Input Metadata テーブル（入力ソースごとのメタデータ）
3. 出力操作 x ジョブ一覧テーブル（Output Op Id、Description、Duration、Status、Job Id、Stages、Tasks、Error）

**帳票の出力タイミング**：StreamingPage のバッチ一覧から特定バッチの時刻リンクをクリックした際に生成される。

**帳票の利用者**：ストリーミングパイプライン運用担当者、データエンジニア

## 帳票種別

Web UI ページ（詳細表示）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| 27 | BatchPage（DStream） | `/streaming/batch/?id={batchTime}` | StreamingPage のバッチ時刻リンクをクリック |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTML（Web UI ページ） |
| 用紙サイズ | N/A（ブラウザ表示） |
| 向き | N/A |
| ファイル名 | N/A（動的 HTML レスポンス） |
| 出力方法 | ブラウザ上にリアルタイム表示 |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

```
+---------------------------------------------+
|   Spark UI ヘッダー                            |
|   "Details of batch at {formattedBatchTime}" |
+---------------------------------------------+
| Batch Duration: {duration}                   |
| Input data size: {records} records           |
| Scheduling delay: {delay}                    |
| Processing time: {time}                      |
| Total delay: {delay}                         |
| Input Metadata:                              |
|   | Input | Metadata |                       |
+---------------------------------------------+
| ジョブテーブル                                  |
| +-------------------------------------------+|
| | Output Op Id | Description | Duration     ||
| | Status | Job Id | Job Duration | Stages   ||
| | Tasks | Error                              ||
| +-------------------------------------------+|
+---------------------------------------------+
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Batch Duration | バッチ間隔 | listener.batchDuration | formatDuration |
| 2 | Input data size | 入力レコード数 | batchUIData.numRecords | "{N} records" |
| 3 | Scheduling delay | スケジューリング遅延 | batchUIData.schedulingDelay | formatDuration |
| 4 | Processing time | 処理時間 | batchUIData.processingDelay | formatDuration |
| 5 | Total delay | 合計遅延 | batchUIData.totalDelay | formatDuration |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Output Op Id | 出力操作 ID | outputOperations.id | 数値 | auto |
| 2 | Description | 出力操作の説明 | outputOp.name + outputOp.description | テキスト (+details 展開) | auto |
| 3 | Output Op Duration | 出力操作の所要時間 | outputOpData.duration | formatDuration | auto |
| 4 | Status | 操作の成否 | outputOp.failureReason | "Succeeded" / エラー詳細 | auto |
| 5 | Job Id | Spark ジョブ ID | sparkJobId | ジョブ詳細リンク | auto |
| 6 | Job Duration | ジョブの所要時間 | completionTime - submissionTime | formatDuration | auto |
| 7 | Stages: Succeeded/Total | ステージの進捗 | numCompletedStages/stageIds.size | "N/M" 形式 | auto |
| 8 | Tasks: Succeeded/Total | タスクの進捗 | プログレスバー | makeProgressBar | auto |
| 9 | Error | エラー情報 | stageData.failureReason | テキスト | auto |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| id | バッチ時刻（ミリ秒） | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | Output Op Id | 昇順 |
| 2 | Spark Job Id | 昇順 |

### 改ページ条件

N/A（単一ページ表示）

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| StreamingJobProgressListener | バッチ情報 | batchTime |
| AppStatusStore | Spark ジョブ・ステージ情報 | jobId, stageId |

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

#### StreamingJobProgressListener

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| getBatchUIData(batchTime) | バッチ詳細 | batchTime 指定 | BatchUIData |
| outputOperations | 出力操作一覧 | - | Map[Int, OutputOperationUIData] |
| outputOpIdSparkJobIdPairs | ジョブ ID マッピング | - | Seq[OutputOpIdAndSparkJobId] |

#### AppStatusStore

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| job(jobId) | ジョブ詳細 | jobId 指定 | JobData |
| lastStageAttempt(stageId) | ステージ情報 | stageId 指定 | StageData |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Job Duration | completionTime - submissionTime | なし | ミリ秒 |
| Output Op Duration | outputOpData.duration | なし | Option[Long] |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B{id パラメータあり？}
    B -->|No| C[エラー: Missing id parameter]
    B -->|Yes| D[listener.getBatchUIData で取得]
    D --> E{データ存在？}
    E -->|No| F[エラー: Batch does not exist]
    E -->|Yes| G[基本情報生成]
    G --> H[Input Metadata テーブル生成]
    H --> I[Output Operation x Job テーブル生成]
    I --> J[各 Job の store.job で詳細取得]
    J --> K[headerSparkPage で HTML 生成]
    K --> L[レスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| パラメータ不足 | id が null | "Missing id parameter" | 正しいバッチ時刻を指定する |
| データなし | 指定バッチが存在しない | "Batch {formattedBatchTime} does not exist" | 正しいバッチ時刻を確認する |
| ジョブ消失 | sparkListener がジョブを破棄した | ジョブ ID のみ表示、他は "-" | 正常動作（保持上限超過時） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1バッチあたり数個～数十の Output Operation、各々に数個のジョブ |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | Spark Web UI のスレッドプール制約に従う |

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

- Output Operation の description にはアプリケーション固有の処理記述が含まれる。
- failure メッセージはUIUtils.failureReasonCell でHTMLエスケープされる。
- listener.synchronized でスレッドセーフにデータ取得される。

## 備考

- ジョブが sparkListener の保持上限を超えて破棄された場合、generateDroppedJobRow でジョブ ID のみの簡略行が表示される。
- Output Operation の description 内のタブは 4 スペースに、改行は `<br/>` に変換される（metadataDescriptionToHTML）。
- rowspan を使って同一 Output Operation の複数ジョブをグループ化表示する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | BatchUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingJobProgressListener.scala` | outputOperations, outputOpIdSparkJobIdPairs, numRecords, schedulingDelay 等 |
| 1-2 | OutputOperationUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/StreamingJobProgressListener.scala` | id, name, description, failureReason, duration |
| 1-3 | SparkJobIdWithUIData | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | sparkJobId と JobData のペア（行30） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | render() メソッド（行321-379） |

**主要処理フロー**:
1. **行322-325**: id パラメータ取得、Time オブジェクト生成
2. **行329-331**: getBatchUIData でバッチデータ取得
3. **行333-341**: 基本情報（遅延、処理時間等）のフォーマット
4. **行342-373**: サマリー HTML 生成 + Input Metadata
5. **行375**: generateJobTable でジョブテーブル生成

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | generateJobTable() メソッド（行289-319）- Output Op と Job のマッピング |
| 3-2 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | generateNormalJobRow() メソッド（行94-160）- 正常ジョブの行HTML生成 |
| 3-3 | BatchPage.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/BatchPage.scala` | generateDroppedJobRow() メソッド（行166-201）- 破棄ジョブの行HTML生成 |

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

```
StreamingTab
    |
    +-- BatchPage (WebUIPage, prefix="batch")
           |
           +-- render(request) [listener.synchronized]
                  |
                  +-- listener.getBatchUIData(batchTime)
                  +-- サマリー生成
                  +-- generateInputMetadataTable()
                  +-- generateJobTable(request, batchUIData)
                         +-- outputOpIdSparkJobIdPairs でマッピング
                         +-- generateOutputOpIdRow()
                                +-- generateJobRow()
                                       +-- generateNormalJobRow()
                                       |      +-- store.job(jobId) [AppStatusStore]
                                       |      +-- store.lastStageAttempt(stageId)
                                       +-- generateDroppedJobRow()
```

### データフロー図

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

HTTPリクエスト              render()
(id={batchTime})       --> パラメータ検証                  --> HTML レスポンス
                            |                                (基本情報 +
StreamingJobProgressListener|                                 Input Metadata +
                       --> getBatchUIData()                    ジョブテーブル)
                            outputOperations
                            outputOpIdSparkJobIdPairs
                            |
AppStatusStore         --> job(jobId)
                           lastStageAttempt(stageId)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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` | ソース | バッチ・操作データのリスナー |
| UIUtils.scala | `streaming/src/main/scala/org/apache/spark/streaming/ui/UIUtils.scala` | ソース | failureReasonCell, createOutputOperationFailureForUI 等 |
| AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | ソース | Spark ジョブ・ステージデータのストア |
