# 画面設計書 11-Executor Thread Dump（エグゼキュータスレッドダンプ）

## 概要

本ドキュメントは、Apache Spark Application UIのExecutorsタブ配下にあるExecutor Thread Dump画面の設計内容を記述する。本画面は特定エグゼキュータのスレッドダンプ情報をサマリー・スタックトレース・フレイムグラフの形式で表示する。

### 本画面の処理概要

**業務上の目的・背景**：Sparkアプリケーションのパフォーマンス問題やデッドロックの調査において、エグゼキュータ上のスレッドの状態を確認することは不可欠である。本画面により、運用者や開発者は特定エグゼキュータの全スレッドの状態（RUNNABLE、WAITING、BLOCKED等）を一覧で把握し、ボトルネックやロック競合の原因を特定できる。フレイムグラフ機能を有効にすることで、スタックトレースの視覚的な分析も可能となる。

**画面へのアクセス方法**：Executors一覧画面（No.10）のテーブル内にある「Thread Dump」リンクをクリックすることでアクセスする。URLパラメータとしてexecutorIdが必要である。spark.ui.threadDumpsEnabledが有効（デフォルト: true）である必要がある。

**主要な操作・処理内容**：
1. スレッドダンプサマリーテーブルで、スレッドの状態別件数と割合を確認する
2. フレイムグラフ（有効時）でスタックトレースの分布を視覚的に分析する
3. スレッドスタックトレーステーブルで個別スレッドの詳細を展開・確認する
4. 検索ボックスでスレッド名やスタックトレースをフィルタリングする
5. Expand All / Collapse Allで全スレッドのスタックトレースを一括展開・折りたたみする
6. スレッドダンプをテキスト形式でダウンロードする

**画面遷移**：Executors一覧画面（No.10）から遷移してくる。Stage Detail画面（No.4）からもエグゼキュータIDリンク経由で遷移可能。本画面からの遷移先はない。

**権限による表示制御**：spark.ui.threadDumpsEnabled（デフォルト: true）が無効の場合、本画面は利用不可。ACL設定（spark.acls.enable）が有効な場合、閲覧権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定Executorの全スレッドダンプをサマリー・スタックトレース・フレイムグラフで表示する主処理 |
| 5 | Executorプロセス管理 | 主機能 | SparkContext.getExecutorThreadDumpを呼び出しExecutorのスレッドダンプを取得 |

## 画面種別

詳細

## URL/ルーティング

- パス: `/executors/threadDump/`
- パラメータ: `executorId` (必須) - 対象エグゼキュータのID
- 例: `/executors/threadDump/?executorId=1`

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| executorId | 入力（URLパラメータ） | String | 必須 | 対象エグゼキュータのID |

## 表示項目

### Thread Dump Summary テーブル

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Thread State | String | スレッドの状態（RUNNABLE, WAITING, TIMED_WAITING, BLOCKED等） |
| Count | Int | 該当状態のスレッド数 |
| Percentage | String | 全スレッドに対する割合（小数2桁、%付き） |

### Flame Graph セクション（spark.ui.flamegraph.enabled=true時のみ）

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Flame Graph | SVG | D3.jsによるフレイムグラフ。スタックトレースの階層構造を視覚化 |

### Thread Stack Trace テーブル

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Thread ID | Long | スレッドID |
| Thread Name | String | スレッド名 |
| Thread State | String | スレッドの状態 |
| Thread Locks | String | ブロック元スレッド情報および保持中のロック（Synchronizer/Monitor） |
| Stack Trace | String | スタックトレース（行クリックで展開表示） |

## イベント仕様

### 1-行クリック（スタックトレース展開）

テーブル行をクリックすると、該当スレッドのスタックトレースが行内に展開表示される。再度クリックで折りたたむ。JavaScriptのtoggleThreadStackTrace関数で制御される。

### 2-Expand All / Collapse All

「Expand All」ボタンクリックで全スレッドのスタックトレースを展開し、ボタンが「Collapse All」に切り替わる。「Collapse All」クリックで全て折りたたむ。

### 3-Search（検索フィルタ）

検索ボックスに文字を入力すると、スレッド名やスタックトレースに一致するスレッドのみがリアルタイムでフィルタリング表示される。onSearchStringChange関数で制御される。

### 4-Download（ダウンロード）

「Download」リンクをクリックすると、全スレッドダンプをテキスト形式（threaddump_{executorId}.txt）としてダウンロードする。data URIスキームを使用。

### 5-Flame Graph 展開/折りたたみ

フレイムグラフセクションのヘッダをクリックすると、フレイムグラフの表示/非表示を切り替える。toggleFlamegraph関数で制御される。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | - | SELECT（リモート呼び出し） | SparkContext経由でExecutorにRPCリクエストを送信しスレッドダンプを取得 |

本画面はデータベースへの更新操作を行わない。エグゼキュータへのリモート呼び出しによりリアルタイムのスレッドダンプを取得する。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG-001 | エラー | "Error fetching thread dump" | スレッドダンプ取得に失敗した場合 |
| MSG-002 | エラー | "Missing executorId parameter" | executorIdパラメータが未指定の場合 |

## 例外処理

- executorIdパラメータが未指定の場合: IllegalArgumentExceptionがスローされ、エラーページが表示される
- スレッドダンプ取得失敗時: "Error fetching thread dump"メッセージが画面に表示される（対象Executorが停止済み・通信不可等）
- Executor通信タイムアウト: SparkContextのRPC呼び出しタイムアウト設定に従い、取得失敗として処理される

## 備考

