# 画面設計書 25-Application Detail（アプリケーション詳細）

## 概要

本ドキュメントは、Standaloneクラスタの特定アプリケーションのエグゼキュータ詳細を表示する画面「Application Detail（アプリケーション詳細）」の設計書である。

### 本画面の処理概要

本画面は、Spark Standaloneクラスタにおける特定アプリケーションの詳細情報と、割り当てられたエグゼキュータの一覧を表示する画面である。

**業務上の目的・背景**：Standaloneクラスタで実行中または完了したアプリケーションに対し、エグゼキュータの割り当て状況（どのワーカーに何コア・何メモリが割り当てられているか）を確認する必要がある。特に、アプリケーションの実行に問題がある場合に、エグゼキュータの状態やログへのアクセスが重要となる。本画面はこれらの情報を一元的に提供する。

**画面へのアクセス方法**：Master Overview画面（No.24）のRunning ApplicationsまたはCompleted Applicationsテーブルにおいて、アプリケーションIDのリンクをクリックすることで本画面に遷移する。URLパラメータとしてアプリケーションID（appId）が必要である。

**主要な操作・処理内容**：
1. アプリケーション基本情報の表示（ID、名前、ユーザー、コア数、エグゼキュータ制限、メモリ、リソース、投入日時、期間、状態）
2. Application Detail UIまたはApplication History UIへのリンク表示
3. Executor Summaryテーブルの表示（全エグゼキュータの状態・リソース・ログリンク）
4. Removed Executorsテーブルの表示（削除済みエグゼキュータ一覧、存在する場合のみ）
5. エグゼキュータのstdout/stderrログへのリンク

**画面遷移**：
- 遷移元：Master Overview画面（No.24）のアプリケーションID選択
- 遷移先：Spark Application UI（実行中アプリケーション）、Application History UI（完了アプリケーション）、Worker UIのログページ（エグゼキュータログ）

**権限による表示制御**：特になし。Master WebUIのアクセス制御に依存する。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定アプリケーションのExecutor詳細（コア数・メモリ・状態・ログ）をテーブル表示する主処理 |
| 84 | Standaloneクラスタマネージャ | 主機能 | MasterEndpointからアプリケーションのExecutor割り当て情報を取得して表示 |
| 5 | Executorプロセス管理 | 補助機能 | ExecutorのState（RUNNING/EXITED等）・リソース使用状況を表示 |

## 画面種別

詳細

## URL/ルーティング

- **URL**: `/app/?appId={appId}`
- **HTTPメソッド**: GET
- **パラメータ**: `appId` - アプリケーションID（必須）
- **ページ名（WebUIPage）**: `app`

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| appId | 入力（URLパラメータ） | String | 必須 | 対象アプリケーションID |

## 表示項目

### アプリケーション基本情報セクション

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| ID | app.id | アプリケーション識別子 |
| Name | app.desc.name | アプリケーション名 |
| User | app.desc.user | 実行ユーザー |
| Cores | app.desc.maxCores, app.coresGranted, app.coresLeft | コア数（Unlimited/最大値、付与数、残り） |
| Executor Limit | app.getExecutorLimit | エグゼキュータ制限数（Unlimited/制限値、付与数） |
| Executor Memory - Default Resource Profile | app.desc.memoryPerExecutorMB | エグゼキュータあたりのメモリ |
| Executor Resources - Default Resource Profile | app.desc.resourceReqsPerExecutor | エグゼキュータあたりのリソース要件 |
| Submit Date | app.submitDate | 投入日時 |
| Duration | app.duration | 実行時間 |
| State | app.state | アプリケーション状態 |
| Application Detail UI / Application History UI | app.desc.appUiUrl / historyServerUrl | 実行中はSpark UIへのリンク、完了時はHistory UIへのリンク |

### Executor Summaryテーブル

| カラム名 | 説明 |
|----------|------|
| ExecutorID | エグゼキュータ識別子 |
| Worker | 実行ワーカー（Worker UIへのリンク付き） |
| Cores | 割り当てコア数 |
| Memory | 割り当てメモリ |
| Resource Profile Id | リソースプロファイルID |
| Resources | 割り当てリソース |
| State | エグゼキュータ状態 |
| Logs | stdout/stderrログリンク（Worker UIのlogPageへ） |

