# 帳票設計書 8-Recovery Report

## 概要

本ドキュメントは、OpenSearchの `_cat/recovery` APIが出力するRecovery Reportの帳票設計書である。シャードのリカバリ進捗情報をテキストテーブル形式で出力するCat APIエンドポイントの仕様を定義する。

### 本帳票の処理概要

Recovery Reportは、クラスタ内で進行中または完了済みのシャードリカバリの進捗状況を一覧表示する帳票である。リカバリの種類、ステージ、ファイル転送進捗、トランスログ適用進捗などの詳細情報を出力する。

**業務上の目的・背景**：シャードリカバリはノード障害復旧、レプリカ再割り当て、スナップショットリストアなど多くの場面で発生する。リカバリの進捗を可視化することで、復旧の見通し確認、ボトルネック検出、運用判断に活用する。

**帳票の利用シーン**：ノード障害後のリカバリ状況確認、スナップショットリストアの進捗監視、シャード再割り当て後の同期状況確認、クラスタ状態回復の進捗モニタリングに利用される。

**主要な出力内容**：
1. リカバリ対象識別（インデックス名、シャード番号）
2. リカバリ時間情報（開始時刻、終了時刻、経過時間）
3. リカバリタイプとステージ
4. ソース/ターゲットノード情報
5. ファイル転送進捗（ファイル数、バイト数、パーセンテージ）
6. トランスログ適用進捗（オペレーション数、パーセンテージ）

**帳票の出力タイミング**：ユーザーが `GET /_cat/recovery` または `GET /_cat/recovery/{index}` エンドポイントにHTTPリクエストを送信した時点で出力される。

**帳票の利用者**：クラスタ管理者、SRE、運用監視チーム。

## 帳票種別

一覧表（テキストテーブル形式のリカバリ進捗情報一覧）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Cat リカバリ | `GET /_cat/recovery` | HTTP GETリクエスト |
| - | Cat リカバリ（指定） | `GET /_cat/recovery/{index}` | HTTP GETリクエスト |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（text/plain）/ JSON（application/json） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | HTTPレスポンス |
| 文字コード | UTF-8 |

## 帳票レイアウト

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | デフォルト表示 |
|----|-------|------|-------------|---------|------------|
| 1 | index | インデックス名 | index (Map key) | 文字列 | Yes |
| 2 | shard | シャード番号 | RecoveryState.getShardId().id() | 数値 | Yes |
| 3 | start_time | リカバリ開始時刻 | RecoveryState.getTimer().startTime() | ISO8601形式 | No |
| 4 | start_time_millis | 開始時刻（エポックミリ秒） | RecoveryState.getTimer().startTime() | 数値 | No |
| 5 | stop_time | リカバリ終了時刻 | RecoveryState.getTimer().stopTime() | ISO8601形式 | No |
| 6 | stop_time_millis | 終了時刻（エポックミリ秒） | RecoveryState.getTimer().stopTime() | 数値 | No |
| 7 | time | リカバリ所要時間 | RecoveryState.getTimer().time() | TimeValue | Yes |
| 8 | type | リカバリタイプ | RecoverySource.getType() | 小文字文字列 | Yes |
| 9 | stage | リカバリステージ | RecoveryState.getStage() | 小文字文字列 | Yes |
| 10 | source_host | ソースホスト | RecoveryState.getSourceNode().getHostName() | 文字列（なければ"n/a"） | Yes |
| 11 | source_node | ソースノード名 | RecoveryState.getSourceNode().getName() | 文字列（なければ"n/a"） | Yes |
| 12 | target_host | ターゲットホスト | RecoveryState.getTargetNode().getHostName() | 文字列 | Yes |
| 13 | target_node | ターゲットノード名 | RecoveryState.getTargetNode().getName() | 文字列 | Yes |
| 14 | repository | リポジトリ名 | SnapshotRecoverySource.snapshot().getRepository() | 文字列（スナップショット以外は"n/a"） | Yes |
| 15 | snapshot | スナップショット名 | SnapshotRecoverySource.snapshot().getSnapshotId().getName() | 文字列（スナップショット以外は"n/a"） | Yes |
| 16 | files | リカバリ対象ファイル数 | RecoveryState.getIndex().totalRecoverFiles() | 数値 | Yes |
| 17 | files_recovered | リカバリ済みファイル数 | RecoveryState.getIndex().recoveredFileCount() | 数値 | Yes |
| 18 | files_percent | ファイルリカバリ率 | RecoveryState.getIndex().recoveredFilesPercent() | パーセンテージ | Yes |
| 19 | files_total | 総ファイル数 | RecoveryState.getIndex().totalFileCount() | 数値 | Yes |
| 20 | bytes | リカバリ対象バイト数 | RecoveryState.getIndex().totalRecoverBytes() | バイト値 | Yes |
| 21 | bytes_recovered | リカバリ済みバイト数 | RecoveryState.getIndex().recoveredBytes() | バイト値 | Yes |
| 22 | bytes_percent | バイトリカバリ率 | RecoveryState.getIndex().recoveredBytesPercent() | パーセンテージ | Yes |
| 23 | bytes_total | 総バイト数 | RecoveryState.getIndex().totalBytes() | バイト値 | Yes |
| 24 | translog_ops | トランスログ総オペレーション数 | RecoveryState.getTranslog().totalOperations() | 数値 | Yes |
| 25 | translog_ops_recovered | リカバリ済みオペレーション数 | RecoveryState.getTranslog().recoveredOperations() | 数値 | Yes |
| 26 | translog_ops_percent | オペレーションリカバリ率 | RecoveryState.getTranslog().recoveredPercent() | パーセンテージ | Yes |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| index | インデックス名パターン | No |
| detailed | 詳細表示フラグ（デフォルト: false） | No |
| active_only | 進行中のリカバリのみ表示（デフォルト: false） | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | shard | 昇順（CollectionUtil.introSort使用） |

