# 画面設計書 2-Job Detail（ジョブ詳細）

## 概要

本ドキュメントは、Apache Spark Web UIの「Job Detail（ジョブ詳細）」画面の設計書である。特定ジョブの統計情報とステージ一覧をActive/Pending/Completed/Skipped/Failedに分類して表示し、DAG可視化機能を含む。

### 本画面の処理概要

**業務上の目的・背景**：個々のジョブの実行状況を詳細に把握するための画面である。ジョブがどのステージで構成されているか、各ステージの進捗状況はどうか、DAG（有向非巡回グラフ）として物理実行計画がどのように構成されているかを確認できる。パフォーマンスボトルネックの特定や、ジョブ失敗時の原因調査に不可欠な画面である。

**画面へのアクセス方法**：All Jobs（全ジョブ一覧）画面のジョブIDリンクをクリックしてアクセスする。URLパラメータとして`id`（ジョブID）が必要。SQL実行詳細画面からジョブIDリンク経由でもアクセス可能。

**主要な操作・処理内容**：
1. ジョブの基本統計情報の表示（ステータス、投入日時、実行時間、関連SQLクエリ、ジョブグループ）
2. ステージ一覧のActive/Pending(Skipped)/Completed/Failedへの分類表示
3. Event Timeline表示（ステージとExecutorの時系列可視化）
4. DAG可視化（operationGraphForJob）による物理実行計画のグラフ表示
5. Active Stageに対するKill操作（StagesTab経由）

**画面遷移**：
- この画面からの遷移先：Stage Detail（ステージ詳細）画面（ステージID選択時）、SQL Execution Detail画面（関連SQLクエリID選択時）
- この画面への遷移元：All Jobs画面（ジョブID選択）、SQL Execution Detail画面（ジョブID選択）、Batch Detail画面（ジョブID選択）

**権限による表示制御**：ステージのKill操作は`killEnabled`設定とセキュリティマネージャの権限チェックに依存する。Kill操作はActiveステージテーブルでのみ表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定ジョブの統計情報・ステージ一覧をActive/Pending/Completed/Skipped/Failedに分類して表示する主処理 |
| 3 | DAGスケジューラ | 主機能 | ジョブのDAG可視化（operationGraphForJob）を取得し物理実行計画のグラフを表示 |
| 5 | Executorプロセス管理 | 補助機能 | Executorタイムライン表示およびステージのKill操作時のExecutor連携 |
| 4 | タスクスケジューラ | 補助機能 | ステージ内のタスク進捗情報（Active/Completed/Failed/Skipped）を参照して表示 |
| 95 | KVStore | API連携 | AppStatusStore経由でジョブ・ステージデータおよびSQL実行IDを非同期取得 |

## 画面種別

詳細

## URL/ルーティング

- パス: `/jobs/job/?id={jobId}`
- クラス: `JobPage` (WebUIPage("job"))
- タブ: `JobsTab` (SparkUITab(parent, "jobs"))
- 必須パラメータ: `id` (ジョブID、整数)

## 入出力項目

| 項目名 | 入出力 | 型 | 説明 |
|--------|--------|------|------|
| id | 入力（URLパラメータ、必須） | Int | 表示対象のジョブID |
| activeStage.page | 入力（URLパラメータ） | Int | Active Stagesテーブルのページ番号 |
| activeStage.sort | 入力（URLパラメータ） | String | Active Stagesテーブルのソートカラム名 |
| activeStage.desc | 入力（URLパラメータ） | Boolean | Active Stagesテーブルのソート順 |
| pendingStage.page | 入力（URLパラメータ） | Int | Pending Stagesテーブルのページ番号 |
| completedStage.page | 入力（URLパラメータ） | Int | Completed Stagesテーブルのページ番号 |
| failedStage.page | 入力（URLパラメータ） | Int | Failed Stagesテーブルのページ番号 |

## 表示項目

### サマリーセクション

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| Status | jobData.status | ジョブのステータス（RUNNING/SUCCEEDED/FAILED） |
| Submitted | jobData.submissionTime | ジョブの投入日時 |
| Duration | completionTime - submissionTime | ジョブの実行時間 |
| Associated SQL Query | sqlExecutionId | 関連するSQL実行のID（リンク付き、存在する場合のみ） |
| Job Group | jobData.jobGroup | ジョブグループ名（存在する場合のみ） |
| Active Stages | activeStages.size | アクティブなステージ数 |
| Pending Stages | pendingOrSkippedStages.size | 保留中のステージ数（ジョブ実行中のみ） |
| Completed Stages | completedStages.size | 完了したステージ数 |
| Skipped Stages | pendingOrSkippedStages.size | スキップされたステージ数（ジョブ完了時のみ） |
| Failed Stages | failedStages.size | 失敗したステージ数 |

### DAG可視化

operationGraphForJobから取得した物理実行計画をDAGとして可視化表示する。UIUtils.showDagVizForJobにより生成される。

### Event Timeline

ステージの開始・終了をバー形式で時系列表示。Executorの追加・削除イベントも含む。ステージの凡例: Completed=緑、Failed=赤、Active=青。

### ステージテーブル（Active/Pending/Completed/Skipped/Failed共通）

StageTableBaseクラスにより生成される。FAIRスケジューラ使用時はプール情報カラムも表示される。

## イベント仕様

### 1-ステージID選択

ステージテーブルのステージIDリンクをクリックすると、Stage Detail（ステージ詳細）画面に遷移する。

### 2-関連SQLクエリリンク

関連SQLクエリIDのリンクをクリックすると、SQL Execution Detail画面に遷移する。遷移先URL: `{basePath}/SQL/execution/?id={sqlExecutionId}`