- spark.ui.threadDumpsEnabled（デフォルト: true）が無効の場合、ExecutorsTabに本ページは登録されない
- spark.ui.flamegraph.enabled（デフォルト: false）が有効の場合、フレイムグラフセクションが追加表示される
- フレイムグラフはD3.js（d3.min.js）およびd3-flamegraph.min.jsライブラリを使用
- スレッドダンプはリアルタイムで取得されるため、ページ表示時点のスナップショットである
- ページ上部に取得時刻が「Updated at {日時}」形式で表示される

---

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

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

### 推奨読解順序

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

まず、スレッドダンプデータの構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ThreadStackTrace.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | ThreadStackTraceクラスのフィールド（threadId, threadName, threadState, stackTrace, blockedByThreadId, blockedByLock, synchronizers, monitors）を確認 |
| 1-2 | FlamegraphNode.scala | `core/src/main/scala/org/apache/spark/ui/flamegraph/FlamegraphNode.scala` | フレイムグラフ用のノード構造とJSON変換ロジックを確認 |

**読解のコツ**: ThreadStackTraceはREST API（v1）のモデルクラスでもあるため、JSONシリアライズ対応の構造になっている。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ExecutorsTab.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala` | 行32-43: threadDumpEnabledの判定とページ登録。UI_THREAD_DUMPS_ENABLED設定で制御 |
| 2-2 | ExecutorThreadDumpPage.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala` | 行31-33: クラス定義。WebUIPage("threadDump")でURLパスを設定 |

**主要処理フロー**:
1. **行37-42**: renderメソッドでexecutorIdパラメータを取得・URLデコード
2. **行44**: sc.get.getExecutorThreadDump(executorId)でスレッドダンプを取得
3. **行46-71**: スレッドダンプの各スレッドをテーブル行に変換
4. **行76-81**: flamegraphEnabledの場合、drawExecutorFlamegraphを呼び出し
5. **行109-122**: スタックトレーステーブルのHTML生成
6. **行126**: UIUtils.headerSparkPageでページ全体をラップ

#### Step 3: サマリーテーブル生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ExecutorThreadDumpPage.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala` | 行158-182: threadDumpSummaryメソッド。groupByでスレッド状態別に集計し、件数と割合を計算 |

#### Step 4: フレイムグラフ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ExecutorThreadDumpPage.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala` | 行129-155: drawExecutorFlamegraphメソッド。FlamegraphNode(thread).toJsonStringでデータ生成し、D3.jsで描画 |
| 4-2 | FlamegraphNode.scala | `core/src/main/scala/org/apache/spark/ui/flamegraph/FlamegraphNode.scala` | スレッドダンプからフレイムグラフ用のツリー構造を構築するロジック |

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

```
ExecutorsTab.init() [行31-44]
    |
    +-- ExecutorThreadDumpPage (UI_THREAD_DUMPS_ENABLED=true時のみ登録)
            |
            +-- render(request) [行37]
                    |
                    +-- UIUtils.decodeURLParameter(executorId) [行38-39]
                    |
                    +-- sc.get.getExecutorThreadDump(executorId) [行44]
                    |       |
                    |       +-- SparkContext -> Executor RPC呼び出し
                    |
                    +-- threadDumpSummary(threadDump) [行76]
                    |       |
                    |       +-- groupBy(_.threadState) -> Count/Percentage計算
                    |
                    +-- drawExecutorFlamegraph(request, threadDump) [行78] (flamegraphEnabled時)
                    |       |
                    |       +-- FlamegraphNode(thread).toJsonString
                    |       +-- D3.js flamegraph描画
                    |
                    +-- テーブル行生成（dumpRows） [行47-71]
                    |
                    +-- UIUtils.headerSparkPage() [行126]
```

### データフロー図

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

executorId ──────────────> ExecutorThreadDumpPage.render()
(URLパラメータ)                    |
                                   +---> SparkContext
                                   |     .getExecutorThreadDump() ──> RPC to Executor
                                   |           |
                                   |     Array[ThreadStackTrace] <──
                                   |           |
                                   +---> threadDumpSummary() ──────> サマリーテーブルHTML
                                   |
                                   +---> drawExecutorFlamegraph() ─> フレイムグラフHTML
                                   |     (flamegraphEnabled時)
                                   |
                                   +---> dumpRows生成 ─────────────> スタックトレーステーブルHTML
                                   |
                                   +---> headerSparkPage() ────────> 完成ページHTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ExecutorThreadDumpPage.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorThreadDumpPage.scala` | ソース | メイン画面ページクラス |
| ExecutorsTab.scala | `core/src/main/scala/org/apache/spark/ui/exec/ExecutorsTab.scala` | ソース | タブ定義・ページ登録 |
| FlamegraphNode.scala | `core/src/main/scala/org/apache/spark/ui/flamegraph/FlamegraphNode.scala` | ソース | フレイムグラフデータ構造 |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | UI共通ユーティリティ |
| SparkContext.scala | `core/src/main/scala/org/apache/spark/SparkContext.scala` | ソース | getExecutorThreadDumpメソッド |
| api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | ソース | ThreadStackTraceデータモデル |
| flamegraph.js | `core/src/main/resources/org/apache/spark/ui/static/flamegraph.js` | JavaScript | フレイムグラフ描画ロジック |
| d3.min.js | `core/src/main/resources/org/apache/spark/ui/static/d3.min.js` | JavaScript | D3.jsライブラリ |
| d3-flamegraph.min.js | `core/src/main/resources/org/apache/spark/ui/static/d3-flamegraph.min.js` | JavaScript | D3フレイムグラフライブラリ |
| d3-flamegraph.css | `core/src/main/resources/org/apache/spark/ui/static/d3-flamegraph.css` | CSS | フレイムグラフスタイル |