### Removed Executorsテーブル（存在する場合のみ）

Executor Summaryテーブルと同一のカラム構成。

## イベント仕様

### 1-ページ読み込み

1. URLパラメータ `appId` からアプリケーションIDを取得する
2. `master.askSync[MasterStateResponse](RequestMasterState)` でマスター状態を取得する
3. activeAppsとcompletedAppsからアプリケーションIDに一致するものを検索する
4. アプリケーションが見つからない場合、「No running application with ID {appId}」を表示し、"Not Found"ページを返す
5. 全エグゼキュータ（executors.values + removedExecutors）を取得する
6. 実行中またはEXITEDのエグゼキュータをExecutor Summaryとして表示する
7. それ以外（終了済み）のエグゼキュータをRemoved Executorsとして表示する（存在する場合のみ）
8. アプリケーションの基本情報を生成する
9. 実行中の場合、Application Detail UIリンクを表示する（UIが有効な場合）
10. 完了済みかつHistoryServerURLが設定されている場合、Application History UIリンクを表示する

### 2-ログリンク押下

Logs列のstdout/stderrリンクをクリックすると、Worker UIのlogPageに遷移する。URLは `{workerUrl}/logPage/?appId={appId}&executorId={executorId}&logType=stdout|stderr` となる。

### 3-テーブル折りたたみ

Executor SummaryおよびRemoved Executorsのヘッダをクリックすると、`collapseTable` JavaScript関数で表示/非表示が切り替わる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ読み込み | MasterEndpoint | RPC/SELECT | RequestMasterStateでアプリケーション・エグゼキュータ情報を取得 |

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

#### ApplicationInfo（RPC応答内）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SELECT | id | URLパラメータ appId と一致 | activeApps/completedAppsから検索 |
| SELECT | desc, startTime, endTime, state, coresGranted, executors, removedExecutors | - | 基本情報・エグゼキュータ一覧表示用 |

#### ExecutorDesc（ApplicationInfo内）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SELECT | id, cores, memory, rpId, resources, state, worker | - | エグゼキュータテーブル表示用 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|----------|
| MSG-01 | エラー | "No running application with ID {appId}" | アプリケーションIDに対応するアプリケーションが見つからない場合 |

## 例外処理

| 例外 | 発生条件 | 処理 |
|------|----------|------|
| アプリケーション未発見 | activeAppsとcompletedAppsの両方にappIdが存在しない場合 | "Not Found"タイトルでエラーページを返す |
| RPC通信エラー | MasterEndpointとの通信が失敗した場合 | Spark UIフレームワークによるエラーページ表示 |

## 備考

- エグゼキュータの分類ロジック: `!ExecutorState.isFinished(exec.state) || exec.state == ExecutorState.EXITED` が true のものが Executor Summary に、残りが Removed Executors に分類される
- executors.values（現在保持中）と removedExecutors（削除済み）の和集合から重複排除（toSet.toSeq）して全エグゼキュータを取得する
- Application Detail UIリンクはアプリケーションUI URLが空でない場合にのみ表示される
- reverseProxy設定時はワーカーリンクやアプリケーションUIリンクがプロキシ経由パスとなる
- Executor Limit表示にはツールチップ（ToolTips.APPLICATION_EXECUTOR_LIMIT）が付く
- UIが無効（appUiUrl が空白）の場合は「Disabled」と表示される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ApplicationInfo.scala | `core/src/main/scala/org/apache/spark/deploy/master/ApplicationInfo.scala` | id, desc, startTime, endTime, state, coresGranted, executors, removedExecutors, getExecutorLimit 等のフィールド |
| 1-2 | ExecutorDesc.scala | `core/src/main/scala/org/apache/spark/deploy/master/ExecutorDesc.scala` | id, cores, memory, rpId, resources, state, worker フィールド |

