# 帳票設計書 12-AllJobsPage

## 概要

本ドキュメントは、Apache Spark Web UI の「Jobs」タブにおける全ジョブ一覧ページ（AllJobsPage）の帳票設計書である。Spark アプリケーション内で実行された全ジョブの状態（Active/Completed/Failed）をHTML形式で表示し、ジョブの進捗状況をリアルタイムに監視できるレポートページを定義する。

### 本帳票の処理概要

**業務上の目的・背景**：Spark アプリケーション実行中および実行後に、全ジョブの進捗と結果を一覧形式で把握するために必要な帳票である。開発者やデータエンジニアがアプリケーションのパフォーマンスを監視し、失敗したジョブを素早く特定するための中核的な画面を提供する。タイムライン表示により、ジョブの時間的な分布と Executor の追加/削除のタイミングを視覚的に把握できる。

**帳票の利用シーン**：Spark アプリケーション実行中にリアルタイムでジョブの進捗を確認する場面、アプリケーション完了後に History Server を通じてジョブ実行結果を確認する場面、パフォーマンスボトルネックの特定やジョブ失敗の原因調査を行う場面で利用される。

**主要な出力内容**：
1. アプリケーションサマリー（ユーザー名、開始時刻、稼働時間、スケジューリングモード）
2. イベントタイムライン（ジョブと Executor の時系列表示）
3. Active Jobs テーブル（実行中ジョブの一覧）
4. Completed Jobs テーブル（完了ジョブの一覧）
5. Failed Jobs テーブル（失敗ジョブの一覧）

**帳票の出力タイミング**：Spark Web UI の「Jobs」タブにアクセスした際に動的にレンダリングされる。ページリロードにより最新状態が反映される。

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

## 帳票種別

Web UI レポートページ（HTML形式一覧表）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| 12 | Spark Jobs | `http://{host}:4040/jobs/` | ブラウザからアクセス |

## 出力形式

### 基本仕様

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

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

ページは上部のアプリケーションサマリー、イベントタイムライン（折りたたみ可能）、および状態別のジョブテーブル（Active/Completed/Failed）で構成される。

```
┌─────────────────────────────────────┐
│         ページヘッダー (Spark Jobs)    │
├─────────────────────────────────────┤
│  アプリケーションサマリー              │
│  - User / Started At / Uptime       │
│  - Scheduling Mode                  │
│  - Active/Completed/Failed Jobs数    │
├─────────────────────────────────────┤
│  Event Timeline（折りたたみ可能）      │
│  - Jobs タイムライン                  │
│  - Executors タイムライン             │
├─────────────────────────────────────┤
│  Active Jobs テーブル                 │
├─────────────────────────────────────┤
│  Completed Jobs テーブル              │
├─────────────────────────────────────┤
│  Failed Jobs テーブル                 │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | User | アプリケーション実行ユーザー | parent.getSparkUser | 文字列 |
| 2 | Started At | アプリケーション開始時刻 | appInfo.attempts.head.startTime | 日時フォーマット |
| 3 | Total Uptime | 総稼働時間 | endTime - startTime（または現在時刻 - startTime） | 時間フォーマット |
| 4 | Scheduling Mode | スケジューリングモード | store.environmentInfo().sparkProperties | FIFO/FAIR/Unknown |
| 5 | Active Jobs | 実行中ジョブ数 | activeJobs.size | 整数（リンク付き） |
| 6 | Completed Jobs | 完了ジョブ数 | completedJobs.size / appSummary.numCompletedJobs | 整数（リンク付き） |
| 7 | Failed Jobs | 失敗ジョブ数 | failedJobs.size | 整数（リンク付き） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Job Id | ジョブ識別子（Job Group付き） | jobData.jobId, jobData.jobGroup | 整数（グループ名） | 自動 |
| 2 | Description | ジョブの説明 | jobData.description / lastStageDescription | テキスト+リンク | 自動 |
| 3 | Submitted | 送信日時 | jobData.submissionTime | 日時フォーマット | 自動 |
| 4 | Duration | 実行時間 | completionTime - submissionTime | 時間フォーマット | 自動 |
| 5 | Stages: Succeeded/Total | ステージ進捗 | numCompletedStages / stageIds.size | 分数表示 | 自動 |
| 6 | Tasks: Succeeded/Total | タスク進捗 | プログレスバー表示 | プログレスバー | 自動 |

### フッター部

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

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ジョブ状態フィルタ | SUCCEEDED/FAILED/RUNNING でジョブを3グループに分類 | Yes（自動） |
| タイムライン制限 | MAX_TIMELINE_JOBS で表示ジョブ数を制限 | No |
| タイムライン制限 | MAX_TIMELINE_EXECUTORS で表示 Executor 数を制限 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | Job Id（デフォルト） | 昇順 |
| 2 | Description | 昇順 |
| 3 | Submitted | 昇順 |
| 4 | Duration | 昇順 |

### 改ページ条件

ページネーション機能あり。各テーブルで pageSize パラメータにより1ページあたりの表示件数を制御する。

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

### 参照テーブル一覧

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

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

#### AppStatusStore

| 参照項目（メソッド） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| applicationInfo() | アプリケーションサマリー | なし | 開始時刻・終了時刻 |
| jobsList(null) | 全ジョブデータ | ステータスフィルタなし | v1.JobData のリスト |
| appSummary() | 完了ジョブ数 | なし | numCompletedJobs |
| environmentInfo() | スケジューリングモード | sparkProperties から取得 | SCHEDULER_MODE キー |
| executorList(false) | タイムライン表示用 | activeOnly=false | ExecutorSummary のリスト |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Duration | completionTime - submissionTime | なし | 実行中ジョブは現在時刻との差分 |
| Total Uptime | endTime - startTime（終了済み）/ currentTime - startTime（実行中） | なし | UIUtils.formatDuration で表示 |
| Completed Job表示文字列 | numCompletedJobs != completedJobs.size の場合 "X, only showing Y" | なし | 表示制限時のメッセージ |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTP GET /jobs/] --> B[AllJobsPage.render]
    B --> C[store.applicationInfo 取得]
    C --> D[store.jobsList で全ジョブ取得]
    D --> E[ジョブを Active/Completed/Failed に分類]
    E --> F[各状態のジョブテーブル生成]
    F --> G{TIMELINE_ENABLED?}
    G -->|Yes| H[makeTimeline でタイムライン生成]
    G -->|No| I[タイムラインなし]
    H --> J[HTML レスポンス生成]
    I --> J
    J --> K[UIUtils.headerSparkPage でページ構成]
    K --> L[HTTP レスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| テーブル描画エラー | IllegalArgumentException / IndexOutOfBoundsException | "Error while rendering job table:" + スタックトレース | エラーメッセージをページ内に表示 |
| ソートカラムエラー | 不明なソートカラム指定 | "Unknown column: {column}" | デフォルトソートにフォールバック |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数千ジョブまで |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | Web UI 同時接続数に依存 |

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

- ジョブキル機能は killEnabled フラグで制御される（行575-591）
- ジョブキルには securityManager.checkModifyPermissions によるユーザー権限チェックが行われる（JobsTab.scala 行51）
- ジョブの説明テキストは HTML エスケープ処理される（StringEscapeUtils.escapeEcmaScript）

## 備考

- タイムライン表示は spark.ui.timeline.enabled 設定で有効/無効を切り替え可能
- タイムライン表示のジョブ数上限は spark.ui.timeline.jobs.maximum で設定
- ページネーション機能により大量のジョブでもパフォーマンスを維持
- ジョブ状態が UNKNOWN のジョブはタイムラインに表示されない

---

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

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

### 推奨読解順序

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

ジョブデータの型定義と AppStatusStore のデータアクセス方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | v1/api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | JobData クラスの定義（jobId, status, stageIds, submissionTime 等）を確認 |
| 1-2 | AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | jobsList(), applicationInfo(), appSummary() 等のデータ取得メソッド |

**読解のコツ**: v1.JobData は REST API のレスポンスモデルとしても使われるため、Web UI と REST API で同じデータ構造を共有している。

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

AllJobsPage の render メソッドが HTTP リクエスト処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AllJobsPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala` | render メソッド（行278-425）でデータ取得からHTML生成までの流れを理解する |

