# 画面設計書 4-Stage Detail（ステージ詳細）

## 概要

本ドキュメントは、Apache Spark Web UIの「Stage Detail（ステージ詳細）」画面の設計書である。特定ステージの統計情報とタスク一覧を表示し、タスクメトリクスのサマリーやDAG可視化を含む。

### 本画面の処理概要

**業務上の目的・背景**：個々のステージの実行詳細を把握するための画面である。タスクレベルの実行時間内訳（Scheduler Delay、Deserialization Time、Shuffle Read/Write Time、Executor Computing Time等）を確認し、パフォーマンスボトルネックを特定する。Locality Level（データローカリティ）の分布確認や、シャッフルの読み書きサイズ、メモリスピルの状況確認にも使用される。

**画面へのアクセス方法**：All Stages画面またはJob Detail画面のステージIDリンクをクリックしてアクセスする。URLパラメータとして`id`（ステージID）と`attempt`（試行ID）が必要。

**主要な操作・処理内容**：
1. ステージの基本統計情報の表示（投入日時、実行時間、Resource Profile ID、Total Time、Locality Summary）
2. Input/Output/Shuffle Read/Shuffle Write/Spillメトリクスの表示（該当データがある場合のみ）
3. 関連ジョブIDのリンク表示
4. DAG可視化（operationGraphForStage）
5. Event Timeline表示（タスクの時系列実行状況、Executor別のグループ表示）
6. タスク一覧テーブル（JavaScript動的レンダリング、ページング・ソート対応）
7. Summary Metricsテーブル（タスクメトリクスのパーセンタイル分布）
8. タスクスレッドダンプへの遷移（threadDumpEnabled時）

**画面遷移**：
- この画面からの遷移先：Job Detail画面（関連ジョブID選択時）、Task Thread Dump画面（タスクのスレッドダンプ表示時）、Executor Thread Dump画面（エグゼキュータID選択時）
- この画面への遷移元：All Stages画面（ステージID選択）、Job Detail画面（ステージID選択）

**権限による表示制御**：スレッドダンプ機能は`spark.ui.threadDumpsEnabled`設定で制御される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定ステージの統計サマリー・タスクメトリクス分布・タスク一覧を表示する主処理 |
| 4 | タスクスケジューラ | 主機能 | タスクのローカリティ別サマリー・実行時間内訳を取得して表示 |
| 3 | DAGスケジューラ | 補助機能 | ステージのDAG可視化（operationGraphForStage）を取得して物理実行計画グラフを表示 |
| 8 | シャッフル機構 | 補助機能 | シャッフルRead/Writeのバイト数・レコード数・待ち時間等のメトリクスを表示 |
| 6 | メモリ管理 | 補助機能 | タスクのメモリスピル（Memory/Disk）情報およびPeak Execution Memoryを表示 |
| 12 | メトリクスシステム | 補助機能 | タスクメトリクスの分布（パーセンタイル）をサマリーテーブルとして表示 |
| 95 | KVStore | API連携 | AppStatusStore経由でステージ・タスクデータをページネーション付きで非同期取得 |

## 画面種別

詳細

## URL/ルーティング

- パス: `/stages/stage/?id={stageId}&attempt={attemptId}`
- クラス: `StagePage` (WebUIPage("stage"))
- タブ: `StagesTab` (SparkUITab(parent, "stages"))
- 必須パラメータ: `id` (ステージID、整数), `attempt` (試行ID、整数)

## 入出力項目

| 項目名 | 入出力 | 型 | 説明 |
|--------|--------|------|------|
| id | 入力（URLパラメータ、必須） | Int | 表示対象のステージID |
| attempt | 入力（URLパラメータ、必須） | Int | 表示対象の試行ID |
| task.sort | 入力（URLパラメータ） | String | タスクテーブルのソートカラム名（デフォルト: "Index"） |
| task.desc | 入力（URLパラメータ） | Boolean | タスクテーブルのソート順（デフォルト: false） |
| task.pageSize | 入力（URLパラメータ） | Int | タスクテーブルの1ページあたり表示件数（デフォルト: 100） |
| task.eventTimelinePageNumber | 入力（URLパラメータ） | Int | タイムラインのページ番号（デフォルト: 1） |
| task.eventTimelinePageSize | 入力（URLパラメータ） | Int | タイムラインの1ページあたりタスク数（デフォルト: 100） |

