# 画面設計書 21-フレームグラフ

## 概要

本ドキュメントは、Apache Flink Web Dashboardの「フレームグラフ」画面の設計仕様を記載したものである。この画面は、ジョブの頂点（オペレーター）ごとのCPU使用率をフレームグラフ形式で視覚化し、パフォーマンスボトルネックの特定を支援する。

### 本画面の処理概要

**業務上の目的・背景**：Flinkジョブの実行中に、どの処理がCPUリソースを最も消費しているかを把握することは、パフォーマンス最適化において極めて重要である。フレームグラフは、スタックトレースをサンプリングし、階層的に視覚化することで、CPUのホットスポットを直感的に特定できる。これにより、開発者はボトルネックとなっているコードパスを迅速に発見し、最適化の対象を明確にできる。

**画面へのアクセス方法**：実行中ジョブ一覧または完了済みジョブ一覧からジョブを選択し、ジョブ概要（DAGグラフ）画面で頂点をクリックして頂点詳細ドロワーを開き、「Flamegraph」タブを選択することでアクセスする。パスは `/job/:status/:jid/overview/:vertexId/flamegraph` となる。

**主要な操作・処理内容**：
1. フレームグラフタイプの選択（On-CPU / Off-CPU / Mixed）
2. サブタスク選択（全サブタスク または 個別サブタスク）
3. フレームグラフの表示・インタラクティブな操作（ズームイン・ズームアウト、詳細表示）
4. サンプリングデータの自動更新

**画面遷移**：
- 遷移元：ジョブ概要（DAGグラフ）画面の頂点詳細ドロワーから「Flamegraph」タブを選択
- 同階層：頂点詳細、サブタスク一覧、TaskManager一覧、ウォーターマーク、アキュムレーター、メトリクスチャート、バックプレッシャータブと相互遷移可能

**権限による表示制御**：特別な権限制御はない。ただし、フレームグラフ機能は設定 `rest.flamegraph.enabled: true` で有効化されている必要がある。また、対象のオペレーターが RUNNING または INITIALIZING 状態でなければサンプリングが行えない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | REST API | 主機能 | フレームグラフデータの取得（/jobs/{jobid}/vertices/{vertexid}/flamegraph API） |
| 57 | メトリクスコア | 補助機能 | CPU使用率のフレームグラフ描画 |

## 画面種別

詳細（頂点詳細ドロワー内タブ）

## URL/ルーティング

- パス: `/job/:status/:jid/overview/:vertexId/flamegraph`
- パラメータ:
  - `status`: ジョブの状態（running / completed）
  - `jid`: ジョブID
  - `vertexId`: 頂点（オペレーター）ID

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | データ型 | 必須 | 説明 |
|--------|--------|----------|---------|------|------|
| グラフタイプ | graphType | 入力 | string(enum) | Yes | On-CPU / Off-CPU / Mixed |
| サブタスクインデックス | subtaskIndex | 入力 | string | Yes | "all" または 数値文字列 |
| フレームグラフデータ | flameGraph | 出力 | JobFlameGraph | - | フレームグラフの構造化データ |
| 終了タイムスタンプ | endTimestamp | 出力 | number | - | サンプリング終了時刻 |

## 表示項目

| 項目名 | 表示位置 | データソース | 書式 | 説明 |
|--------|----------|-------------|------|------|
| タイプ選択ラジオボタン | 上部 | ローカル状態 | ラジオボタングループ | On-CPU / Off-CPU / Mixed |
| サブタスク選択ドロップダウン | 上部 | API | セレクトボックス | all または RUNNINGサブタスクのインデックス |
| 計測時刻 | 上部右 | API | "Measurement: {時間} ago" | サンプリングからの経過時間 |
| フレームグラフ | 中央 | API | d3-flame-graph | CPU使用率の階層的視覚化 |
| ローディングスピナー | 中央 | ローカル状態 | スピナー | データ取得中の表示 |
| エラーメッセージ | 上部 | API/ローカル | テキスト | 各種状態メッセージ |

## イベント仕様

### 1-タイプ選択変更

ラジオボタンでフレームグラフのタイプ（On-CPU / Off-CPU / Mixed）を選択した際に発火する。