**主要処理フロー**:
1. **行279-282**: store.applicationInfo() でアプリケーション情報取得、開始/終了時刻を算出
2. **行284-297**: store.jobsList(null) で全ジョブを取得し、Active/Completed/Failed に分類
3. **行299-304**: 各状態のジョブテーブル（JobPagedTable）を生成
4. **行310-321**: スケジューリングモード取得とサマリーセクション構築
5. **行377-378**: makeTimeline でタイムラインセクション生成
6. **行423-424**: UIUtils.headerSparkPage で最終ページ構成

#### Step 3: テーブル描画層を理解する

JobPagedTable によるページネーション付きテーブルの描画ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AllJobsPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala` | JobPagedTable（行508-618）でヘッダー定義（行553-564）と行描画（行572-617） |
| 3-2 | AllJobsPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala` | JobDataSource（行440-506）でソートとページネーションのデータ準備 |

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

JavaScript ベースのタイムライン可視化のデータ準備。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AllJobsPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala` | makeTimeline（行173-242）、makeJobEvent（行71-124）、makeExecutorEvent（行126-171） |

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

```
HttpServletRequest
    |
    +-- AllJobsPage.render()
            |
            +-- store.applicationInfo()
            +-- store.jobsList(null)
            +-- store.appSummary()
            +-- store.environmentInfo()
            +-- store.executorList(false)
            |
            +-- jobsTable()
            |     +-- JobPagedTable
            |           +-- JobDataSource
            |                 +-- lastStageNameAndDescription()
            |                 +-- JobDataUtil.getDuration()
            |
            +-- makeTimeline()
                  +-- makeJobEvent()
                  +-- makeExecutorEvent()
                  +-- drawApplicationTimeline() [JavaScript]
```

### データフロー図

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

HTTP GET /jobs/      ──▶  AllJobsPage.render()            ──▶  HTML レスポンス
                            |
AppStatusStore       ──▶  ジョブデータ取得・分類            ──▶  サマリーセクション
 (KVStore)                  |
                          JobPagedTable                    ──▶  ジョブテーブル(3種)
                            |
                          makeTimeline()                   ──▶  タイムライン(JavaScript)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AllJobsPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala` | ソース | 全ジョブ一覧ページの描画 |
| JobsTab.scala | `core/src/main/scala/org/apache/spark/ui/jobs/JobsTab.scala` | ソース | Jobs タブの定義とジョブキルハンドリング |
| 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 ユーティリティ（headerSparkPage, formatDate等） |
| WebUIPage.scala | `core/src/main/scala/org/apache/spark/ui/WebUIPage.scala` | ソース | Web UI ページ基底クラス |
| PagedTable.scala | `core/src/main/scala/org/apache/spark/ui/PagedTable.scala` | ソース | ページネーション付きテーブル基底クラス |