## 表示項目

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

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| Submitted | stageData.submissionTime | ステージの投入日時 |
| Duration | completionTime - submissionTime | ステージの実行時間 |
| Resource Profile Id | stageData.resourceProfileId | リソースプロファイルID |
| Total Time Across All Tasks | stageData.executorRunTime | 全タスクの総実行時間 |
| Locality Level Summary | localitySummary | ローカリティレベル別のタスク数（Process local/Node local/Rack local/Any） |
| Input Size / Records | stageData.inputBytes / inputRecords | 入力サイズ・レコード数（入力がある場合のみ） |
| Output Size / Records | stageData.outputBytes / outputRecords | 出力サイズ・レコード数（出力がある場合のみ） |
| Shuffle Read Size / Records | stageData.shuffleReadBytes / shuffleReadRecords | シャッフル読み取りサイズ・レコード数 |
| Shuffle Write Size / Records | stageData.shuffleWriteBytes / shuffleWriteRecords | シャッフル書き込みサイズ・レコード数 |
| Spill (Memory) | stageData.memoryBytesSpilled | メモリスピルサイズ |
| Spill (Disk) | stageData.diskBytesSpilled | ディスクスピルサイズ |
| Associated Job Ids | stageJobIds | 関連するジョブIDの一覧（リンク付き） |

### Event Timeline

タスクの実行をExecutor別にグループ化して時系列バー表示。各タスクバーは実行時間の内訳を色分けで可視化する。凡例: Scheduler Delay / Task Deserialization Time / Shuffle Read Time / Executor Computing Time / Shuffle Write Time / Result Serialization Time / Getting Result Time。

タイムラインはページング対応で、1ページあたりの表示タスク数を設定可能。

### タスク一覧テーブル（JavaScript動的レンダリング）

stagepage.jsにより動的にレンダリングされる。DataTablesライブラリを使用。

### Summary Metricsテーブル

stagepage.js内でタスクメトリクスのパーセンタイル分布を表示する。

## イベント仕様

### 1-関連ジョブID選択

関連ジョブIDのリンクをクリックすると、Job Detail画面に遷移する。遷移先URL: `{basePath}/jobs/job/?id={jobId}`

### 2-タスクスレッドダンプ表示

threadDumpEnabledがtrueの場合、タスク一覧からタスクのスレッドダンプを表示する機能が有効になる。stagepage.js内のsetTaskThreadDumpEnabledで制御される。

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

DAG可視化セクションの展開/折りたたみが可能。

### 4-Event Timelineの折りたたみ/ページング

Event Timelineは折りたたみ可能。ページ番号入力とページサイズ指定のフォームでタイムライン内のタスク表示を制御する。

### 5-Additional Metricsの表示切替

`showAdditionalMetrics` div内でメトリクスの表示/非表示を切り替える。

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

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

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

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

本画面はデータの読み取り専用である。

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| 情報 | "No information to display for Stage {stageId} (Attempt {stageAttemptId})" | ステージ情報が存在しない場合 |
| 情報 | "No tasks have started yet" | totalTasksが0の場合（Summary MetricsとTasksの両セクション） |
| 情報 | "Only the most recent {MAX_TIMELINE_TASKS} tasks (of {total} total) are shown." | タイムライン表示タスク数が上限を超えた場合 |
| エラー | "Missing id parameter" | idパラメータ未指定時 |
| エラー | "Missing attempt parameter" | attemptパラメータ未指定時 |

## 例外処理

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

## 備考

- タスク一覧はstagegage.jsにより動的レンダリングされ、サーバーサイドのScalaコードではテーブル構造を直接生成しない
- Event TimelineのタスクバーはSVGで描画され、実行時間の内訳を色分け比率で表示する
- タスクのローカリティレベルはProcess local / Node local / Rack local / Anyの4種類
- タイムラインに表示する最大タスク数は`spark.ui.timeline.tasks.maximum`で設定可能
- タスクテーブルのソートカラムはApiHelper.COLUMN_TO_INDEXでKVStoreのインデックス名にマッピングされる
- SPARK-8705: 実行時間が0の場合、SVGの無効なattributeエラーを回避するための特別処理がある（331行目）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | StageData, TaskData, TaskMetrics, ShuffleReadMetricsの定義 |
| 1-2 | AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | stageAttempt(), taskList(), taskCount(), localitySummary(), operationGraphForStage()のAPI |

