# 画面設計書 20-Spark Connect Server Overview（Connect Server概要）

## 概要

本ドキュメントは、Apache Spark Application UIのConnectタブにあるSpark Connect Server概要画面の設計内容を記述する。本画面はSpark Connect Serverのセッション統計・リクエスト（SQL）実行状況をテーブル形式で表示する。

### 本画面の処理概要

**業務上の目的・背景**：Spark Connect Serverは、クライアントからgRPC経由でSparkセッションを管理しSQL/DataFrame操作を受け付けるサーバーである。本画面は運用者がサーバーの稼働状況を監視するためのダッシュボードとして機能する。オンラインセッション数・実行中リクエスト数をサマリー表示し、セッション統計テーブルではユーザー別のセッション一覧と各セッションの開始時刻・終了時刻・継続時間・実行回数を確認できる。リクエスト統計テーブルでは各SQL/DataFrame実行のユーザー・関連Job ID・SQL Query ID・セッションID・実行時間・ステートメント内容・ステート・エラー詳細などを確認でき、サーバー上で実行されたすべてのリクエストの状況を網羅的に把握できる。Job IDリンクからジョブ詳細画面、SQL Query IDリンクからSQL実行詳細画面、Session IDリンクからセッション詳細画面への遷移が可能であり、問題発生時のドリルダウン調査に活用できる。

**画面へのアクセス方法**：SparkUIのタブバーにある「Connect」タブをクリックすることでアクセスする。Spark Connect Serverが起動しているアプリケーションでのみタブが表示される。

**主要な操作・処理内容**：
1. サーバー基本情報（開始日時、稼働時間）を確認する
2. オンラインセッション数・実行中リクエスト数のサマリーを確認する
3. Session Statisticsテーブルでセッション一覧を確認する（ページング・ソート対応）
4. Request Statisticsテーブルでリクエスト（SQL実行）一覧を確認する（ページング・ソート対応）
5. Session IDリンクからセッション詳細画面（No.21）へ遷移する
6. Job IDリンクからジョブ詳細画面（No.2）へ遷移する
7. SQL Query IDリンクからSQL実行詳細画面（No.15）へ遷移する

**画面遷移**：SparkUIのタブバーから直接アクセスする。本画面からセッション詳細画面（No.21）、ジョブ詳細画面（No.2）、SQL実行詳細画面（No.15）へ遷移可能。

**権限による表示制御**：Spark Connect Serverモジュール未使用の場合、Connectタブ自体が表示されない。ACL設定が有効な場合、閲覧権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | Spark Connect Serverのセッション統計・SQL実行状況をテーブル表示する主処理 |
| 80 | Spark Connectサーバー | 主機能 | SparkConnectServerAppStatusStoreからセッション数・実行中リクエスト数・SQL統計を取得して表示 |
| 95 | KVStore | API連携 | SparkConnectServerAppStatusStore経由でセッション・SQL実行データを非同期取得 |

## 画面種別

一覧（ダッシュボード）

## URL/ルーティング

- パス: `/connect/`
- パラメータ（ページング用）:
  - `sessionstat.page` - セッション統計テーブルのページ番号
  - `sessionstat.sort` - セッション統計テーブルのソートカラム
  - `sessionstat.desc` - セッション統計テーブルの降順フラグ
  - `sessionstat.pageSize` - セッション統計テーブルのページサイズ
  - `sqlstat.page` - リクエスト統計テーブルのページ番号
  - `sqlstat.sort` - リクエスト統計テーブルのソートカラム
  - `sqlstat.desc` - リクエスト統計テーブルの降順フラグ
  - `sqlstat.pageSize` - リクエスト統計テーブルのページサイズ
- 例: `/connect/`

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| sessionstat.page | 入力（URLパラメータ） | Int | 任意 | セッション統計テーブルのページ番号。デフォルト: 1 |
| sessionstat.sort | 入力（URLパラメータ） | String | 任意 | ソートカラム名。デフォルト: "Start Time" |
| sessionstat.desc | 入力（URLパラメータ） | Boolean | 任意 | 降順フラグ |
| sessionstat.pageSize | 入力（URLパラメータ） | Int | 任意 | ページサイズ |
| sqlstat.page | 入力（URLパラメータ） | Int | 任意 | リクエスト統計テーブルのページ番号。デフォルト: 1 |
| sqlstat.sort | 入力（URLパラメータ） | String | 任意 | ソートカラム名。デフォルト: "Start Time" |
| sqlstat.desc | 入力（URLパラメータ） | Boolean | 任意 | 降順フラグ |
| sqlstat.pageSize | 入力（URLパラメータ） | Int | 任意 | ページサイズ |

