# 帳票設計書 20-Segment Replication Report

## 概要

本ドキュメントは、OpenSearchのCat API「/_cat/segment_replication」エンドポイントが出力するSegment Replication Reportの設計仕様を定義する。本帳票はセグメントレプリケーションの進捗状況をテキストテーブル形式にて出力するものである。

### 本帳票の処理概要

本帳票は、OpenSearchのセグメントレプリケーション機能におけるレプリカシャードのレプリケーション状態を可視化する。セグメントレプリケーションはドキュメントレプリケーションの代替手法であり、プライマリシャードのLuceneセグメントを直接レプリカにコピーすることで、レプリケーションの効率を向上させる。

**業務上の目的・背景**：セグメントレプリケーションはOpenSearch固有の機能であり、レプリカの同期遅延はデータの可用性に直結する。本帳票によりレプリケーションの遅延状況（チェックポイント遅れ、バイト遅れ）やラグ時間を監視し、レプリケーションの健全性を確認できる。

**帳票の利用シーン**：セグメントレプリケーション有効インデックスのレプリケーション遅延監視、レプリケーション失敗の調査、detailedモードでの各ステージの時間分析に利用される。

**主要な出力内容**：
1. シャードID・ターゲットノード情報
2. チェックポイント遅延数・バイト遅延量
3. 現在のラグ時間・最終完了ラグ時間
4. リクエスト拒否数
5. 詳細モード: ステージ情報、ファイル/バイト転送進捗、各ステージ所要時間

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

**帳票の利用者**：OpenSearchクラスタ管理者、SRE、セグメントレプリケーション運用担当者。

## 帳票種別

一覧表（セグメントレプリケーション状態一覧）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | REST API | `GET /_cat/segment_replication` | HTTPリクエスト送信 |
| - | REST API | `GET /_cat/segment_replication/{index}` | HTTPリクエスト送信（インデックス指定） |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | text/plain（テキストテーブル）またはJSON/YAML（format指定時） |
| 用紙サイズ | N/A（API応答） |
| 向き | N/A |
| ファイル名 | N/A（HTTPレスポンスボディ） |
| 出力方法 | HTTPレスポンス |
| 文字コード | UTF-8 |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

テキストテーブル形式。通常モードは8カラム、detailedモードでは25カラムの拡張表示となる。

```
┌──────────────────────────────────────────────────────────────────┐
│  ヘッダー部（shardId, target_node, target_host,                   │
│  checkpoints_behind, bytes_behind, current_lag,                   │
│  last_completed_lag, rejected_requests                            │
│  [detailed: + stage, time, files_fetched, files_percent, ...]）   │
├──────────────────────────────────────────────────────────────────┤
│  明細部（シャード×レプリカノードごとに1行）                          │
│  例: [idx][0]  node2  host2  0  0b  0s  100ms  0                 │
└──────────────────────────────────────────────────────────────────┘
```

### ヘッダー部（通常モード）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | shardId | シャードID | SegmentReplicationPerGroupStats.getShardId() | 文字列（alias: s） |
| 2 | target_node | ターゲットノード名 | SegmentReplicationState.getTargetNode().getName() | 文字列（alias: tnode） |
| 3 | target_host | ターゲットホスト名 | SegmentReplicationState.getTargetNode().getHostName() | 文字列（alias: thost） |
| 4 | checkpoints_behind | チェックポイント遅延数 | SegmentReplicationShardStats.getCheckpointsBehindCount() | 数値（alias: cpb） |
| 5 | bytes_behind | バイト遅延量 | SegmentReplicationShardStats.getBytesBehindCount() | ByteSizeValue（alias: bb） |
| 6 | current_lag | 現在のレプリケーションラグ | SegmentReplicationShardStats.getCurrentReplicationLagMillis() | TimeValue（alias: clag） |
| 7 | last_completed_lag | 最終完了ラグ | SegmentReplicationShardStats.getLastCompletedReplicationTimeMillis() | TimeValue（alias: lcl） |
| 8 | rejected_requests | リクエスト拒否数 | SegmentReplicationPerGroupStats.getRejectedRequestCount() | 数値（alias: rr） |

