# 帳票設計書 24-StreamingQueryPage

## 概要

本ドキュメントは、Apache Spark Web UI における Structured Streaming クエリ一覧ページ（StreamingQueryPage）の帳票設計書である。Structured Streaming クエリの実行状況を Active / Completed に分類して一覧表示する HTML レポートページの仕様を定義する。

### 本帳票の処理概要

StreamingQueryPage は Structured Streaming で実行中および完了済みのストリーミングクエリをページ付きテーブル形式で表示する帳票レポートページである。

**業務上の目的・背景**：Structured Streaming を用いたリアルタイムデータ処理パイプラインの運用において、稼働中のクエリの状態把握と完了済みクエリの履歴確認は、システムの健全性監視の基礎となる。本帳票により、全ストリーミングクエリの一覧を効率的に把握できる。

**帳票の利用シーン**：Structured Streaming アプリケーション実行中に「Structured Streaming」タブを開き、クエリの稼働状態を確認する際に利用される。入力レートや処理レートの概要確認、エラー発生有無の初期チェックに使われる。

**主要な出力内容**：
1. Active Streaming Queries テーブル（稼働中クエリ一覧）
2. Completed Streaming Queries テーブル（完了済みクエリ一覧とエラー情報）
3. 各クエリの Name、Status、ID、Run ID、Start Time、Duration、Avg Input/sec、Avg Process/sec、Latest Batch

**帳票の出力タイミング**：Spark Web UI の「Structured Streaming」タブにアクセスした際にリアルタイムで生成される。

**帳票の利用者**：ストリーミングパイプライン運用担当者、データエンジニア、SRE

## 帳票種別

Web UI ページ（一覧表）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| 24 | StreamingQueryPage | `/StreamingQuery/` | Spark UI の「Structured Streaming」タブをクリック |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTML（Web UI ページ） |
| 用紙サイズ | N/A（ブラウザ表示） |
| 向き | N/A |
| ファイル名 | N/A（動的 HTML レスポンス） |
| 出力方法 | ブラウザ上にリアルタイム表示 |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

```
+---------------------------------------------+
|   Spark UI ヘッダー (Streaming Query)          |
+---------------------------------------------+
| ▼ Active Streaming Queries ({count})         |
| +------------------------------------------+|
| | Name | Status | ID | Run ID | Start Time ||
| | Duration | Avg Input/sec | Avg Process   ||
| |   /sec | Latest Batch                     ||
| +------------------------------------------+|
+---------------------------------------------+
| ▼ Completed Streaming Queries ({count})      |
| +------------------------------------------+|
| | Name | Status | ID | Run ID | Start Time ||
| | Duration | Avg Input/sec | Avg Process   ||
| |   /sec | Latest Batch | Error            ||
| +------------------------------------------+|
+---------------------------------------------+
```

### ヘッダー部

N/A（テーブルセクションヘッダーのみ）

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Name | クエリ名 | UIUtils.getQueryName(streamingQuery) | テキスト | auto |
| 2 | Status | クエリ状態 | UIUtils.getQueryStatus(streamingQuery) | テキスト | auto |
| 3 | ID | クエリ ID (UUID) | summary.id | UUID | auto |
| 4 | Run ID | 実行 ID (UUID) | summary.runId | UUID リンク（統計ページへ） | auto |
| 5 | Start Time | 開始時刻 | summary.startTimestamp | SparkUIUtils.formatDate | auto |
| 6 | Duration | 実行時間 | 計算値 | SparkUIUtils.formatDurationVerbose | auto |
| 7 | Avg Input /sec | 平均入力レート | recentProgress.inputRowsPerSecond 平均 | "%.2f" 形式 | auto |
| 8 | Avg Process /sec | 平均処理レート | recentProgress.processedRowsPerSecond 平均 | "%.2f" 形式 | auto |
| 9 | Latest Batch | 最新バッチ ID | lastProgress.batchId | 数値 | auto |
| 10 | Error | エラー情報 | summary.exception | テキスト（Completed のみ） | auto |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ページネーション | テーブルのページ切り替え | PagedTable 基盤 | ページ番号リンク |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| summary.isActive | Active / Completed の分類 | N/A（自動分類） |
| {tag}.page | ページ番号 | No（デフォルト: 1） |
| {tag}.sort | ソートカラム名 | No（デフォルト: Start Time） |
| {tag}.desc | 降順フラグ | No |
| {tag}.pageSize | ページサイズ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | Start Time（デフォルト） | 昇順（切替可能） |

### 改ページ条件

PagedTable フレームワークにより pageSize 単位でページ分割される。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| StreamingQueryStatusStore | ストリーミングクエリ情報の取得 | N/A |

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

