# 帳票設計書 25-StreamingQueryStatisticsPage

## 概要

本ドキュメントは、Apache Spark Web UI における Structured Streaming クエリ統計情報ページ（StreamingQueryStatisticsPage）の帳票設計書である。個別ストリーミングクエリの詳細統計（入力レート、処理レート、バッチ所要時間、ステート情報等）をタイムラインとヒストグラムで可視化する HTML レポートページの仕様を定義する。

### 本帳票の処理概要

StreamingQueryStatisticsPage は特定の Structured Streaming クエリについて、入力レート・処理レート・入力行数・バッチ所要時間・操作別所要時間をタイムライングラフとヒストグラムで可視化し、さらにステートオペレータの集約メトリクスやウォーターマーク情報をグラフ表示する帳票レポートページである。

**業務上の目的・背景**：ストリーミング処理のパフォーマンス監視において、入力レートと処理レートのバランスや、バッチ処理時間の推移を視覚的に把握することは、処理遅延の検知やキャパシティプランニングの基礎となる。本帳票により、ストリーミングクエリの健全性を多角的に分析できる。

**帳票の利用シーン**：StreamingQueryPage（No.24）から特定クエリの Run ID をクリックして遷移する詳細統計ページとして利用される。ストリーミングクエリの処理遅延調査、ステート肥大化の監視、ウォーターマークギャップの確認などに使用される。

**主要な出力内容**：
1. 基本情報（実行時間、開始時刻、完了バッチ数、Name、ID、RunId）
2. Input Rate タイムライン・ヒストグラム
3. Process Rate タイムライン・ヒストグラム
4. Input Rows タイムライン・ヒストグラム
5. Batch Duration タイムライン・ヒストグラム
6. Operation Duration エリアスタックグラフ
7. Global Watermark Gap タイムライン・ヒストグラム
8. ステートオペレータ集約メトリクス（Total/Updated/Removed Rows、Memory Used、Dropped by Watermark）
9. カスタムメトリクス（設定で有効化時）

**帳票の出力タイミング**：StreamingQueryPage から特定クエリの Run ID リンクをクリックした際に生成される。

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

## 帳票種別

Web UI ページ（統計グラフ集計表）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| 25 | StreamingQueryStatisticsPage | `/StreamingQuery/statistics/?id={runId}` | StreamingQueryPage の Run ID リンクをクリック |

## 出力形式

### 基本仕様

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

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