- **トリガー**: ラジオボタンクリック（selectFrameGraphType()メソッド呼び出し）
- **処理内容**:
  1. 既存のサブスクリプションを破棄（destroy$.next()）
  2. 選択されたタイプで requestFlameGraph() を呼び出し
  3. REST API `/jobs/{jobid}/vertices/{vertexid}/flamegraph?type={type}` を呼び出し
  4. 取得したデータでフレームグラフを再描画
- **後続処理**: 画面の再レンダリング

### 2-サブタスク選択変更

サブタスクのドロップダウンで特定のサブタスクを選択した際に発火する。

- **トリガー**: セレクトボックス変更（selectSubtask()メソッド呼び出し）
- **処理内容**:
  1. 既存のサブスクリプションを破棄
  2. subtaskIndex を更新
  3. requestFlameGraph() を呼び出し
  4. サブタスク指定時は `/jobs/{jobid}/vertices/{vertexid}/flamegraph?type={type}&subtaskindex={index}` を呼び出し
- **後続処理**: 画面の再レンダリング

### 3-初期化処理

コンポーネント初期化時（ngOnInit）に実行される。

- **トリガー**: コンポーネントマウント
- **処理内容**:
  1. requestRunningSubtasks() でRUNNING/INITIALIZINGサブタスク一覧を取得
  2. requestFlameGraph(ON_CPU) でデフォルトのフレームグラフを取得
- **後続処理**: 画面の初期表示

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

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

本画面はデータの参照のみを行い、データベースへの更新処理は発生しない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベース更新なし |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG-001 | 警告 | "Operator is not running or initializing. Cannot sample flame graph." | オペレーターがRUNNING/INITIALIZING以外の状態 |
| MSG-002 | 情報 | "The task has already been terminated" | endTimestamp が -1 の場合 |
| MSG-003 | 警告 | "The flame graph feature is currently disabled (enable it by setting rest.flamegraph.enabled: true)" | endTimestamp が -2 の場合 |
| MSG-004 | 情報 | "We are waiting for the first samples to create a flame graph" | endTimestamp が -3 の場合 |
| MSG-005 | 情報 | "Measurement: {duration} ago" | 正常にデータ取得できた場合 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| オペレーターが停止済み | endTimestamp = -1 としてメッセージ表示、フレームグラフは空 |
| フレームグラフ機能が無効 | endTimestamp = -2 として設定変更を促すメッセージ表示 |
| サンプリング待ち | endTimestamp = -3 として待機メッセージ表示 |
| API通信エラー | isLoading = false に設定し、ローディング表示を停止 |
| サブタスク取得エラー | listOfSampleableSubtasks を [all] のみにリセット |

## 備考

- フレームグラフの描画には d3-flame-graph ライブラリを使用
- On-CPU: Thread.State が RUNNABLE または NEW のスレッドのスタックトレース
- Off-CPU: Thread.State が WAITING, TIMED_WAITING, BLOCKED のスレッドのスタックトレース
- Mixed: すべての状態のスレッドのスタックトレース
- サンプリングは継続的に行われ、画面は自動的に更新される

---

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

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

### 推奨読解順序

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

フレームグラフのデータ構造と、フレームグラフタイプの列挙型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | job-flamegraph.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/job-flamegraph.ts` | JobFlameGraph, JobFlameGraphNode インターフェース、FlameGraphType enum の定義 |

**読解のコツ**: JobFlameGraphNode は再帰的な構造（children プロパティ）を持ち、コールスタックの階層を表現している。value はサンプル数を表す。

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

画面コンポーネントのメイン実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | job-overview-drawer-flamegraph.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/job/overview/flamegraph/job-overview-drawer-flamegraph.component.ts` | コンポーネントの主要ロジック |

**主要処理フロー**:
1. **75-78行目**: ngOnInit で requestRunningSubtasks() と requestFlameGraph() を呼び出し
2. **85-119行目**: requestFlameGraph() でフレームグラフデータを取得
3. **121-147行目**: requestRunningSubtasks() で実行中サブタスク一覧を取得
4. **149-154行目**: selectSubtask() でサブタスク変更時の処理
5. **156-159行目**: selectFrameGraphType() でグラフタイプ変更時の処理

#### Step 3: テンプレートを理解する