### ヘッダー部（detailedモード追加カラム）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 9 | stage | レプリケーションステージ | SegmentReplicationState.getStage() | 小文字文字列（alias: st） |
| 10 | time | レプリケーション時間 | SegmentReplicationState.getTimer().time() | TimeValue（alias: t） |
| 11 | files_fetched | フェッチ済みファイル数 | state.getIndex().recoveredFileCount() | 数値（alias: ff） |
| 12 | files_percent | ファイルフェッチ進捗率 | state.getIndex().recoveredFilesPercent() | パーセント（alias: fp） |
| 13 | bytes_fetched | フェッチ済みバイト数 | state.getIndex().recoveredBytes() | 数値（alias: bf） |
| 14 | bytes_percent | バイトフェッチ進捗率 | state.getIndex().recoveredBytesPercent() | パーセント（alias: bp） |
| 15 | start_time | 開始時刻 | state.getTimer().startTime() | ISO 8601形式（alias: start） |
| 16 | stop_time | 停止時刻 | state.getTimer().stopTime() | ISO 8601形式（alias: stop） |
| 17 | files | フェッチ対象ファイル数 | state.getIndex().totalRecoverFiles() | 数値（alias: f） |
| 18 | files_total | 全ファイル数 | state.getIndex().totalFileCount() | 数値（alias: tf） |
| 19 | bytes | フェッチ対象バイト数 | state.getIndex().totalRecoverBytes() | ByteSizeValue（alias: b） |
| 20 | bytes_total | 全バイト数 | state.getIndex().totalBytes() | ByteSizeValue（alias: tb） |
| 21 | replicating_stage_time_taken | レプリケーションステージ時間 | state.getReplicatingStageTime() | TimeValue（alias: rstt） |
| 22 | get_checkpoint_info_stage_time_taken | チェックポイント情報取得時間 | state.getGetCheckpointInfoStageTime() | TimeValue（alias: gcistt） |
| 23 | file_diff_stage_time_taken | ファイル差分ステージ時間 | state.getFileDiffStageTime() | TimeValue（alias: fdstt） |
| 24 | get_files_stage_time_taken | ファイル取得ステージ時間 | state.getGetFileStageTime() | TimeValue（alias: gfstt） |
| 25 | finalize_replication_stage_time_taken | レプリケーション完了ステージ時間 | state.getFinalizeReplicationStageTime() | TimeValue（alias: frstt） |

### 明細部

上記ヘッダー部と同一構成（通常8カラム、detailed時25カラム）。

### フッター部

フッター部は存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| index | 対象インデックス名（カンマ区切り） | No |
| detailed | 詳細モード | No（デフォルト: false） |
| active_only | アクティブなレプリケーションのみ | No（デフォルト: false） |
| shards | 対象シャード番号（カンマ区切り） | No |
| timeout | タイムアウト | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | シャードID | 昇順（CollectionUtil.introSort、行151-155） |
| 2 | レプリカ順 | replicaStatsのSetイテレーション順 |

### 改ページ条件

改ページなし。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| SegmentReplicationStatsResponse（内部API） | レプリケーション統計取得 | SegmentReplicationStatsRequest |

### テーブル別参照項目詳細