```
+---------------------------------------------+
|   Spark UI ヘッダー                            |
|   "Streaming Query Statistics"               |
+---------------------------------------------+
| Running batches for {duration} since {date}  |
| ({numBatches} completed batches)             |
| Name: {name}  Id: {id}  RunId: {runId}      |
+---------------------------------------------+
| 統計テーブル                                   |
| +-------------------------------------------+|
| |          | Timelines    | Histograms      ||
| |----------+--------------+-----------------||
| | Input Rate | [timeline]  | [histogram]    ||
| | Process Rate | [timeline] | [histogram]   ||
| | Input Rows | [timeline]  | [histogram]    ||
| | Batch Duration | [timeline] | [histogram] ||
| | Operation Duration | [area stack chart]   ||
| | Watermark Gap | [timeline] | [histogram]  ||
| | State Rows Total | [timeline] | [histo]   ||
| | State Rows Updated | [timeline] | [histo] ||
| | State Rows Removed | [timeline] | [histo] ||
| | State Memory | [timeline] | [histogram]   ||
| | Dropped by WM | [timeline] | [histogram]  ||
| | Custom Metrics... | [timeline] | [histo]  ||
| +-------------------------------------------+|
+---------------------------------------------+
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 実行時間 | クエリの稼働時間 | currentTime - startTimestamp (Active) / last - first progress (Completed) | formatDurationVerbose |
| 2 | 開始時刻 | クエリ開始時刻 | summary.startTimestamp | formatDate |
| 3 | 完了バッチ数 | 処理済みバッチ数 | lastProgress.batchId + 1 | 数値 |
| 4 | Name | クエリ名 | UIUtils.getQueryName | テキスト |
| 5 | Id | クエリ ID | summary.id | UUID |
| 6 | RunId | 実行 ID | summary.runId | UUID |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Input Rate | 入力レート推移 | recentProgress.inputRowsPerSecond | タイムライン + ヒストグラム (records/sec) | 492px + 350px |
| 2 | Process Rate | 処理レート推移 | recentProgress.processedRowsPerSecond | タイムライン + ヒストグラム (records/sec) | 同上 |
| 3 | Input Rows | 入力行数推移 | recentProgress.numInputRows | タイムライン + ヒストグラム (records) | 同上 |
| 4 | Batch Duration | バッチ処理時間推移 | recentProgress.batchDuration | タイムライン + ヒストグラム (ms) | 同上 |
| 5 | Operation Duration | 操作別時間推移 | recentProgress.durationMs | エリアスタックグラフ (ms) | colspan=2 |
| 6 | Watermark Gap | ウォーターマークギャップ | eventTime.watermark | タイムライン + ヒストグラム (seconds) | 同上 |
| 7 | Total State Rows | ステート行数合計 | stateOperators.numRowsTotal | タイムライン + ヒストグラム (records) | 同上 |
| 8 | Updated State Rows | 更新ステート行数 | stateOperators.numRowsUpdated | タイムライン + ヒストグラム (records) | 同上 |
| 9 | Removed State Rows | 削除ステート行数 | stateOperators.numRowsRemoved | タイムライン + ヒストグラム (records) | 同上 |
| 10 | State Memory | ステートメモリ使用量 | stateOperators.memoryUsedBytes | タイムライン + ヒストグラム (bytes) | 同上 |
| 11 | Dropped by Watermark | WM により破棄された行数 | stateOperators.numRowsDroppedByWatermark | タイムライン + ヒストグラム (records) | 同上 |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| id | Run ID (UUID) | Yes |

### ソート順

N/A（時系列データのグラフ表示）

### 改ページ条件

N/A（単一ページ）

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| StreamingQueryStatusStore | ストリーミングクエリの進捗データ取得 | runId |

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

#### StreamingQueryStatusStore

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| allQueryUIData | クエリデータ | runId で filter | StreamingQueryUIData |
| summary | 基本情報 | - | StreamingQuerySummary |
| recentProgress | タイムラインデータ | - | Array[StreamingQueryProgress] |
| lastProgress | 最新バッチデータ | - | StreamingQueryProgress |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Watermark Gap | (batchTimestamp - watermarkValue) / 1000.0 | なし | 秒単位 |
| Total State Rows (集約) | sum(stateOperators.numRowsTotal) | なし | 全オペレータ合計 |
| Updated State Rows (集約) | sum(stateOperators.numRowsUpdated) | なし | 全オペレータ合計 |
| State Memory (集約) | sum(stateOperators.memoryUsedBytes) | なし | 全オペレータ合計 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B{id パラメータあり？}
    B -->|No| C[エラー: Missing id parameter]
    B -->|Yes| D[runId でクエリデータ検索]
    D --> E{データ存在？}
    E -->|No| F[エラー: Failed to find streaming query]
    E -->|Yes| G[基本情報生成]
    G --> H[統計テーブル生成]
    H --> I[GraphUIData でグラフ描画]
    I --> J[Watermark / State メトリクス生成]
    J --> K[カスタムメトリクス生成]
    K --> L[headerSparkPage で HTML 生成]
    L --> M[レスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| パラメータ不足 | id が null または空 | "Missing id parameter" | 正しい Run ID を指定する |
| データなし | runId のクエリが見つからない | "Failed to find streaming query {id}" | 正しい Run ID を確認する |
| Progress なし | lastProgress が null | "No visualization information available." | クエリがバッチを処理するまで待つ |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | recentProgress 配列サイズ（通常数百件） |
| 目標出力時間 | 2秒以内（グラフ描画含む） |
| 同時出力数上限 | Spark Web UI のスレッドプール制約に従う |

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

- ストリーミングクエリの詳細統計にはアプリケーション固有の処理特性が反映されるため、Spark UI のアクセス制御を適切に設定すること。
- JavaScript による動的グラフ描画を行うため、静的リソースの提供パスが正しく制御されていることを確認すること。

## 備考

- グラフ描画には D3.js と structured-streaming-page.js を使用する。
- Operation Duration は triggerExecution を除外して表示する（他の操作の合計と重複するため）。
- カスタムメトリクスは STATE_STORE_PROVIDER_CLASS に設定された StateStoreProvider の supportedCustomMetrics と ENABLED_STREAMING_UI_CUSTOM_METRIC_LIST 設定の積集合で表示対象が決まる。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | StreamingQueryUIData | `sql/core/src/main/scala/org/apache/spark/sql/execution/ui/StreamingQueryStatusStore.scala` | summary, recentProgress, lastProgress の構造 |
| 1-2 | StreamingQueryProgress | Spark SQL API | inputRowsPerSecond, processedRowsPerSecond, batchDuration, durationMs, stateOperators, eventTime 等 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | StreamingQueryStatisticsPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryStatisticsPage.scala` | render() メソッド（行59-74）が起点 |

