# 画面設計書 110-ホットスレッド

## 概要

本ドキュメントは、OpenSearchクラスタ内の各ノードのホットスレッド情報を取得するREST APIエンドポイント `GET /_nodes/hot_threads` の設計を記述する。

### 本画面の処理概要

本APIは、各ノードで最もCPUやリソースを消費しているスレッドのスタックトレース情報を返すエンドポイントである。レスポンスはJSON形式ではなくテキスト形式で返される。

**業務上の目的・背景**：クラスタの性能問題やハング状態を診断する際に、どのスレッドがCPUやI/Oを最も消費しているかを特定するために必要である。高負荷状態の原因調査、デッドロックやスレッドブロッキングの検出、性能ボトルネックの特定において不可欠なデバッグツールである。運用チームがリアルタイムでスレッドの活動状況を確認し、問題のある処理を特定するために使用する。

**画面へのアクセス方法**：HTTPクライアントから `GET /_nodes/hot_threads` または `GET /_nodes/{nodeId}/hot_threads` にGETリクエストを送信する。

**主要な操作・処理内容**：
1. URLパスパラメータからノードIDを取得する
2. クエリパラメータからスレッド数、サンプリング間隔、サンプリングタイプ等を設定する
3. 各ノードで2回のスレッドサンプリングを実行し、差分からホットスレッドを特定する
4. ノードごとのホットスレッドスタックトレースをテキスト形式で返却する

**画面遷移**：関連するAPIとして、ノード情報（No.107）、ノード統計（No.108）がある。ホットスレッドはリアルタイムのスレッド分析に特化している。

**権限による表示制御**：クラスタレベルのモニタリング権限が必要である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 49 | ノード情報・統計 | 主機能 | 各ノードのホットスレッド情報を返す処理 |
| 128 | スレッドプール管理 | 補助機能 | スレッドプールのホットスレッド情報取得処理 |

## 画面種別

情報取得（GET）API

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET | `/_nodes/hot_threads` | 全ノードのホットスレッドを取得 |
| GET | `/_nodes/{nodeId}/hot_threads` | 指定ノードのホットスレッドを取得 |

### 非推奨パス

| メソッド | パス | 説明 |
|---------|------|------|
| GET | `/_cluster/nodes/hot_threads` | 非推奨（7.0.0以降） |
| GET | `/_cluster/nodes/{nodeId}/hot_threads` | 非推奨（7.0.0以降） |
| GET | `/_cluster/nodes/hotthreads` | 非推奨（7.0.0以降） |
| GET | `/_cluster/nodes/{nodeId}/hotthreads` | 非推奨（7.0.0以降） |
| GET | `/_nodes/hotthreads` | 非推奨（7.0.0以降） |
| GET | `/_nodes/{nodeId}/hotthreads` | 非推奨（7.0.0以降） |

## 入出力項目

### パスパラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| nodeId | list(string) | No | ノードIDのカンマ区切りリスト |

### クエリパラメータ

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
|-------------|-----|------|-----------|------|
| interval | time | No | - | 2回目のスレッドサンプリングまでの間隔 |
| snapshots | number | No | 10 | スレッドスタックトレースのサンプル数 |
| threads | number | No | 3 | 情報を提供するスレッド数 |
| ignore_idle_threads | boolean | No | true | アイドルスレッドを除外するか |
| type | enum | No | cpu | サンプリングタイプ（cpu/wait/block） |
| timeout | time | No | - | 操作タイムアウト |

### サンプリングタイプ

| タイプ | 説明 |
|-------|------|
| cpu | CPU時間でソート（デフォルト） |
| wait | 待機時間でソート |
| block | ブロック時間でソート |

## 表示項目

### レスポンス形式

レスポンスはJSON形式ではなく、**テキスト形式**（text/plain）で返される。

### レスポンス例

```
::: [node-1][127.0.0.1:9300]{...}
   99.5% (497.5ms out of 500ms) cpu usage by thread 'opensearch[node-1][search][T#1]'
     2/2 snapshots sharing following 15 elements
       java.base@17/java.lang.Thread.sleep(Native Method)
       org.opensearch.search.SearchService.executeQueryPhase(...)
       ...

::: [node-2][127.0.0.1:9301]{...}
   ...
```

## イベント仕様

### 1-GETリクエスト受信

1. `RestNodesHotThreadsAction.prepareRequest()` がリクエストを受信する
2. `nodeId` パラメータからノードIDを解析する
3. `NodesHotThreadsRequest` を構築する
4. クエリパラメータ（threads, ignore_idle_threads, type, interval, snapshots, timeout）を設定する
5. Transport層経由で各ノードにリクエストを転送する
6. 各ノードでスレッドサンプリングを実行する
7. 結果をテキスト形式に整形して返却する

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| GETリクエスト | 各ノードのJVMスレッド情報 | SELECT | スレッドのスタックトレースとCPU使用率のサンプリング |

