# 画面設計書 22-ThriftServer Overview（ThriftServer概要）

## 概要

本ドキュメントは、Hive ThriftServer（JDBC/ODBC Server）のセッション統計およびSQL実行状況を一覧表示する画面「ThriftServer Overview（ThriftServer概要）」の設計書である。

### 本画面の処理概要

本画面は、Hive ThriftServerが提供するJDBC/ODBCサーバーの運用状況を俯瞰するための概要画面である。

**業務上の目的・背景**：Hive ThriftServerはSparkのSQL機能をJDBC/ODBCプロトコル経由で外部クライアントに提供するサービスである。運用管理者は、サーバーの稼働状況、接続中のセッション数、実行中のSQL数を常時監視する必要がある。本画面は、セッション一覧とSQL実行統計を集約表示することで、パフォーマンスのボトルネック検出やスロークエリの特定を支援する。

**画面へのアクセス方法**：Spark Application UIのナビゲーションバーにある「JDBC/ODBC Server」タブ（/sqlserver/）をクリックして遷移する。ThriftServerが有効な場合にのみタブが表示される。本画面はThriftServerTabのデフォルト画面（WebUIPage("")）である。

**主要な操作・処理内容**：
1. サーバー基本情報の表示（起動日時、起動からの経過時間）
2. オンラインセッション数と実行中SQL数のサマリー表示
3. Session Statisticsテーブルの表示（全セッションのページネーション付き一覧）
4. SQL Statisticsテーブルの表示（全SQL実行のページネーション付き一覧）
5. 各テーブルのソート（カラムヘッダクリックによる昇順/降順切り替え）
6. セッション詳細画面へのリンク遷移

**画面遷移**：
- 遷移元：Spark Application UIのナビゲーションバー「JDBC/ODBC Server」タブ
- 遷移先：ThriftServer Session Detail画面（No.23）へセッションIDリンクから遷移、Job Detail画面（No.2）へジョブIDリンクから遷移

**権限による表示制御**：特になし。Spark UIのアクセス制御（spark.ui.filters等）に依存する。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | Hive ThriftServerのセッション統計・SQL実行状況をテーブル表示する主処理 |
| 29 | Hiveメタストア連携 | 主機能 | ThriftServerAppStatusStoreからHive ThriftServerのセッション数・SQL統計を取得して表示 |
| 95 | KVStore | API連携 | HiveThriftServer2AppStatusStore経由でセッション・SQL実行データを非同期取得 |

## 画面種別

一覧

## URL/ルーティング

- **URL**: `/sqlserver/`
- **HTTPメソッド**: GET
- **ページ名（WebUIPage）**: `""` （デフォルトページ）
- **親タブ**: ThriftServerTab（`/sqlserver/`）

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| sessionstat.page | 入力（URLパラメータ） | Int | 任意 | セッションテーブルのページ番号（デフォルト: 1） |
| sessionstat.sort | 入力（URLパラメータ） | String | 任意 | セッションテーブルのソート対象カラム（デフォルト: "Start Time"） |
| sessionstat.desc | 入力（URLパラメータ） | Boolean | 任意 | セッションテーブルの降順ソートフラグ |
| sessionstat.pageSize | 入力（URLパラメータ） | Int | 任意 | セッションテーブルの1ページあたり表示件数 |
| sqlstat.page | 入力（URLパラメータ） | Int | 任意 | SQLテーブルのページ番号（デフォルト: 1） |
| sqlstat.sort | 入力（URLパラメータ） | String | 任意 | SQLテーブルのソート対象カラム（デフォルト: "Start Time"） |
| sqlstat.desc | 入力（URLパラメータ） | Boolean | 任意 | SQLテーブルの降順ソートフラグ |
| sqlstat.pageSize | 入力（URLパラメータ） | Int | 任意 | SQLテーブルの1ページあたり表示件数 |

## 表示項目

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

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| Started at | parent.startTime | サーバー起動日時 |
| Time since start | 現在時刻 - startTime | サーバー起動からの経過時間 |

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

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| オンラインセッション数 | store.getOnlineSessionNum | 現在アクティブなセッション数 |
| 実行中SQL数 | store.getTotalRunning | 現在実行中のSQL文数 |

### Session Statisticsテーブル

| カラム名 | ソート可能 | ツールチップ | 説明 |
|----------|-----------|-------------|------|
| User | はい | なし | セッションユーザー名 |
| IP | はい | なし | クライアントIPアドレス |
| Session ID | はい | なし | セッション識別子（セッション詳細へのリンク付き） |
| Start Time | はい | なし | セッション開始日時 |
| Finish Time | はい | なし | セッション終了日時 |
| Duration | はい | THRIFT_SESSION_DURATION | セッション持続時間 |
| Total Execute | はい | THRIFT_SESSION_TOTAL_EXECUTE | 総SQL実行回数 |

### SQL Statisticsテーブル