## 表示項目

### 基本情報セクション

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Started at | Date | サーバー開始日時（アプリケーション開始時刻） |
| Time since start | Duration | サーバー稼働時間（人間可読形式） |

### サマリーセクション

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Online Sessions | Int | 現在オンライン（finishTimestamp == 0）のセッション数 |
| Running Requests | Int | 現在実行中（isExecutionActive）のリクエスト数 |

### Session Statistics テーブル（折りたたみ可能）

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| User | String | セッションユーザー名 |
| Session ID | String（リンク） | セッションID（セッション詳細画面へのリンク） |
| Start Time | Date | セッション開始日時 |
| Finish Time | Date | セッション終了日時（未終了の場合は空欄） |
| Duration | Duration | セッション継続時間（ツールチップ: "Elapsed time since session start, or until closed if the session was closed"） |
| Total Execute | Long | セッション内の総実行回数（ツールチップ: "Number of operations submitted in this session"） |

### Request Statistics テーブル（折りたたみ可能）

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| User | String | 実行ユーザー名 |
| Job ID | Seq[String]（リンク） | 関連Spark Job IDリスト（ジョブ詳細画面へのリンク） |
| SQL Query ID | Seq[String]（リンク） | 関連SQL Execution IDリスト（SQL実行詳細画面へのリンク） |
| Session ID | String（リンク） | セッションID（セッション詳細画面へのリンク） |
| Start Time | Date | 実行開始日時 |
| Finish Time | Date | 実行終了日時（ツールチップ: "Execution finish time, before fetching the results"） |
| Close Time | Date | クローズ日時（ツールチップ: "Operation close time after fetching the results"） |
| Execution Time | Duration | 実行時間（開始〜終了）（ツールチップ: "Difference between start time and finish time"） |
| Duration | Duration | 総所要時間（開始〜クローズ）（ツールチップ: "Difference between start time and close time"） |
| Statement | String | 実行ステートメント内容 |
| State | String | 実行状態（RUNNING / STARTED / COMPILED / READY / CANCELED / FAILED / FINISHED / CLOSED） |
| Operation ID | String | オペレーションID |
| Job Tag | String | ジョブタグ |
| Spark Session Tags | Seq[String] | Sparkセッションタグ（カンマ区切り表示） |
| Detail | String | エラー詳細（エラー発生時に展開表示） |

## イベント仕様

### 1-Session IDリンククリック

Session Statistics テーブルまたは Request Statistics テーブルの Session ID リンクをクリックすると、セッション詳細画面（/connect/session/?id={sessionId}）へ遷移する。

### 2-Job IDリンククリック

Request Statistics テーブルの Job ID リンクをクリックすると、ジョブ詳細画面（/jobs/job/?id={jobId}）へ遷移する。

### 3-SQL Query IDリンククリック

Request Statistics テーブルの SQL Query ID リンクをクリックすると、SQL実行詳細画面（/SQL/execution/?id={sqlExecId}）へ遷移する。

### 4-Session Statisticsセクション折りたたみ

Session Statistics のヘッダをクリックすると、collapseTable関数によりテーブルの表示/非表示を切り替える。

### 5-Request Statisticsセクション折りたたみ

Request Statistics のヘッダをクリックすると、collapseTable関数によりテーブルの表示/非表示を切り替える。

### 6-テーブルカラムソート

Session Statistics テーブルおよび Request Statistics テーブルの各カラムヘッダをクリックすると、該当カラムで昇順/降順ソートされる。

### 7-ページング操作

各テーブルのページ番号リンクまたはGo ボタンでページ移動する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | SessionInfo (KVStore) | SELECT | SparkConnectServerAppStatusStoreからセッション一覧・オンラインセッション数を取得 |
| ページ表示 | ExecutionInfo (KVStore) | SELECT | SparkConnectServerAppStatusStoreから実行一覧・実行中リクエスト数を取得 |

本画面はデータベースへの更新操作を行わない。store.synchronizedブロック内でデータを取得し、表示の一貫性を保証する。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| MSG-001 | 情報 | "No statistics have been generated yet." | セッションデータまたはリクエストデータが0件の場合 |
| MSG-002 | エラー | "Error while rendering job table: {exception}" | テーブルレンダリング中にIllegalArgumentExceptionまたはIndexOutOfBoundsExceptionが発生した場合 |

## 例外処理

- テーブルレンダリングエラー: IllegalArgumentExceptionまたはIndexOutOfBoundsExceptionをキャッチし、エラーメッセージをdivで表示
- 不正なソートカラム: SqlStatsTableDataSource/SessionStatsTableDataSourceのorderingメソッドで不明カラムに対してIllegalArgumentException("Unknown column: {column}")をスロー
- アプリケーション開始時刻取得失敗: NoSuchElementExceptionをキャッチし、現在時刻でフォールバック

