# 画面設計書 23-ThriftServer Session Detail（ThriftServerセッション詳細）

## 概要

本ドキュメントは、Hive ThriftServer（JDBC/ODBC Server）の特定セッションの詳細情報とSQL実行履歴を表示する画面「ThriftServer Session Detail（ThriftServerセッション詳細）」の設計書である。

### 本画面の処理概要

本画面は、ThriftServerに接続された個別セッションの詳細情報と、そのセッションで実行されたSQL文の一覧を表示する画面である。

**業務上の目的・背景**：ThriftServerではJDBC/ODBC経由で複数のクライアントセッションが同時接続し、それぞれ独立してSQL文を実行する。運用管理者やDBエンジニアが特定セッションの利用状況を把握し、問題のあるクエリの特定やセッション単位のパフォーマンス分析を行うために、セッション単位でのSQL実行履歴の詳細確認が必要である。本画面はその要件を満たす。

**画面へのアクセス方法**：ThriftServer Overview画面（No.22）のSession Statisticsテーブルにおいて、セッションIDのリンクをクリックすることで本画面に遷移する。URLパラメータとしてセッションID（id）が必要である。

**主要な操作・処理内容**：
1. サーバー基本情報の表示（起動日時、起動からの経過時間）
2. セッション概要の表示（ユーザー名、IPアドレス、セッション作成日時、総SQL実行数）
3. SQL Statisticsテーブルの表示（セッションに紐づくSQL実行履歴のページネーション付き一覧）
4. テーブルのソート（カラムヘッダクリックによる昇順/降順切り替え）
5. 関連ジョブ詳細画面へのリンク遷移

**画面遷移**：
- 遷移元：ThriftServer Overview画面（No.22）のSession StatisticsテーブルからセッションID選択
- 遷移先：Job Detail画面（No.2）へジョブIDリンクから遷移

**権限による表示制御**：特になし。Spark UIのアクセス制御に依存する。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 特定ThriftServerセッションの詳細情報とSQL実行履歴をテーブル表示する主処理 |
| 29 | Hiveメタストア連携 | 主機能 | セッションのユーザー・IPアドレス・実行SQL一覧を取得して表示 |

## 画面種別

詳細

## URL/ルーティング

- **URL**: `/sqlserver/session/?id={sessionId}`
- **HTTPメソッド**: GET
- **パラメータ**: `id` - セッションID（必須）
- **ページ名（WebUIPage）**: `session`
- **親タブ**: ThriftServerTab（`/sqlserver/`）

## 入出力項目

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

## 表示項目

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

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

### セッション概要セクション

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| User | sessionStat.userName | セッションユーザー名 |
| IP | sessionStat.ip | クライアントIPアドレス |
| Session created at | sessionStat.startTimestamp | セッション作成日時 |
| Total run | sessionStat.totalExecution | 総SQL実行回数 |

### SQL Statisticsテーブル

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

## イベント仕様

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

1. URLパラメータ `id` からセッションIDを取得する
2. `store.synchronized` ブロック内でデータ一貫性を保証する
3. `store.getSession(parameterId)` でセッション情報を取得する
4. セッションが null の場合、`require` によりエラーとなる（"Invalid sessionID[{id}]"）
5. `generateBasicStats()` でサーバー基本情報を生成する
6. セッション概要（ユーザー名、IP、作成日時、総実行数）を生成する
7. `generateSQLStatsTable(request, sessionStat.sessionId)` でSQL統計テーブルを生成する

### 2-テーブルソート

カラムヘッダをクリックすると、該当カラムで昇順/降順ソートされたページに遷移する。ソート状態はURLパラメータ `sqlsessionstat.sort` および `sqlsessionstat.desc` で管理される。

### 3-ページネーション

テーブル下部のページ番号リンクをクリックすると、該当ページに遷移する。ページ番号はURLパラメータ `sqlsessionstat.page` で管理される。

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

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

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

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

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

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

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

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

#### SessionInfo（KVStore）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | sessionId | URLパラメータ `id` と一致 | KVStoreからの読み取り |
| SELECT | userName, ip, startTimestamp, totalExecution | - | セッション概要表示用 |

#### ExecutionInfo（KVStore）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | sessionId | 対象セッションIDと一致するもの | フィルタリング条件 |
| SELECT | execId, statement, userName, startTimestamp, finishTimestamp, closeTimestamp, executePlan, detail, state, jobId, groupId | - | テーブル表示用 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|----------|
| MSG-01 | エラー | "Missing id parameter" | idパラメータがnullまたは空文字の場合 |
| MSG-02 | エラー | "Invalid sessionID[{id}]" | 指定セッションIDに対応するセッションが存在しない場合 |
| MSG-03 | 情報 | "No statistics have been generated yet." | セッションに紐づくSQL実行が0件の場合 |
| MSG-04 | エラー | "Error while rendering job table: {exception}" | テーブルレンダリング中に例外が発生した場合 |