## メッセージ仕様

| 種別 | メッセージ | 条件 |
|------|----------|------|
| 成功 | 200 OK + テキストレスポンス | 正常にホットスレッド情報を取得できた場合 |

## 例外処理

| 例外条件 | HTTPステータス | レスポンス内容 |
|---------|---------------|---------------|
| タイムアウト | 408 Request Timeout | タイムアウトエラー |
| ノード到達不能 | 200 OK | 到達可能なノードの結果のみ返却 |

## 備考

- レスポンスはJSON形式ではなくテキスト形式である（`RestResponseListener` を使用）
- 各ノードのホットスレッド情報は `::: ` で始まるセクションに分かれて表示される
- `interval` パラメータで2回のサンプリング間隔を制御できる。短いインターバルは瞬間的なスパイクを、長いインターバルは持続的な高負荷を検出するのに適している
- 非推奨パスが6つ定義されており、後方互換性のために維持されている
- `canTripCircuitBreaker()` が `false` を返すため、サーキットブレーカーをトリップしない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NodesHotThreadsRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java` | リクエスト構造。threads, type, interval, snapshots フィールド |
| 1-2 | NodeHotThreads.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/NodeHotThreads.java` | 個別ノードのホットスレッド結果 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestNodesHotThreadsAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java` | ルート定義（行113-114）、非推奨ルート（行99-110）、`prepareRequest()`（行123-146） |

**主要処理フロー**:
1. **行113-114**: 正規ルートを登録（`/_nodes/hot_threads`, `/_nodes/{nodeId}/hot_threads`）
2. **行99-110**: 非推奨ルート6つを登録
3. **行124**: nodeIdを解析
4. **行125**: `NodesHotThreadsRequest` を構築
5. **行126**: `threads` パラメータを設定
6. **行127**: `ignore_idle_threads` パラメータを設定
7. **行128**: `type` パラメータを設定（cpu/wait/block）
8. **行129**: `interval` パラメータを設定
9. **行130**: `snapshots` パラメータを設定
10. **行136-143**: カスタムレスポンスビルダーでテキスト形式のレスポンスを構築

#### Step 3: レスポンス構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RestNodesHotThreadsAction.java（内部クラス） | 同上 | `buildResponse()` メソッド（行136-143）。`RestResponseListener` を使用してテキスト形式のレスポンスを構築 |

**主要処理フロー**:
- **行137**: `StringBuilder` でレスポンステキストを構築
- **行138**: 各ノードの結果をイテレーション
- **行139**: `::: ` プレフィックスとノード情報を追加
- **行140**: ホットスレッドテキストを3スペースインデントで追加
- **行143**: `BytesRestResponse(RestStatus.OK, sb.toString())` でテキストレスポンスを返却

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

```
RestNodesHotThreadsAction.prepareRequest()
    |
    +-- NodesHotThreadsRequest(nodesIds)
    |       +-- .threads(n)
    |       +-- .ignoreIdleThreads(bool)
    |       +-- .type(cpu|wait|block)
    |       +-- .interval(TimeValue)
    |       +-- .snapshots(n)
    |
    +-- NodeClient.admin().cluster().nodesHotThreads()
            |
            +-- TransportNodesHotThreadsAction
            |       +-- HotThreads sampling [on each node]
            |
            +-- RestResponseListener<NodesHotThreadsResponse>
                    +-- buildResponse()
                        +-- StringBuilder (text format)
                        +-- BytesRestResponse(200, text)
```

### データフロー図

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

GET request            --> RestNodesHotThreadsAction         --> NodesHotThreadsRequest
  nodeId (opt)             .prepareRequest()
  threads (opt)
  type (opt)
  interval (opt)

                       --> TransportNodesHotThreadsAction    --> NodesHotThreadsResponse
                           [各ノードに分散実行]
                           HotThreads.detect() (2回サンプリング)

                       --> RestResponseListener              --> HTTP 200 text/plain
                           buildResponse()                       "::: [node] ..."
                           StringBuilder形式でテキスト構築
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestNodesHotThreadsAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java` | ソース | RESTエンドポイント定義・テキストレスポンス構築 |
| NodesHotThreadsRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java` | ソース | リクエストオブジェクト |
| NodesHotThreadsResponse.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/NodesHotThreadsResponse.java` | ソース | レスポンスオブジェクト |
| NodeHotThreads.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/NodeHotThreads.java` | ソース | 個別ノードのホットスレッド結果 |
| TransportNodesHotThreadsAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java` | ソース | Transport層ロジック |
| HotThreads.java | `server/src/main/java/org/opensearch/monitor/jvm/HotThreads.java` | ソース | ホットスレッド検出エンジン |
| nodes.hot_threads.json | `rest-api-spec/src/main/resources/rest-api-spec/api/nodes.hot_threads.json` | 設定 | REST APIスペック定義 |