### 3-DAG可視化の表示切替

DAG可視化セクションは展開/折りたたみが可能。showVisualization=trueでページが表示される。

### 4-Event Timelineの折りたたみ

「Event Timeline」ラベルをクリックすると、タイムラインの表示/非表示が切り替わる。ズーム操作も可能。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | KVStore (AppStatusStore) | SELECT | ジョブ情報・ステージ情報・DAGグラフ・Executor一覧の読み取り |

### テーブル別更新項目詳細

本画面はデータの読み取り専用であり、KVStoreへの直接的な書き込みは行わない。

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| エラー | "No information to display for job {jobId}" | 指定されたジョブIDが存在しない場合 |
| エラー | "No DAG visualization information to display for job {jobId}" | DAGグラフ情報が取得できない場合 |
| エラー | "Missing id parameter" | idパラメータが指定されていない場合（require例外） |
| 情報 | "Only the most recent {MAX_TIMELINE_STAGES} submitted/completed stages (of {total} total) are shown." | タイムライン表示ステージ数が上限を超えた場合 |

## 例外処理

| 例外 | 発生条件 | 処理 |
|------|----------|------|
| IllegalArgumentException | idパラメータが未指定 | require文によるエラー |
| NoSuchElementException | ジョブIDがKVStoreに存在しない | "No information to display"メッセージを表示 |

## 備考

- ジョブが完了している場合、Pending StagesはSkipped Stagesとして表示される（317-341行目の分岐処理）
- ステージ情報が未到着またはGCで削除されている場合、StageStatus.PENDINGのダミーStageDataが生成される（243-312行目）
- タイムラインのステージ最大数は`spark.ui.timeline.stages.maximum`で設定可能
- DAG可視化にはshowVisualization=trueが必要

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | JobData, StageData, ExecutorSummaryのフィールドを理解する |
| 1-2 | AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | jobWithAssociatedSql(), lastStageAttempt(), operationGraphForJob()のAPI |

**読解のコツ**: jobWithAssociatedSqlは(JobData, Option[Long])のタプルを返す。2番目の要素はSQL実行IDで、SQLモジュール使用時のみ値が入る。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | JobPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala` | renderメソッド（224行目）がHTTPリクエストを受けてHTML Nodeを返す |

**主要処理フロー**:
1. **225-228行目**: リクエストからjobIdパラメータを取得
2. **229-236行目**: `store.jobWithAssociatedSql(jobId)` でジョブデータとSQL実行IDを取得。存在しなければエラー画面を返す
3. **238行目**: ジョブ完了判定（isComplete）
4. **239-312行目**: ステージ情報を取得。未到着ステージにはダミーStageDataを生成
5. **315-332行目**: ステージをActive/Completed/PendingOrSkipped/Failedに分類
6. **343-358行目**: 各ステータスのStageTableBaseを生成
7. **366-442行目**: サマリーHTML構築
8. **447-448行目**: タイムライン生成
9. **450-457行目**: DAG可視化生成（operationGraphForJob）
10. **459-526行目**: 各ステージテーブルセクションをHTML出力
11. **527-528行目**: ページ全体をラップ（showVisualization=true）

#### Step 3: タイムライン生成を理解する

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

**主要処理フロー**:
- **65-105行目**: makeStageEventでステージの開始・終了をタイムラインイベントJSONに変換
- **107-151行目**: makeExecutorEventでExecutor追加・削除をイベントJSONに変換
- **153-222行目**: drawJobTimeline JavaScriptを生成

#### Step 4: ステージテーブルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | StageTableBase.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StageTableBase.scala` | ステージテーブルのカラム定義・行レンダリング。FAIRスケジューラ時のプール情報カラム |

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

```
JobPage.render(request)
    |
    +-- store.jobWithAssociatedSql(jobId)    ... ジョブ+SQL実行ID取得
    |     +-- KVStore                        ... データ読み取り
    |
    +-- store.lastStageAttempt(stageId)      ... 各ステージの最新試行取得
    |     （存在しない場合はダミーStageData生成）
    |
    +-- StageTableBase()                     ... ステージテーブル生成
    |     +-- active/pending/completed/failed 各テーブル
    |
    +-- makeTimeline()                       ... タイムラインHTML生成
    |     +-- makeStageEvent()              ... ステージイベントJSON
    |     +-- makeExecutorEvent()           ... ExecutorイベントJSON
    |     +-- store.executorList(false)     ... Executor一覧取得
    |
    +-- store.operationGraphForJob(jobId)    ... DAGグラフ取得
    |     +-- UIUtils.showDagVizForJob()    ... DAG HTML生成
    |
    +-- UIUtils.headerSparkPage()            ... ページラップ
```

### データフロー図

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

HTTPリクエスト
  id=jobId          ---> JobPage.render()
                            |
KVStore              --> jobWithAssociatedSql()     --> ジョブ基本情報+SQL ID
                     --> lastStageAttempt()          --> ステージ一覧
                     --> operationGraphForJob()      --> DAGグラフ
                     --> executorList(false)          --> Executorタイムライン
                            |
                            v
                        HTML(Seq[Node])              --> ブラウザ表示
                            |
                        JavaScript                   --> drawJobTimeline()
                                                         showDagViz()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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` | ソース | データアクセス層 |
| api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | ソース | データモデル定義 |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | HTML/DAG生成ユーティリティ |
| spark-dag-viz.js | `core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js` | JavaScript | DAG可視化ライブラリ |
| timeline-view.js | `core/src/main/resources/org/apache/spark/ui/static/timeline-view.js` | JavaScript | タイムライン描画ライブラリ |
