# 帳票設計書 13-JobPage

## 概要

本ドキュメントは、Apache Spark Web UI の個別ジョブ詳細ページ（JobPage）の帳票設計書である。特定のジョブIDに対して、そのジョブに属するステージの状態（Active/Pending/Completed/Skipped/Failed）、DAG可視化、イベントタイムラインをHTML形式で表示するレポートページを定義する。

### 本帳票の処理概要

**業務上の目的・背景**：全ジョブ一覧（AllJobsPage）から個別ジョブをドリルダウンして、ジョブ内のステージ構成と進捗を詳細に把握するために必要な帳票である。ジョブ内のどのステージがボトルネックとなっているか、どのステージが失敗しているかを特定し、パフォーマンスチューニングや障害対応に活用する。DAG可視化によりジョブの実行計画を視覚的に理解できる。

**帳票の利用シーン**：AllJobsPage からジョブIDをクリックして遷移する場面、特定ジョブの実行状況を詳細に確認する場面、DAG 可視化でジョブの実行計画構造を把握する場面、関連する SQL クエリを確認する場面で利用される。

**主要な出力内容**：
1. ジョブサマリー（ステータス、送信日時、実行時間、Job Group、関連SQL）
2. イベントタイムライン（ステージと Executor の時系列表示）
3. DAG 可視化（ジョブの実行計画グラフ）
4. Active Stages テーブル
5. Pending/Skipped Stages テーブル
6. Completed Stages テーブル
7. Failed Stages テーブル

**帳票の出力タイミング**：Spark Web UI で `/jobs/job/?id={jobId}` にアクセスした際に動的にレンダリングされる。

**帳票の利用者**：アプリケーション開発者、データエンジニア、クラスタ管理者

## 帳票種別

Web UI レポートページ（HTML形式詳細表示）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| 13 | Job Details | `http://{host}:4040/jobs/job/?id={jobId}` | AllJobsPage のジョブID リンクをクリック |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTML（動的レンダリング） |
| 用紙サイズ | 該当なし（ブラウザ表示） |
| 向き | 該当なし |
| ファイル名 | 該当なし（HTTP レスポンス） |
| 出力方法 | Spark Web UI からのブラウザ表示 |
| 文字コード | UTF-8 |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

ページ上部にジョブサマリー、次にイベントタイムラインとDAG可視化（折りたたみ可能）、その下に状態別のステージテーブルを表示する。