## 備考

- store.synchronizedブロックでrender全体を実行し、セッション・リクエストデータの一貫性を保証
- ページタイトルは「Spark Connect」
- タブ名は「Connect」、URLプレフィックスは「connect」
- タブの表示順序（displayOrder）は3
- Session Statistics テーブルはセッション数を括弧内に表示（例: "Session Statistics (5)"）
- Request Statistics テーブルはリクエスト数を括弧内に表示（例: "Request Statistics (10)"）
- Request Statistics テーブルのState列は、isExecutionActiveがtrueの場合は固定値"RUNNING"を表示し、それ以外はExecutionInfoのstateフィールド値を表示
- isExecutionActiveの判定条件: state == STARTED || state == COMPILED || state == READY
- Session Statistics テーブルのDurationは、セッション未終了時はSystem.currentTimeMillis - startTimestamp、終了時はfinishTimestamp - startTimestampで算出
- Request Statistics テーブルのExecution Timeはstart〜finishTimestamp間、Durationはstart〜closeTimestamp間の時間を表示
- テーブルはBootstrapのtable-bordered/table-sm/table-striped/table-head-clickable/table-cell-width-limitedスタイルを使用
- アプリケーション開始時刻はsparkUI.store.applicationInfo().attempts.head.startTimeから取得。取得失敗時は現在時刻にフォールバック

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SessionInfo | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerAppStatusStore.scala` | 行76-91: SessionInfoクラス。sessionId, startTimestamp, userId, finishTimestamp, totalExecution。totalTimeメソッドの計算ロジック |
| 1-2 | ExecutionInfo | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerAppStatusStore.scala` | 行93-126: ExecutionInfoクラス。jobTag, statement, sessionId, startTimestamp, userId, operationId, sparkSessionTags, finishTimestamp, closeTimestamp, detail, state, jobId, sqlExecId。isExecutionActiveの判定条件（行113-117）、totalTimeの計算（行119-125） |
| 1-3 | ExecutionState | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerAppStatusStore.scala` | 行128-131: 列挙型（STARTED, COMPILED, READY, CANCELED, FAILED, FINISHED, CLOSED） |
| 1-4 | SqlStatsTableRow | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行422-429: SQLテーブル行データ。jobTag, jobId, sqlExecId, duration, executionTime, sparkSessionTags, executionInfo |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SparkConnectServerTab.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerTab.scala` | 行27-51: SparkUITab("connect")。displayOrder = 3。attachPage(SparkConnectServerPage)とattachPage(SparkConnectServerSessionPage) |
| 2-2 | SparkConnectServerPage.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行34-35: WebUIPage("")でデフォルトページ。store = parent.store |

**主要処理フロー**:
1. **行42-57**: renderメソッド。store.synchronizedブロック内でgenerateBasicStats + サマリー + generateSessionStatsTable + generateSQLStatsTableを実行
2. **行60-70**: generateBasicStats。開始日時と稼働時間を表示
3. **行43-55**: サマリー。store.getOnlineSessionNum（オンラインセッション数）とstore.getTotalRunning（実行中リクエスト数）を表示
4. **行122-167**: generateSessionStatsTable。SessionStatsPagedTableでページング対応テーブルを生成
5. **行73-119**: generateSQLStatsTable。SqlStatsPagedTableでページング対応テーブルを生成

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SessionStatsPagedTable | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行343-420: PagedTable[SessionInfo]。6列構成（User/Session ID/Start Time/Finish Time/Duration/Total Execute）。ツールチップ付きヘッダ。sessionLink生成（行407-410） |
| 3-2 | SessionStatsTableDataSource | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行493-526: ソートロジック。User/Session ID/Start Time/Finish Time/Duration/Total Executeでソート可能 |
| 3-3 | SqlStatsPagedTable | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行170-341: PagedTable[SqlStatsTableRow]。15列構成（showSessionLink=trueの場合）。jobURL/sqlURL生成（行336-340） |
| 3-4 | SqlStatsTableDataSource | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | 行431-491: ExecutionInfoからSqlStatsTableRowへの変換（行446-461）。15列ソートロジック |

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