### 改ページ条件

改ページは発生しない。

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

### 参照テーブル一覧

| データソース | 用途 | 取得方法 |
|-----------|------|---------|
| RecoveryResponse | リカバリ状態情報 | RecoveryRequest |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| files_percent | recoveredFilesPercent() | 小数点第1位（%1.1f%%） | RecoveryState.Index 内部で計算 |
| bytes_percent | recoveredBytesPercent() | 小数点第1位（%1.1f%%） | RecoveryState.Index 内部で計算 |
| translog_ops_percent | recoveredPercent() | 小数点第1位（%1.1f%%） | RecoveryState.Translog 内部で計算 |
| time | TimeValue(getTimer().time()) | なし | ミリ秒からTimeValueに変換 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[GET /_cat/recovery リクエスト受信] --> B[doCatRequest]
    B --> C[RecoveryRequest 生成]
    C --> D[client.admin.indices.recoveries 実行]
    D --> E[RecoveryResponse 受信]
    E --> F[buildRecoveryTable でテーブル構築]
    F --> G[インデックスごとにシャードIDでソート]
    G --> H[RestTable.buildResponse]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| リカバリなし | shardRecoveryStates のサイズが0 | 該当インデックスをスキップ | 正常動作 |
| ソースノードなし | SourceNode がnull | "n/a" を表示 | 正常動作（ローカルリカバリ等） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | リカバリ中/完了のシャード数分（通常数個～数百） |
| 目標出力時間 | 数百ミリ秒 |
| 同時出力数上限 | 制限なし |

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

- ノードのホスト名やリポジトリ名などのインフラ情報が含まれる。
- IndicesOptions によるインデックスアクセス制御が適用される。

## 備考

- シャードIDの昇順でソートされる（CollectionUtil.introSort使用）。
- リカバリタイプ（type）にはstore, snapshot, peer, empty_store, existing_store等がある。
- スナップショットリカバリの場合のみ repository と snapshot カラムに有効値が表示される。
- buildRecoveryTable() は public メソッドとして公開されている。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RestCatRecoveryAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatRecoveryAction.java` | 行103-134: getTableWithHeader() で26カラムの定義 |
| 1-2 | RecoveryState.java | `server/src/main/java/org/opensearch/indices/recovery/RecoveryState.java` | リカバリ状態データ構造 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestCatRecoveryAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatRecoveryAction.java` | 行87-100: doCatRequest() で RecoveryRequest を生成・実行 |

**主要処理フロー**:
1. **行88**: RecoveryRequest 生成（インデックス指定）
2. **行89-92**: パラメータ設定（timeout, detailed, active_only, indicesOptions）
3. **行94**: client.admin().indices().recoveries() 実行

#### Step 3: テーブル構築ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RestCatRecoveryAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatRecoveryAction.java` | 行144-212: buildRecoveryTable() でリカバリ状態を行に変換 |

**主要処理フロー**:
- **行156-169**: シャードIDの昇順ソート（CollectionUtil.introSort）
- **行171-207**: RecoveryState から各カラム値を取得
- **行186-195**: スナップショットリカバリの場合のみ repository/snapshot を設定

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

```
AbstractCatAction.prepareRequest()
    |
    +-- RestCatRecoveryAction.doCatRequest() [行87]
           |
           +-- RecoveryRequest 生成 [行88]
           +-- client.admin().indices().recoveries() [行94]
                  |
                  +-- buildRecoveryTable() [行144]
                         |
                         +-- getTableWithHeader() [行103]
                         +-- CollectionUtil.introSort() [行156]
                         +-- RecoveryState 反復 [行171]
           |
           +-- RestTable.buildResponse() [行97]
```

### データフロー図

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

GET /_cat/recovery    --->  RecoveryRequest              --->  テキストテーブル
GET /_cat/recovery/{idx}       |                               (リカバリ数分の行)
                               v
                        RecoveryResponse
                        (Map<String, List<RecoveryState>>)
                               |
                               v
                        シャードIDでソート
                               |
                               v
                        buildRecoveryTable() → Table
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestCatRecoveryAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatRecoveryAction.java` | ソース | Recovery Report メイン処理 |
| RecoveryState.java | `server/src/main/java/org/opensearch/indices/recovery/RecoveryState.java` | ソース | リカバリ状態データ構造 |
| RecoveryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryRequest.java` | ソース | リカバリリクエスト |
| RecoveryResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryResponse.java` | ソース | リカバリレスポンス |
| RecoverySource.java | `server/src/main/java/org/opensearch/cluster/routing/RecoverySource.java` | ソース | リカバリソース種別 |