| カラム名 | ソート可能 | ツールチップ | 説明 |
|----------|-----------|-------------|------|
| User | はい | なし | SQL実行ユーザー名 |
| JobID | はい | なし | 関連するSparkジョブID（リンク付き） |
| GroupID | はい | なし | SQLグループID |
| Start Time | はい | なし | SQL実行開始日時 |
| Finish Time | はい | THRIFT_SERVER_FINISH_TIME | SQL実行終了日時 |
| Close Time | はい | THRIFT_SERVER_CLOSE_TIME | SQLクローズ日時 |
| Execution Time | はい | THRIFT_SERVER_EXECUTION | 実行時間（開始〜終了） |
| Duration | はい | THRIFT_SERVER_DURATION | 全体所要時間（開始〜クローズ） |
| Statement | はい | なし | 実行SQL文 |
| State | はい | なし | 実行状態 |
| Detail | はい | なし | 詳細情報（エラーメッセージまたは実行プラン） |

## イベント仕様

### 1-ページ読み込み

1. `store.synchronized` ブロック内でデータ一貫性を保証しつつ処理を行う
2. `generateBasicStats()` でサーバー基本情報（起動日時、経過時間）を生成する
3. `store.getOnlineSessionNum` でオンラインセッション数を取得する
4. `store.getTotalRunning` で実行中SQL数を取得する
5. `generateSessionStatsTable(request)` でセッション統計テーブルを生成する
6. `generateSQLStatsTable(request)` でSQL統計テーブルを生成する

### 2-Session Statisticsテーブルのソート/ページネーション

カラムヘッダクリックでソート、ページ番号リンクでページ遷移。URLパラメータ `sessionstat.sort`、`sessionstat.desc`、`sessionstat.page` で管理される。

### 3-SQL Statisticsテーブルのソート/ページネーション

カラムヘッダクリックでソート、ページ番号リンクでページ遷移。URLパラメータ `sqlstat.sort`、`sqlstat.desc`、`sqlstat.page` で管理される。

### 4-セッションIDリンク押下

Session Statisticsテーブルのセッションリンクをクリックすると、`{basePath}/sqlserver/session/?id={sessionId}` に遷移し、セッション詳細画面が表示される。

### 5-ジョブIDリンク押下

SQL StatisticsテーブルのJobIDリンクをクリックすると、`{basePath}/jobs/job/?id={jobId}` に遷移し、ジョブ詳細画面が表示される。

### 6-テーブル折りたたみ

各テーブルのヘッダをクリックすると、`collapseTable` JavaScript関数が呼び出され、テーブルの表示/非表示が切り替わる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ読み込み | SessionInfo（KVStore） | SELECT | セッション一覧の取得 |
| ページ読み込み | ExecutionInfo（KVStore） | SELECT | SQL実行情報一覧の取得 |

### テーブル別更新項目詳細

#### SessionInfo（KVStore）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | sessionId, userName, ip, startTimestamp, finishTimestamp, totalExecution | 全件取得 | getSessionList |
| SELECT | finishTimestamp | == 0 の件数 | getOnlineSessionNum |

#### ExecutionInfo（KVStore）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | execId, statement, sessionId, startTimestamp, userName, finishTimestamp, closeTimestamp, executePlan, detail, state, jobId, groupId | 全件取得 | getExecutionList |
| SELECT | isExecutionActive | アクティブな件数 | getTotalRunning |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|----------|
| MSG-01 | 情報 | "No statistics have been generated yet." | セッションが0件の場合（Session Statistics） |
| MSG-02 | 情報 | "No statistics have been generated yet." | SQL実行が0件の場合（SQL Statistics） |
| MSG-03 | エラー | "Error while rendering job table: {exception}" | テーブルレンダリング中に例外が発生した場合 |

## 例外処理

| 例外 | 発生条件 | 処理 |
|------|----------|------|
| IllegalArgumentException | テーブルレンダリング時に無効なソートカラムが指定された場合 | エラーメッセージをアラートdivで表示 |
| IndexOutOfBoundsException | テーブルレンダリング時にページ番号が範囲外の場合 | エラーメッセージをアラートdivで表示 |

## 備考

- store.synchronized ブロック内で全データ取得が行われるため、ページ表示中のデータ一貫性が保証される
- Session StatisticsとSQL Statisticsの2つのテーブルがそれぞれ独立したページネーション・ソートを持つ
- ThriftServerTabのdisplayOrderは1であり、他の拡張タブより優先して表示される
- SQL StatisticsテーブルのDetail列は、`detail` が空の場合に `executePlan` が代わりに表示される（SqlStatsTableDataSourceの373-377行目）
- HiveThriftServer2のExecutionStateはFAILED, CANCELED, TIMEDOUT, CLOSEDが終了状態として扱われる

---

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

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

### 推奨読解順序

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