HTMLテンプレートの構造とデータバインディングを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | job-overview-drawer-flamegraph.component.html | `flink-runtime-web/web-dashboard/src/app/pages/job/overview/flamegraph/job-overview-drawer-flamegraph.component.html` | UI構造とイベントバインディング |

**主要処理フロー**:
- **19-26行目**: オペレーター状態チェックと警告メッセージ
- **29-54行目**: タイプ選択ラジオボタン（On-CPU / Off-CPU / Mixed）
- **57-71行目**: サブタスク選択ドロップダウン
- **74-84行目**: 状態に応じたメッセージ表示（ngSwitch）
- **86-88行目**: フレームグラフコンポーネントの配置

#### Step 4: サービス層を理解する

REST API呼び出しを行うサービスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | job.service.ts | `flink-runtime-web/web-dashboard/src/app/services/job.service.ts` | loadOperatorFlameGraph, loadOperatorFlameGraphForSingleSubtask メソッド |

**主要処理フロー**:
- **122-126行目**: loadOperatorFlameGraph() - 全サブタスクのフレームグラフ取得
- **128-137行目**: loadOperatorFlameGraphForSingleSubtask() - 個別サブタスクのフレームグラフ取得
- **139-143行目**: loadSubTasks() - サブタスク一覧取得

#### Step 5: フレームグラフ描画コンポーネントを理解する

d3-flame-graph を使用した描画処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | flame-graph.component.ts | `flink-runtime-web/web-dashboard/src/app/components/flame-graph/flame-graph.component.ts` | d3-flame-graph による描画ロジック |

**主要処理フロー**:
- **38-63行目**: draw() メソッド - フレームグラフの描画処理
- **56-58行目**: Off-CPU タイプ時の色設定

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

```
JobOverviewDrawerFlameGraphComponent
    │
    ├─ ngOnInit()
    │      ├─ requestRunningSubtasks()
    │      │      └─ JobService.loadSubTasks()
    │      │             └─ HTTP GET /jobs/{jid}/vertices/{vertexId}
    │      │
    │      └─ requestFlameGraph()
    │             ├─ JobService.loadOperatorFlameGraph()
    │             │      └─ HTTP GET /jobs/{jid}/vertices/{vertexId}/flamegraph?type={type}
    │             │
    │             └─ JobService.loadOperatorFlameGraphForSingleSubtask()
    │                    └─ HTTP GET /jobs/{jid}/vertices/{vertexId}/flamegraph?type={type}&subtaskindex={index}
    │
    ├─ selectFrameGraphType()
    │      └─ requestFlameGraph()
    │
    └─ selectSubtask()
           └─ requestFlameGraph()
```

### データフロー図

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

グラフタイプ選択 ─────┐
                     │
サブタスク選択 ──────┼──▶ JobOverviewDrawerFlameGraphComponent ───▶ FlameGraphComponent
                     │              │                                     │
ジョブID/頂点ID ────┘              │                                     │
                                   ▼                                     ▼
                              JobService                         d3-flame-graph
                                   │                                     │
                                   ▼                                     ▼
                           REST API呼び出し                      SVG描画出力
                                   │
                                   ▼
                    JobFlameGraph (JSON レスポンス)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| job-overview-drawer-flamegraph.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/job/overview/flamegraph/job-overview-drawer-flamegraph.component.ts` | ソース | メインコンポーネント |
| job-overview-drawer-flamegraph.component.html | `flink-runtime-web/web-dashboard/src/app/pages/job/overview/flamegraph/job-overview-drawer-flamegraph.component.html` | テンプレート | UI構造定義 |
| job-overview-drawer-flamegraph.component.less | `flink-runtime-web/web-dashboard/src/app/pages/job/overview/flamegraph/job-overview-drawer-flamegraph.component.less` | スタイル | コンポーネント固有スタイル |
| job-flamegraph.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/job-flamegraph.ts` | ソース | データ型定義 |
| job.service.ts | `flink-runtime-web/web-dashboard/src/app/services/job.service.ts` | ソース | API呼び出しサービス |
| flame-graph.component.ts | `flink-runtime-web/web-dashboard/src/app/components/flame-graph/flame-graph.component.ts` | ソース | フレームグラフ描画コンポーネント |
| job-local.service.ts | `flink-runtime-web/web-dashboard/src/app/pages/job/job-local.service.ts` | ソース | ジョブコンテキスト管理サービス |