#### SegmentReplicationStatsResponse

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| SegmentReplicationPerGroupStats.getShardId() | shardId | - | シャードID |
| SegmentReplicationPerGroupStats.getRejectedRequestCount() | rejected_requests | - | 拒否数 |
| SegmentReplicationShardStats.getCheckpointsBehindCount() | checkpoints_behind | - | CP遅延数 |
| SegmentReplicationShardStats.getBytesBehindCount() | bytes_behind | - | バイト遅延量 |
| SegmentReplicationShardStats.getCurrentReplicationLagMillis() | current_lag | - | 現在ラグ |
| SegmentReplicationShardStats.getLastCompletedReplicationTimeMillis() | last_completed_lag | - | 最終完了ラグ |
| SegmentReplicationState（detailed時） | stage, time, files等 | detailed=true | レプリケーション状態詳細 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| bytes_behind | new ByteSizeValue(getBytesBehindCount()) | - | バイトから人間可読形式 |
| current_lag | new TimeValue(getCurrentReplicationLagMillis()) | - | ミリ秒からTimeValue |
| last_completed_lag | new TimeValue(getLastCompletedReplicationTimeMillis()) | - | ミリ秒からTimeValue |
| files_percent | String.format("%1.1f%%", recoveredFilesPercent()) | 小数第1位 | パーセント表示 |
| bytes_percent | String.format("%1.1f%%", recoveredBytesPercent()) | 小数第1位 | パーセント表示 |
| start_time | DEFAULT_FORMATTER.format(Instant.ofEpochMilli(startTime)) | - | ISO 8601形式 |
| stop_time | DEFAULT_FORMATTER.format(Instant.ofEpochMilli(stopTime)) | - | ISO 8601形式 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[クライアントからGETリクエスト受信] --> B[RestCatSegmentReplicationAction.doCatRequest]
    B --> C[SegmentReplicationStatsRequest生成]
    C --> D[index, detailed, active_only, shards設定]
    D --> E[NodeClient.admin.indices.segmentReplicationStats実行]
    E --> F[SegmentReplicationStatsResponse受信]
    F --> G[buildSegmentReplicationTable]
    G --> H[インデックスごとにループ]
    H --> I[シャードIDで昇順ソート]
    I --> J[グループごと→レプリカごとにループ]
    J --> K{state != null?}
    K -->|Yes| L[テーブル行追加]
    K -->|No| M[スキップ]
    L --> N[RestTable.buildResponse]
    M --> N
    N --> O[HTTPレスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| レプリケーション状態なし | getCurrentReplicationState()がnullの場合 | 行をスキップ（行163-165: state==null時continue） | 正常なスキップ |
| データなし | 対象シャードにレプリケーション情報がない | 空テーブル | 正常動作 |
| 空グループ | replicationPerGroupStatsが空 | スキップ（行146-148: isEmpty時continue） | 正常動作 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | インデックス数 x シャード数 x レプリカ数 |
| 目標出力時間 | 全ノードからの統計収集に依存（通常数秒以内） |
| 同時出力数上限 | REST APIスレッドプールに依存 |

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

セグメントレプリケーション統計情報へのアクセスには、indices:monitor/segment_replication 権限が必要である。

## 備考

- OpenSearch固有の機能（Elasticsearchには存在しない）
- detailedモードでは5つのレプリケーションステージ（replicating, get_checkpoint_info, file_diff, get_files, finalize_replication）の所要時間が表示される
- シャードIDによる昇順ソートはCollectionUtil.introSort使用（行151-155）
- 日時フォーマッタはXContentOpenSearchExtension.DEFAULT_FORMATTERを使用（行184-185）
- IndicesOptions.fromRequestでインデックスオプションを設定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SegmentReplicationPerGroupStats.java | `server/src/main/java/org/opensearch/index/SegmentReplicationPerGroupStats.java` | シャードグループ単位のレプリケーション統計（shardId, replicaStats, rejectedRequestCount） |
| 1-2 | SegmentReplicationShardStats.java | `server/src/main/java/org/opensearch/index/SegmentReplicationShardStats.java` | レプリカシャード単位の統計（checkpointsBehind, bytesBehind, lag等） |
| 1-3 | SegmentReplicationState.java | `server/src/main/java/org/opensearch/indices/replication/SegmentReplicationState.java` | レプリケーション状態（stage, timer, index recovery state等） |

**読解のコツ**: 3階層構造（Response -> PerGroupStats -> ShardStats -> State）を理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestCatSegmentReplicationAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatSegmentReplicationAction.java` | 帳票メインクラス。203行 |

**主要処理フロー**:
1. **行49-53**: routes()で2つのルート定義
2. **行67-85**: doCatRequest()でSegmentReplicationStatsRequestを構築。index, detailed, active_only, shards設定
3. **行88-126**: getTableWithHeader()でdetailedパラメータに応じて8-25カラム定義
4. **行136-202**: buildSegmentReplicationTable()で3重ループ（インデックス→グループ→レプリカ）
5. **行151-155**: CollectionUtil.introSortでシャードID昇順ソート
6. **行162-165**: state==null時のスキップ処理

#### Step 3: レプリケーション状態モデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SegmentReplicationStatsResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/replication/SegmentReplicationStatsResponse.java` | getReplicationStats()でMap<String, List<PerGroupStats>>取得 |

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

```
HTTP GET /_cat/segment_replication[/{index}]
    |
    +-- AbstractCatAction.prepareRequest()
        |
        +-- RestCatSegmentReplicationAction.doCatRequest() [行67]
            |
            +-- SegmentReplicationStatsRequest [行68-75]
            +-- NodeClient.admin().indices().segmentReplicationStats() [行77]
                |
                +-- RestResponseListener.buildResponse() [行81]
                    |
                    +-- buildSegmentReplicationTable() [行136]
                        |
                        +-- response.getReplicationStats().entrySet() loop [行143]
                            |
                            +-- CollectionUtil.introSort(byShardId) [行151]
                            +-- PerGroupStats loop [行157]
                                |
                                +-- ReplicaStats loop [行161]
                                    +-- state null check [行163]
                                    +-- table.addCell() x 8-25 [行168-195]
```

### データフロー図

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

HTTP GET Request        --> RestCatSegmentReplicationAction       --> HTTP Response
  /_cat/segment_replication  |                                       (text/plain
  /{index}                   +-> SegmentReplicationStatsRequest       or JSON)
  ?detailed=true             +-> SegmentReplicationStatsResponse
  ?active_only=true          |   Map<index, List<PerGroupStats>>
  ?shards=0,1                +-> introSort by shardId
                             +-> buildSegmentReplicationTable()
                             |   (3-level nested loop)
                             +-> RestTable.buildResponse()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestCatSegmentReplicationAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestCatSegmentReplicationAction.java` | ソース | 帳票メインクラス（203行） |
| AbstractCatAction.java | `server/src/main/java/org/opensearch/rest/action/cat/AbstractCatAction.java` | ソース | Cat API基底クラス |
| RestTable.java | `server/src/main/java/org/opensearch/rest/action/cat/RestTable.java` | ソース | テーブルレスポンス構築 |
| SegmentReplicationPerGroupStats.java | `server/src/main/java/org/opensearch/index/SegmentReplicationPerGroupStats.java` | ソース | グループ統計 |
| SegmentReplicationShardStats.java | `server/src/main/java/org/opensearch/index/SegmentReplicationShardStats.java` | ソース | シャード統計 |
| SegmentReplicationState.java | `server/src/main/java/org/opensearch/indices/replication/SegmentReplicationState.java` | ソース | レプリケーション状態 |
| SegmentReplicationStatsRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/replication/SegmentReplicationStatsRequest.java` | ソース | リクエスト |
| SegmentReplicationStatsResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/replication/SegmentReplicationStatsResponse.java` | ソース | レスポンス |
| RestCatSegmentReplicationActionTests.java | `server/src/test/java/org/opensearch/rest/action/cat/RestCatSegmentReplicationActionTests.java` | テスト | テストケース |
| ActionModule.java | `server/src/main/java/org/opensearch/action/ActionModule.java` | ソース | アクション登録 |