```
┌─────────────────────────────────────┐
│   ページヘッダー (Details for Job X)  │
├─────────────────────────────────────┤
│  ジョブサマリー                       │
│  - Status / Submitted / Duration     │
│  - Associated SQL Query              │
│  - Job Group                         │
│  - ステージ数サマリー                 │
├─────────────────────────────────────┤
│  Event Timeline（折りたたみ可能）      │
│  - Stages タイムライン                │
│  - Executors タイムライン             │
├─────────────────────────────────────┤
│  DAG Visualization（折りたたみ可能）   │
├─────────────────────────────────────┤
│  Active Stages テーブル              │
├─────────────────────────────────────┤
│  Pending/Skipped Stages テーブル     │
├─────────────────────────────────────┤
│  Completed Stages テーブル           │
├─────────────────────────────────────┤
│  Failed Stages テーブル              │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Status | ジョブの実行状態 | jobData.status | RUNNING/SUCCEEDED/FAILED |
| 2 | Submitted | 送信日時 | JobDataUtil.getFormattedSubmissionTime | 日時フォーマット |
| 3 | Duration | 実行時間 | JobDataUtil.getFormattedDuration | 時間フォーマット |
| 4 | Associated SQL Query | 関連SQLクエリID | sqlExecutionId | リンク付き整数 |
| 5 | Job Group | ジョブグループ名 | jobData.jobGroup | 文字列 |
| 6 | Active Stages | アクティブステージ数 | activeStages.size | 整数（リンク付き） |
| 7 | Pending Stages | 保留中ステージ数 | pendingOrSkippedStages.size | 整数（リンク付き） |
| 8 | Completed Stages | 完了ステージ数 | completedStages.size | 整数（リンク付き） |
| 9 | Skipped Stages | スキップステージ数 | pendingOrSkippedStages.size | 整数（リンク付き、ジョブ完了時のみ） |
| 10 | Failed Stages | 失敗ステージ数 | failedStages.size | 整数（リンク付き） |

### 明細部

ステージテーブルは StageTableBase を使用（共通コンポーネント）。

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Stage Id | ステージ識別子 | stageData.stageId | 整数 | 自動 |
| 2 | Description | ステージ説明 | stageData.description | テキスト | 自動 |
| 3 | Submitted | 送信日時 | stageData.submissionTime | 日時 | 自動 |
| 4 | Duration | 実行時間 | completionTime - submissionTime | 時間 | 自動 |
| 5 | Tasks | タスク進捗 | numCompleteTasks / numTasks | プログレスバー | 自動 |
| 6 | Input | 入力サイズ | inputBytes | バイト表示 | 自動 |
| 7 | Output | 出力サイズ | outputBytes | バイト表示 | 自動 |
| 8 | Shuffle Read | シャッフル読み取り | shuffleReadBytes | バイト表示 | 自動 |
| 9 | Shuffle Write | シャッフル書き込み | shuffleWriteBytes | バイト表示 | 自動 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| - | 該当なし | ページフッターはSparkUI共通フッター | - | - |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| id パラメータ | ジョブID（URLパラメータ） | Yes |
| タイムライン制限 | MAX_TIMELINE_STAGES で表示ステージ数を制限 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ステージ送信時刻順（タイムライン） | 昇順 |

### 改ページ条件

ステージテーブルは StageTableBase のページネーション機能を使用。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| AppStatusStore (KVStore) | ジョブ・ステージ情報の取得 | jobId, stageId による検索 |

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

#### AppStatusStore

| 参照項目（メソッド） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| jobWithAssociatedSql(jobId) | ジョブデータ + SQL実行ID | jobId 指定 | JobData と Option[Long] を返す |
| lastStageAttempt(stageId) | 各ステージの最新試行データ | stageId 指定 | 存在しない場合はデフォルト StageData |
| executorList(false) | タイムライン表示用 | activeOnly=false | ExecutorSummary のリスト |
| operationGraphForJob(jobId) | DAG 可視化用 | jobId 指定 | RDDOperationGraph |
| applicationInfo() | アプリケーション開始時刻 | なし | タイムライン基準時刻 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ステージ状態分類 | submissionTime/completionTime/status による判定 | なし | Active/Completed/Pending/Failed に分類 |
| Duration | JobDataUtil.getFormattedDuration | なし | 送信時刻と完了時刻の差分 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTP GET /jobs/job/?id=X] --> B[JobPage.render]
    B --> C[id パラメータ検証]
    C --> D[store.jobWithAssociatedSql 取得]
    D --> E{ジョブ存在?}
    E -->|No| F[No information メッセージ表示]
    E -->|Yes| G[各ステージデータ取得]
    G --> H[ステージを Active/Completed/Pending/Failed に分類]
    H --> I[StageTableBase で各テーブル生成]
    I --> J[makeTimeline でタイムライン生成]
    J --> K[operationGraphForJob で DAG 生成]
    K --> L[HTML レスポンス構成]
    L --> M[UIUtils.headerSparkPage]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| パラメータ不足 | id パラメータが null または空 | "Missing id parameter" (require例外) | 正しいURLでアクセス |
| ジョブ未発見 | 指定ジョブIDが存在しない | "No information to display for job X" | 正しいジョブIDを確認 |
| DAG情報なし | DAG情報が取得できない | "No DAG visualization information to display for job X" | 情報が利用可能になるまで待つ |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1ジョブあたり数十〜数百ステージ |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | Web UI 同時接続数に依存 |

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

- ステージキル機能は killEnabled フラグで制御される
- ジョブの説明テキストとステージ名は HTML エスケープ処理される

## 備考

- ジョブが完了している場合、Pending ステージは "Skipped" として表示される（行336-341）
- ステージ情報が未受信またはGCされた場合、デフォルト値の StageData が使用される（行243-312）
- DAG 可視化は showVisualization=true で有効化される（行528）
- タイムラインのステージ数上限は UI_TIMELINE_STAGES_MAXIMUM で設定

---

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

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

### 推奨読解順序

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

ジョブとステージのデータ構造、および StageData のデフォルト値を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | v1/api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | JobData と StageData の定義を確認 |

**読解のコツ**: StageData のデフォルト値（行243-312）は、ステージ情報が未受信の場合のフォールバック値として使われる。全フィールドが0/null/空で初期化される点に注目。

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

JobPage.render メソッドの処理フローを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | JobPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala` | render メソッド（行224-529）全体の流れ |

**主要処理フロー**:
1. **行225-228**: id パラメータの検証と取得
2. **行229-236**: store.jobWithAssociatedSql でジョブデータと SQL 実行ID を取得
3. **行238-312**: 各ステージの StageData を取得（未受信時はデフォルト値）
4. **行315-332**: ステージを Active/Completed/Pending/Failed に分類
5. **行343-358**: 各状態の StageTableBase を生成
6. **行447-448**: makeTimeline でタイムライン生成
7. **行450-456**: operationGraphForJob で DAG 可視化

#### Step 3: タイムライン描画を理解する

ステージとExecutorのタイムラインデータ生成ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | JobPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala` | makeStageEvent（行65-105）、makeTimeline（行153-222） |

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

```
HttpServletRequest (?id=X)
    |
    +-- JobPage.render()
            |
            +-- store.jobWithAssociatedSql(jobId)
            +-- store.lastStageAttempt(stageId)  [各ステージ]
            +-- store.executorList(false)
            +-- store.operationGraphForJob(jobId)
            +-- store.applicationInfo()
            |
            +-- StageTableBase [Active/Pending/Completed/Failed]
            +-- makeTimeline()
            |     +-- makeStageEvent()
            |     +-- makeExecutorEvent()
            |     +-- drawJobTimeline() [JavaScript]
            |
            +-- UIUtils.showDagVizForJob()
```

### データフロー図

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

HTTP GET /jobs/job/   ──▶  JobPage.render()               ──▶  HTML レスポンス
  ?id=X                      |
                            store.jobWithAssociatedSql      ──▶  ジョブサマリー
                            store.lastStageAttempt          ──▶  ステージテーブル(4種)
                            store.operationGraphForJob      ──▶  DAG 可視化
                            makeTimeline()                  ──▶  タイムライン(JavaScript)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| JobPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala` | ソース | ジョブ詳細ページの描画 |
| JobsTab.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobsTab.scala` | ソース | Jobs タブの定義 |
| StageTableBase.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StageTableBase.scala` | ソース | ステージテーブル共通コンポーネント |
| AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | ソース | データストアアクセス |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | HTML ユーティリティ・DAG可視化 |