#### StreamingQueryStatusStore

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| allQueryUIData | 全クエリ一覧 | なし | StreamingQueryUIData のリスト |
| summary.isActive | Active/Completed 分類 | - | Boolean |
| summary.id | ID | - | UUID |
| summary.runId | Run ID | - | UUID |
| summary.startTimestamp | Start Time | - | Long |
| recentProgress | 平均レート計算元 | - | Array[StreamingQueryProgress] |
| lastProgress | Latest Batch | - | StreamingQueryProgress |
| summary.exception | Error | - | Option[String] |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Duration (Active) | currentTimeMillis - startTimestamp | なし | ミリ秒 |
| Duration (Completed) | parseProgressTimestamp(lastProgress.timestamp) - startTimestamp | なし | ミリ秒 |
| Avg Input /sec | sum(recentProgress.inputRowsPerSecond) / recentProgress.length | 小数点以下2桁 | NaN の場合 "NaN" 表示 |
| Avg Process /sec | sum(recentProgress.processedRowsPerSecond) / recentProgress.length | 小数点以下2桁 | NaN の場合 "NaN" 表示 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B[parent.store.allQueryUIData 取得]
    B --> C[isActive で Active/Completed に分類]
    C --> D{Active クエリあり？}
    D -->|Yes| E[Active テーブル生成]
    D -->|No| F{Completed クエリあり？}
    E --> F
    F -->|Yes| G[Completed テーブル生成]
    F -->|No| H[headerSparkPage で HTML 生成]
    G --> H
    H --> I[レスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| テーブル描画エラー | IllegalArgumentException / IndexOutOfBoundsException | "Error while rendering execution table: {exception}" | 不正なパラメータを修正する |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数個～数十のストリーミングクエリ |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | Spark Web UI のスレッドプール制約に従う |

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

- クエリ名やエラーメッセージにビジネスロジック固有の情報が含まれる可能性がある。
- Spark UI のアクセス制御を適切に設定すること。

## 備考

- Run ID リンクから StreamingQueryStatisticsPage（No.25）の詳細統計ページへ遷移可能。
- Progress データが存在しない場合は "NaN" と表示される（withNoProgress ヘルパー関数使用）。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | StreamingQueryUIData | `sql/core/src/main/scala/org/apache/spark/sql/execution/ui/StreamingQueryStatusStore.scala` | summary, recentProgress, lastProgress の構造 |
| 1-2 | StructuredStreamingRow | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala` | テーブル行データ（行203-207） |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StreamingQueryTab.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryTab.scala` | ページ登録（行31） |
| 2-2 | StreamingQueryPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala` | render() メソッド（行36-39） |

**主要処理フロー**:
1. **行37**: generateStreamingQueryTable(request) でメインコンテンツ生成
2. **行42-43**: allQueryUIData を Active/Completed に partition
3. **行47-81**: 各テーブルの生成

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StreamingQueryPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala` | StreamingQueryPagedTable クラス（行113-201）- ヘッダー・行HTML生成 |
| 3-2 | StreamingQueryPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala` | StreamingQueryDataSource クラス（行209-261）- データ変換とソート |

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

```
SparkUI
    |
    +-- StreamingQueryTab (SparkUITab, prefix="StreamingQuery")
           |
           +-- StreamingQueryPage (WebUIPage, prefix="")
           |      |
           |      +-- render(request)
           |             +-- generateStreamingQueryTable(request)
           |                    +-- parent.store.allQueryUIData
           |                    +-- partition(isActive)
           |                    +-- queryTable() [Active/Completed]
           |                           +-- StreamingQueryPagedTable
           |                                  +-- StreamingQueryDataSource
           |
           +-- StreamingQueryStatisticsPage (No.25)
```

### データフロー図

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

HTTPリクエスト              StreamingQueryPage.render()
                       --> generateStreamingQueryTable()  --> HTML レスポンス
                            |                               (Active/Completed
StreamingQueryStatusStore   |                                テーブル)
(インメモリ)            --> allQueryUIData
                            |
                            +-- partition(isActive)
                            +-- StreamingQueryPagedTable
                                 +-- ソート・ページング
                                 +-- Duration/AvgRate 計算
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| StreamingQueryPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryPage.scala` | ソース | メインページクラス |
| StreamingQueryTab.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryTab.scala` | ソース | タブ登録 |
| StreamingQueryStatusStore.scala | `sql/core/src/main/scala/org/apache/spark/sql/execution/ui/StreamingQueryStatusStore.scala` | ソース | データストア |
| UIUtils.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/UIUtils.scala` | ソース | ストリーミング固有ユーティリティ（getQueryName, getQueryStatus, withNoProgress 等） |
| StreamingQueryStatisticsPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryStatisticsPage.scala` | ソース | 詳細統計ページ（リンク先） |