```
SparkConnectServerTab [行27] (SparkUITab("connect"))
    |
    +-- store: SparkConnectServerAppStatusStore [行28]
    +-- startTime: Date [行36-41]
    +-- displayOrder = 3 [行50]
    |
    +-- SparkConnectServerPage (WebUIPage("")) [行43]
    |       |
    |       +-- render(request) [行42] (store.synchronized)
    |               |
    |               +-- generateBasicStats() [行60]
    |               |       +-- formatDate(startTime) [行64]
    |               |       +-- formatDurationVerbose(timeSinceStart) [行67]
    |               |
    |               +-- store.getOnlineSessionNum [行47]
    |               +-- store.getTotalRunning [行50]
    |               |
    |               +-- generateSessionStatsTable(request) [行53]
    |               |       |
    |               |       +-- store.getSessionList [行123]
    |               |       +-- SessionStatsPagedTable [行133]
    |               |       |       +-- SessionStatsTableDataSource [行360]
    |               |       |       +-- headers (6列) [行384-392]
    |               |       |       +-- row(session) [行406-419]
    |               |       |               +-- sessionLink生成 [行407-410]
    |               |       +-- collapseTable制御 [行154-155]
    |               |
    |               +-- generateSQLStatsTable(request) [行54]
    |                       |
    |                       +-- store.getExecutionList [行75]
    |                       +-- SqlStatsPagedTable [行86] (showSessionLink=true)
    |                       |       +-- SqlStatsTableDataSource [行188]
    |                       |       |       +-- sqlStatsTableRow変換 [行446-461]
    |                       |       +-- headers (15列) [行213-247]
    |                       |       +-- row(sqlStatsTableRow) [行261-333]
    |                       |               +-- jobURL [行336-337]
    |                       |               +-- sqlURL [行339-340]
    |                       |               +-- sessionLink [行277-280]
    |                       +-- collapseTable制御 [行108-109]
    |
    +-- SparkConnectServerSessionPage (WebUIPage("session")) [行43-44]
```

### データフロー図

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

(パラメータなし) ──────────> SparkConnectServerPage.render()
                                   |                    (store.synchronized)
                                   |
                                   +---> generateBasicStats() ──────> 基本情報HTML
                                   |     (startTime, timeSinceStart)
                                   |
                                   +---> store.getOnlineSessionNum ──> オンラインセッション数
                                   +---> store.getTotalRunning ──────> 実行中リクエスト数
                                   |                                    ──> サマリーHTML
                                   |
                                   +---> generateSessionStatsTable()
                                   |     |
                                   |     +---> store.getSessionList
                                   |     |     ──> Seq[SessionInfo]
                                   |     |
                                   |     +---> SessionStatsPagedTable
                                   |     |     +--- SessionStatsTableDataSource
                                   |     |     |    (ソート・ページング)
                                   |     |     +--- row(session) ──> セッション行HTML
                                   |     |           +-- sessionLink
                                   |     |           +-- formatDate
                                   |     |           +-- formatDurationVerbose
                                   |     |
                                   |     +---> セッション統計テーブルHTML
                                   |
                                   +---> generateSQLStatsTable()
                                   |     |
                                   |     +---> store.getExecutionList
                                   |     |     ──> Seq[ExecutionInfo]
                                   |     |
                                   |     +---> SqlStatsPagedTable
                                   |     |     +--- SqlStatsTableDataSource
                                   |     |     |    (ExecutionInfo → SqlStatsTableRow変換)
                                   |     |     |    (ソート・ページング)
                                   |     |     +--- row(sqlStatsTableRow) ──> リクエスト行HTML
                                   |     |           +-- jobURL (→ /jobs/job/)
                                   |     |           +-- sqlURL (→ /SQL/execution/)
                                   |     |           +-- sessionLink (→ /connect/session/)
                                   |     |
                                   |     +---> リクエスト統計テーブルHTML
                                   |
                                   +---> headerSparkPage() ────────> 完成ページHTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SparkConnectServerPage.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerPage.scala` | ソース | メイン画面ページクラス。SqlStatsPagedTable/SessionStatsPagedTable/DataSourceクラスを含む |
| SparkConnectServerTab.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerTab.scala` | ソース | タブ定義。ページ登録とstore/startTime保持 |
| SparkConnectServerAppStatusStore.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerAppStatusStore.scala` | ソース | データストア。SessionInfo/ExecutionInfoデータモデル定義。KVStore経由でデータ取得 |
| SparkConnectServerSessionPage.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/SparkConnectServerSessionPage.scala` | ソース | セッション詳細画面（遷移先。SqlStatsPagedTableを再利用） |
| ToolTips.scala | `sql/connect/server/src/main/scala/org/apache/spark/sql/connect/ui/ToolTips.scala` | ソース | ツールチップ文字列定義 |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | 共通UIユーティリティ（formatDate, formatDurationVerbose, headerSparkPage, errorMessageCell等） |
| PagedTable.scala | `core/src/main/scala/org/apache/spark/ui/PagedTable.scala` | ソース | ページングテーブル基底クラス |