## 例外処理

| 例外 | 発生条件 | 処理 |
|------|----------|------|
| IllegalArgumentException | `id` パラメータが null または空文字の場合 | `require` によりエラーページ表示 |
| IllegalArgumentException | セッションIDに対応するセッションが存在しない場合 | `require` によりエラーページ表示 |
| IllegalArgumentException | テーブルレンダリング時に無効なソートカラムが指定された場合 | エラーメッセージをアラートdivで表示 |
| IndexOutOfBoundsException | テーブルレンダリング時にページ番号が範囲外の場合 | エラーメッセージをアラートdivで表示 |

## 備考

- store.synchronized ブロック内で全データ取得が行われるため、ページ表示中のデータ一貫性が保証される
- Connect版のセッション詳細画面（No.21）とは異なり、ThriftServer版ではIPアドレスが表示される
- SQL StatisticsテーブルはThriftServerPage.scalaで定義された `SqlStatsPagedTable` を再利用しており、subPathは `"sqlserver/session"` となる
- テーブルのヘッダタイトルは「SQL Statistics」（Connect版は「Request Statistics」）
- ページタイトルは「JDBC/ODBC Session」

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 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等のフィールド |

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ThriftServerSessionPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala` | renderメソッド（36-55行目）: リクエストからセッションIDを取得、store.getSessionでセッション情報を取得し、基本統計とSQLテーブルを生成 |

**主要処理フロー**:
1. **37行目**: `request.getParameter("id")` でセッションIDを取得
2. **38行目**: `require(parameterId != null && parameterId.nonEmpty)` でIDの存在チェック
3. **40行目**: `store.synchronized` ブロック開始
4. **41行目**: `store.getSession(parameterId).orNull` でセッション情報取得
5. **42行目**: `require(sessionStat != null)` でセッション存在チェック
6. **44行目**: `generateBasicStats()` で基本情報生成
7. **47-51行目**: セッション概要（User, IP, Session created at, Total run SQL）を生成
8. **52行目**: `generateSQLStatsTable(request, sessionStat.sessionId)` でSQLテーブル生成
9. **54行目**: `UIUtils.headerSparkPage(request, "JDBC/ODBC Session", content, parent)` でHTMLレスポンス生成

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ThriftServerSessionPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala` | generateSQLStatsTableメソッド（71-117行目）: store.getExecutionListでフィルタリングし、SqlStatsPagedTableでテーブル生成。subPathは"sqlserver/session"（87行目） |

#### Step 4: テーブルコンポーネントの理解

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | SqlStatsPagedTable（165-278行目）: テーブルヘッダ・行レンダリング定義。SqlStatsTableDataSource（359-407行目）: データソース。ThriftServerSessionPageで再利用される |

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

```
ThriftServerSessionPage.render(request)
    |
    +-- request.getParameter("id")
    +-- require(parameterId != null)
    |
    +-- store.synchronized {
    |       |
    |       +-- store.getSession(parameterId)
    |       |       +-- KVStore.read(SessionInfo, sessionId)
    |       |
    |       +-- require(sessionStat != null)
    |       |
    |       +-- generateBasicStats()
    |       |
    |       +-- generateSQLStatsTable(request, sessionId)
    |               |
    |               +-- store.getExecutionList
    |               |       +-- KVStore.view(ExecutionInfo)
    |               |
    |               +-- .filter(_.sessionId == sessionID)
    |               |
    |               +-- SqlStatsPagedTable (from ThriftServerPage.scala)
    |                       +-- SqlStatsTableDataSource
    |                       +-- table(sqlTablePage)
    |   }
    |
    +-- UIUtils.headerSparkPage(request, "JDBC/ODBC Session", content, parent)
```

### データフロー図

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

URLパラメータ "id"   ───> ThriftServerSessionPage          ───> HTML Page
                              |                                  |
KVStore                       |                                  +-- 基本統計情報
  +-- SessionInfo    ───> store.getSession()               ───> セッション概要
  |                            |                                (User, IP, 作成日時, 実行数)
  +-- ExecutionInfo  ───> store.getExecutionList()         ───> SQL Statistics
                         .filter(sessionId)                     テーブル
                              |                                  |
                         SqlStatsPagedTable                     +-- ページネーション
                              |                                  +-- ソート
                         SqlStatsTableDataSource                +-- Jobリンク
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ThriftServerSessionPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerSessionPage.scala` | ソース | セッション詳細画面のメインページクラス |
| ThriftServerPage.scala | `sql/hive-thriftserver/src/main/scala/org/apache/spark/sql/hive/thriftserver/ui/ThriftServerPage.scala` | ソース | SqlStatsPagedTable等のテーブルコンポーネント定義（再利用） |
| 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サーバータブの定義 |
| 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` | ソース | ページネーション付きテーブルの基底クラス |