**主要処理フロー**:
1. **行60-61**: id パラメータの取得・検証
2. **行63-65**: runId でクエリデータ検索
3. **行67-68**: リソース読み込みと基本情報生成
4. **行69-72**: 統計テーブル生成
5. **行73**: headerSparkPage で HTML 生成

#### Step 3: グラフ描画を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StreamingQueryStatisticsPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryStatisticsPage.scala` | generateStatTable() メソッド（行390-564）- メイングラフ生成ロジック |
| 3-2 | GraphUIData | `core/src/main/scala/org/apache/spark/ui/GraphUIData.scala` | タイムライン・ヒストグラム描画の共通基盤 |

#### Step 4: ステートメトリクスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | StreamingQueryStatisticsPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryStatisticsPage.scala` | generateAggregatedStateOperators() メソッド（行198-343）とgenerateWatermark() メソッド（行146-196） |

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

```
StreamingQueryTab
    |
    +-- StreamingQueryStatisticsPage (WebUIPage, prefix="statistics")
           |
           +-- render(request)
                  +-- generateLoadResources()
                  +-- generateBasicInfo(query)
                  +-- generateStatTable(query, request)
                         +-- GraphUIData (Input Rate)
                         +-- GraphUIData (Process Rate)
                         +-- GraphUIData (Input Rows)
                         +-- GraphUIData (Batch Duration)
                         +-- GraphUIData (Operation Duration - area stack)
                         +-- generateWatermark()
                         |      +-- GraphUIData (Watermark Gap)
                         +-- generateAggregatedStateOperators()
                         |      +-- GraphUIData (Total/Updated/Removed Rows)
                         |      +-- GraphUIData (Memory Used)
                         |      +-- GraphUIData (Dropped by Watermark)
                         +-- generateAggregatedCustomMetrics()
                                +-- GraphUIData (各カスタムメトリクス)
```

### データフロー図

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

HTTPリクエスト              render()
(id={runId})           --> パラメータ検証                  --> HTML レスポンス
                            |                                (基本情報 +
StreamingQueryStatusStore   |                                 タイムライン +
(インメモリ)            --> allQueryUIData.find(runId)         ヒストグラム +
                            |                                 エリアスタック)
                            +-- recentProgress 解析
                            +-- GraphUIData 生成
                            +-- JsCollector で JS 集約
                            +-- D3.js でグラフ描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| StreamingQueryStatisticsPage.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryStatisticsPage.scala` | ソース | メインページクラス |
| StreamingQueryTab.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/StreamingQueryTab.scala` | ソース | タブ登録 |
| UIUtils.scala | `sql/core/src/main/scala/org/apache/spark/sql/streaming/ui/UIUtils.scala` | ソース | ストリーミング UI ユーティリティ |
| GraphUIData.scala | `core/src/main/scala/org/apache/spark/ui/GraphUIData.scala` | ソース | タイムライン・ヒストグラム描画基盤 |
| JsCollector.scala | `core/src/main/scala/org/apache/spark/ui/JsCollector.scala` | ソース | JavaScript コード集約 |
| d3.min.js | `core/src/main/resources/org/apache/spark/ui/static/d3.min.js` | 静的リソース | D3.js ライブラリ |
| streaming-page.js | `core/src/main/resources/org/apache/spark/ui/static/streaming-page.js` | 静的リソース | ストリーミングページ共通 JS |
| structured-streaming-page.js | `core/src/main/resources/org/apache/spark/ui/static/structured-streaming-page.js` | 静的リソース | Structured Streaming 固有 JS |
| streaming-page.css | `core/src/main/resources/org/apache/spark/ui/static/streaming-page.css` | 静的リソース | ストリーミングページ CSS |