**読解のコツ**: ApplicationInfoはMasterが管理するアプリケーション状態であり、executorsはMap[Int, ExecutorDesc]、removedExecutorsはSeq[ExecutorDesc]である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ApplicationPage.scala | `core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala` | renderメソッド（36-146行目）: appIdパラメータ取得、MasterState取得、アプリ検索、エグゼキュータ分類、HTML生成 |

**主要処理フロー**:
1. **37行目**: `request.getParameter("appId")` でアプリケーションID取得
2. **38行目**: `master.askSync[MasterStateResponse](RequestMasterState)` でマスター状態取得
3. **39-40行目**: activeApps/completedAppsからアプリ検索
4. **41-43行目**: アプリ未発見時のエラーページ返却
5. **48行目**: 全エグゼキュータの取得（executors + removedExecutors、重複排除）
6. **50-52行目**: エグゼキュータの分類（実行中/EXITED vs 終了済み）
7. **57-144行目**: HTML生成（基本情報、UIリンク、エグゼキュータテーブル）
8. **145行目**: `UIUtils.basicSparkPage` でHTMLレスポンス生成

#### Step 3: エグゼキュータ行のレンダリング

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ApplicationPage.scala | `core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala` | executorRowメソッド（148-168行目）: ExecutorDescからHTML行を生成。ワーカーリンク、ログリンク（stdout/stderr）の生成 |

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

```
ApplicationPage.render(request)
    |
    +-- request.getParameter("appId")
    |
    +-- master.askSync[MasterStateResponse](RequestMasterState)
    |
    +-- state.activeApps.find(_.id == appId)
    |       .getOrElse(state.completedApps.find(_.id == appId).orNull)
    |
    +-- [app == null] => エラーページ返却
    |
    +-- allExecutors = (app.executors.values ++ app.removedExecutors).toSet.toSeq
    |
    +-- executors = allExecutors.filter(実行中 or EXITED)
    +-- removedExecutors = allExecutors.diff(executors)
    |
    +-- UIUtils.listingTable(executorHeaders, executorRow, executors)
    +-- UIUtils.listingTable(executorHeaders, executorRow, removedExecutors)
    |
    +-- executorRow(executor)
    |       +-- UIUtils.makeHref(reverseProxy, worker.id, worker.webUiAddress)
    |       +-- stdout/stderr ログリンク生成
    |
    +-- UIUtils.basicSparkPage(request, content, "Application: " + app.desc.name)
```

### データフロー図

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

URLパラメータ "appId"  ───> ApplicationPage.render          ───> HTML Page
                              |                                  |
MasterEndpoint           ───> askSync(RequestMasterState)   ───> アプリ基本情報
  +-- ApplicationInfo          |                                  |
      +-- ExecutorDesc[]  ───> executors/removedExecutorsに分類───> Executor Summary
                              |                                  +-- Removed Executors
                              |                                  |
                         UIUtils.listingTable()                  +-- ログリンク
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ApplicationPage.scala | `core/src/main/scala/org/apache/spark/deploy/master/ui/ApplicationPage.scala` | ソース | アプリケーション詳細画面のメインページクラス |
| MasterPage.scala | `core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala` | ソース | マスター概要画面（遷移元） |
| MasterWebUI.scala | `core/src/main/scala/org/apache/spark/deploy/master/ui/MasterWebUI.scala` | ソース | ページ登録 |
| ApplicationInfo.scala | `core/src/main/scala/org/apache/spark/deploy/master/ApplicationInfo.scala` | ソース | アプリケーション情報データクラス |
| ExecutorDesc.scala | `core/src/main/scala/org/apache/spark/deploy/master/ExecutorDesc.scala` | ソース | エグゼキュータ記述データクラス |
| ExecutorState.scala | `core/src/main/scala/org/apache/spark/deploy/ExecutorState.scala` | ソース | エグゼキュータ状態列挙型 |
| ToolTips.scala | `core/src/main/scala/org/apache/spark/ui/ToolTips.scala` | ソース | APPLICATION_EXECUTOR_LIMITツールチップ定義 |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | HTML生成ユーティリティ |