**読解のコツ**: TaskDataには実行時間の各フェーズ（executorDeserializeTime, executorRunTime, resultSerializationTimeなど）が含まれる。これらがタイムラインの色分け表示に使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StagePage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala` | renderメソッド（83行目）が主処理 |

**主要処理フロー**:
1. **84-106行目**: URLパラメータ取得（id, attempt, task.sort, task.desc, task.pageSize, タイムラインページ設定）
2. **109-117行目**: `store.stageAttempt(stageId, stageAttemptId)` でステージデータと関連ジョブIDを取得
3. **119行目**: `store.localitySummary()` でローカリティ別タスク数を取得
4. **121-123行目**: 総タスク数を計算（active + complete + failed + killed）
5. **141-209行目**: サマリーHTMLを構築（条件付きでInput/Output/Shuffle/Spillメトリクスを表示）
6. **213-214行目**: DAG可視化用のグラフデータを取得
7. **227-238行目**: Event Timelineを生成（タスクデータはページング付きでstore.taskListから取得）
8. **239-244行目**: タスクテーブル用のJavaScript（stagepage.js）をロード

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StagePage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala` | makeTimeline（250行目）がタスクタイムラインを生成 |

**主要処理フロー**:
- **269-389行目**: 各タスクについて実行時間の内訳（schedulerDelay, deserializationTime, shuffleReadTime, executorComputingTime, shuffleWriteTime, serializationTime, gettingResultTime）を計算し、SVGバーのwidthに比率変換
- **391-399行目**: Executor別のグループ定義を生成
- **401-454行目**: タイムラインHTMLとJavaScript（drawTaskAssignmentTimeline）を生成

#### Step 4: ApiHelperを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | StagePage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala` | ApiHelper（459行目）がタスクテーブルのカラム定義とKVStoreインデックスマッピングを定義 |

**主要処理フロー**:
- **461-486行目**: 22種類のカラムヘッダー定数定義
- **488-516行目**: COLUMN_TO_INDEXマップでカラム名をKVStoreインデックス名に対応付け
- **518-557行目**: ユーティリティ関数群（hasInput, hasOutput, hasShuffleRead, hasShuffleWrite, hasBytesSpilled, indexName, lastStageNameAndDescription）

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

```
StagePage.render(request)
    |
    +-- store.stageAttempt(stageId, attemptId)    ... ステージデータ取得
    +-- store.localitySummary(stageId, attemptId)  ... ローカリティサマリー
    |
    +-- store.operationGraphForStage(stageId)      ... DAGグラフ取得
    |     +-- UIUtils.showDagVizForStage()         ... DAG HTML生成
    |
    +-- makeTimeline()                              ... タイムラインHTML生成
    |     +-- store.taskList(stageId, attemptId, from, size, sortColumn, asc)
    |     +-- AppStatusUtils.schedulerDelay()
    |     +-- AppStatusUtils.gettingResultTime()
    |     +-- drawTaskAssignmentTimeline()          ... JavaScript呼び出し
    |
    +-- stagepage.js (JavaScript)                   ... タスクテーブル動的レンダリング
    |     +-- setTaskThreadDumpEnabled()
    |
    +-- UIUtils.headerSparkPage()                   ... ページラップ
```

### データフロー図

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

HTTPリクエスト
  id, attempt        ---> StagePage.render()
                              |
KVStore               --> stageAttempt()            --> ステージ基本情報
                      --> localitySummary()          --> ローカリティ分布
                      --> operationGraphForStage()   --> DAGグラフ
                      --> taskList() (ページング)     --> タスクタイムラインデータ
                              |
                              v
                          HTML + JavaScript          --> ブラウザ表示
                              |
                          stagepage.js               --> タスクテーブル動的描画
                          drawTaskAssignmentTimeline  --> タイムライン描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| StagePage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala` | ソース | 画面のメインページクラスとApiHelper |
| StagesTab.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagesTab.scala` | ソース | Stagesタブ定義 |
| AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | ソース | データアクセス層 |
| AppStatusUtils.scala | `core/src/main/scala/org/apache/spark/status/AppStatusUtils.scala` | ソース | schedulerDelay, gettingResultTime計算 |
| api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | ソース | データモデル定義 |
| stagepage.js | `core/src/main/resources/org/apache/spark/ui/static/stagepage.js` | JavaScript | タスクテーブル動的レンダリング |
| utils.js | `core/src/main/resources/org/apache/spark/ui/static/utils.js` | JavaScript | UIユーティリティ |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | HTML/DAG生成ユーティリティ |