まず、セッションとSQL実行のデータモデルを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | HiveThriftServer2AppStatusStore.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/HiveThriftServer2AppStatusStore.scala` | SessionInfo（81-97行目）: sessionId, startTimestamp, ip, userName, finishTimestamp, totalExecution フィールド。ExecutionInfo（99-132行目）: execId, statement, sessionId, startTimestamp, userName, finishTimestamp, closeTimestamp, executePlan, detail, state, jobId, groupId フィールド。isExecutionActive（118-123行目）: FAILED/CANCELED/TIMEDOUT/CLOSED以外がアクティブ |

**読解のコツ**: ThriftServerのSessionInfoにはConnectと異なり `ip` フィールドがある。ExecutionInfoには `groupId` と `executePlan` フィールドがある点がConnect版との差異。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | renderメソッド（39-54行目）: store.synchronizedブロック内で基本統計・セッションテーブル・SQLテーブルを順次生成する流れを確認 |

**主要処理フロー**:
1. **40行目**: `store.synchronized` ブロック開始
2. **41行目**: `generateBasicStats()` でサーバー基本情報生成
3. **44行目**: `store.getOnlineSessionNum` でオンラインセッション数取得
4. **47行目**: `store.getTotalRunning` で実行中SQL数取得
5. **50行目**: `generateSessionStatsTable(request)` でセッション統計テーブル生成
6. **51行目**: `generateSQLStatsTable(request)` でSQL統計テーブル生成
7. **53行目**: `UIUtils.headerSparkPage` でSparkページとして出力

#### Step 3: セッション統計テーブルの生成

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | generateSessionStatsTableメソッド（117-162行目）: SessionStatsPagedTableの生成。セッション一覧テーブルのページネーション・ソート処理 |

#### Step 4: SQL統計テーブルの生成

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | generateSQLStatsTableメソッド（70-114行目）: SqlStatsPagedTableの生成。SQL実行一覧テーブルのページネーション・ソート処理。SqlStatsPagedTable（165-278行目）: テーブルのヘッダ定義（206-218行目）と行レンダリング（226-274行目） |

#### Step 5: テーブルのデータソースとソート処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | SqlStatsTableDataSource（359-407行目）: SQL統計テーブルのデータ変換・ソート。SessionStatsTableDataSource（409-442行目）: セッション統計テーブルのソート。ordering各メソッドでソート可能カラムと順序を確認 |

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

```
ThriftServerPage.render(request)
    |
    +-- store.synchronized {
    |       |
    |       +-- generateBasicStats()
    |       |       +-- formatDate(startTime)
    |       |       +-- formatDurationVerbose(timeSinceStart)
    |       |
    |       +-- store.getOnlineSessionNum
    |       |       +-- KVStore.view(SessionInfo) [finishTimestamp==0をカウント]
    |       |
    |       +-- store.getTotalRunning
    |       |       +-- KVStore.view(ExecutionInfo) [isExecutionActiveをカウント]
    |       |
    |       +-- generateSessionStatsTable(request)
    |       |       +-- store.getSessionList
    |       |       |       +-- KVStore.view(SessionInfo)
    |       |       +-- SessionStatsPagedTable
    |       |               +-- SessionStatsTableDataSource
    |       |               +-- table(sessionTablePage)
    |       |
    |       +-- generateSQLStatsTable(request)
    |               +-- store.getExecutionList
    |               |       +-- KVStore.view(ExecutionInfo)
    |               +-- SqlStatsPagedTable
    |                       +-- SqlStatsTableDataSource
    |                       +-- table(sqlTablePage)
    |   }
    |
    +-- UIUtils.headerSparkPage(request, "JDBC/ODBC Server", content, parent)
```

### データフロー図

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

URLパラメータ            ───> ThriftServerPage              ───> HTML Page
(sort, page, desc)            |                                  |
                              |                                  +-- 基本統計情報
KVStore                       |                                  |
  +-- SessionInfo    ───> store.getSessionList()          ───> Session Statistics
  |                       store.getOnlineSessionNum()          テーブル
  |                            |                                  |
  +-- ExecutionInfo  ───> store.getExecutionList()        ───> SQL Statistics
                          store.getTotalRunning()               テーブル
                              |                                  |
                         PagedTable                              +-- ページネーション
                              |                                  +-- ソート
                         DataSource                              +-- リンク
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | ソース | ThriftServer概要画面のメインページクラス、テーブルコンポーネント定義 |
| HiveThriftServer2AppStatusStore.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/HiveThriftServer2AppStatusStore.scala` | ソース | KVStoreラッパー、SessionInfo/ExecutionInfoデータモデル定義 |
| ThriftServerTab.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerTab.scala` | ソース | JDBC/ODBCサーバータブの定義、ページ登録 |
| ToolTips.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ToolTips.scala` | ソース | テーブルヘッダのツールチップ定義 |
| UIUtils.scala | `core/src/main/scala/org/apache/spark/ui/UIUtils.scala` | ソース | HTML生成ユーティリティ |
| PagedTable.scala | `core/src/main/scala/org/apache/spark/ui/PagedTable.scala` | ソース | ページネーション付きテーブルの基底クラス |
