# 帳票設計書 16-Snapshots Report

## 概要

本ドキュメントは、OpenSearchのCat API「/_cat/snapshots」エンドポイントが出力するSnapshots Reportの設計仕様を定義する。本帳票は指定リポジトリ内のスナップショット一覧と各スナップショットの状態情報をテキストテーブル形式にて出力するものである。

### 本帳票の処理概要

本帳票は、OpenSearchクラスタの特定スナップショットリポジトリに格納されたスナップショットの詳細情報を一覧化する。スナップショットの状態（SUCCESS, FAILED, IN_PROGRESS等）、開始・終了時刻、所要時間、インデックス数、シャード成功・失敗数等を包括的に表示する。

**業務上の目的・背景**：スナップショットはOpenSearchのバックアップ・リストア機能の中核であり、スナップショットの取得状況を把握することはデータ保護の観点から不可欠である。本帳票により、バックアップの成功・失敗状況やサイズ・所要時間を迅速に確認できる。

**帳票の利用シーン**：バックアップの成功確認、進行中のスナップショットの監視、過去のスナップショット履歴の確認、失敗したスナップショットの原因調査に利用される。

**主要な出力内容**：
1. スナップショット名とステータス
2. 開始・終了時刻（エポック秒とHH:MM:SS形式）
3. 所要時間
4. インデックス数・シャード数（成功/失敗/合計）
5. 失敗理由

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

**帳票の利用者**：OpenSearchクラスタ管理者、バックアップ運用担当者、SRE。

## 帳票種別

一覧表（スナップショット一覧）

## 利用画面

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

## 出力形式

### 基本仕様

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

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

テキストテーブル形式で、1行が1スナップショットに対応する一覧を出力する。

```
┌─────────────────────────────────────────────────────────────────┐
│  ヘッダー部（id, status, start_epoch, start_time, end_epoch,    │
│  end_time, duration, indices, successful_shards, failed_shards, │
│  total_shards, reason*）  *=デフォルト非表示                      │
├─────────────────────────────────────────────────────────────────┤
│  明細部（スナップショットごとに1行）                                │
│  例: snap1  SUCCESS  1234567890  10:30:00  1234567900           │
│      10:30:10  10s  5  10  0  10                                │
└─────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | id | スナップショット名 | SnapshotInfo.snapshotId().getName() | 文字列（alias: snapshot） |
| 2 | status | スナップショット状態 | SnapshotInfo.state() | SnapshotState列挙値（alias: s、右寄せ） |
| 3 | start_epoch | 開始時刻（エポック秒） | SnapshotInfo.startTime() | 秒単位（alias: ste, startEpoch） |
| 4 | start_time | 開始時刻（HH:MM:SS） | SnapshotInfo.startTime() | HH:mm:ss形式（alias: sti, startTime） |
| 5 | end_epoch | 終了時刻（エポック秒） | SnapshotInfo.endTime() | 秒単位（alias: ete, endEpoch） |
| 6 | end_time | 終了時刻（HH:MM:SS） | SnapshotInfo.endTime() | HH:mm:ss形式（alias: eti, endTime） |
| 7 | duration | 所要時間 | 計算値 | TimeValue形式（alias: dur、右寄せ） |
| 8 | indices | インデックス数 | SnapshotInfo.indices().size() | 数値（alias: i、右寄せ） |
| 9 | successful_shards | 成功シャード数 | SnapshotInfo.successfulShards() | 数値（alias: ss、右寄せ） |
| 10 | failed_shards | 失敗シャード数 | SnapshotInfo.failedShards() | 数値（alias: fs、右寄せ） |
| 11 | total_shards | 合計シャード数 | SnapshotInfo.totalShards() | 数値（alias: ts、右寄せ） |
| 12 | reason | 失敗理由（デフォルト非表示） | SnapshotInfo.reason() | 文字列（alias: r） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1-12 | 上記ヘッダー部と同一 | - | - | - | 可変 |

### フッター部

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

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| repository | 対象リポジトリ名 | No（パスパラメータ） |
| ignore_unavailable | 利用不可スナップショットを無視するか | No（デフォルト: false） |
| cluster_manager_timeout | タイムアウト | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | スナップショット順 | GetSnapshotsResponseの返却順 |

### 改ページ条件

改ページなし。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| SnapshotInfo（内部API） | スナップショット情報取得 | GetSnapshotsRequest(repository, ALL_SNAPSHOTS) |

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

#### GetSnapshotsResponse

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| SnapshotInfo.snapshotId().getName() | id | - | スナップショット名 |
| SnapshotInfo.state() | status | - | SUCCESS/FAILED/IN_PROGRESS/PARTIAL/INCOMPATIBLE |
| SnapshotInfo.startTime() | start_epoch, start_time | - | ミリ秒をエポック秒とHH:mm:ss に変換 |
| SnapshotInfo.endTime() | end_epoch, end_time | - | 同上 |
| SnapshotInfo.indices().size() | indices | - | インデックス数 |
| SnapshotInfo.successfulShards() | successful_shards | - | 成功シャード数 |
| SnapshotInfo.failedShards() | failed_shards | - | 失敗シャード数 |
| SnapshotInfo.totalShards() | total_shards | - | 合計シャード数 |
| SnapshotInfo.reason() | reason | - | 失敗理由（null可） |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| start_epoch | TimeUnit.SECONDS.convert(startTime, MILLISECONDS) | 切り捨て | ミリ秒から秒への変換 |
| start_time | FORMATTER.format(Instant.ofEpochMilli(startTime)) | - | HH:mm:ss(UTC)形式 |
| end_epoch | TimeUnit.SECONDS.convert(endTime, MILLISECONDS) | 切り捨て | ミリ秒から秒への変換 |
| end_time | FORMATTER.format(Instant.ofEpochMilli(endTime)) | - | HH:mm:ss(UTC)形式 |
| duration | IN_PROGRESS時: System.currentTimeMillis() - startTime、それ以外: endTime - startTime | - | TimeValue形式で出力 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[クライアントからGETリクエスト受信] --> B[RestSnapshotAction.doCatRequest]
    B --> C[GetSnapshotsRequest生成 - repository, ALL_SNAPSHOTS]
    C --> D[ignore_unavailable設定]
    D --> E[NodeClient.admin.cluster.getSnapshots実行]
    E --> F[GetSnapshotsResponse受信]
    F --> G[buildTable: SnapshotInfoをループ]
    G --> H{スナップショット状態}
    H -->|IN_PROGRESS| I[duration = now - startTime]
    H -->|その他| J[duration = endTime - startTime]
    I --> K[テーブル行追加]
    J --> K
    K --> L[RestTable.buildResponse]
    L --> M[HTTPレスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| リポジトリ未指定 | repository パスパラメータなし | 全リポジトリが対象 | 正常動作 |
| リポジトリ不存在 | 指定リポジトリが存在しない | RepositoryMissingException | フレームワーク側エラー処理 |
| スナップショットなし | リポジトリにスナップショットがない場合 | 空テーブル | 正常動作 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | スナップショット数（数個〜数百個） |
| 目標出力時間 | リポジトリアクセスに依存（リモートストレージの場合は数秒） |
| 同時出力数上限 | REST APIスレッドプールに依存 |

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

スナップショット情報にはインデックス名等が含まれるため、cluster:admin/snapshot/get 権限を持つユーザーのみアクセス可能とすべきである。

## 備考

- duration計算はIN_PROGRESSの場合、現在時刻との差分で算出（行135-139）
- 日時フォーマッタはUTCのHH:mm:ss固定（行121）
- reasonカラムはデフォルト非表示
- `master_timeout` は非推奨

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SnapshotInfo.java | `server/src/main/java/org/opensearch/snapshots/SnapshotInfo.java` | スナップショットの全情報（ID, state, startTime, endTime, indices, shards等） |
| 1-2 | SnapshotState.java | `server/src/main/java/org/opensearch/snapshots/SnapshotState.java` | 状態列挙（IN_PROGRESS, SUCCESS, FAILED, PARTIAL, INCOMPATIBLE） |

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

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

**主要処理フロー**:
1. **行67-69**: routes()で2つのルート定義
2. **行77-96**: doCatRequest()でGetSnapshotsRequestを発行。ALL_SNAPSHOTS指定
3. **行81**: ignore_unavailableパラメータ対応
4. **行104-119**: getTableWithHeader()で12カラム定義
5. **行121**: FORMATTER定義（HH:mm:ss, UTC）
6. **行123-151**: buildTable()でスナップショットループ。duration計算にIN_PROGRESS判定あり

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

```
HTTP GET /_cat/snapshots[/{repository}]
    |
    +-- AbstractCatAction.prepareRequest()
        |
        +-- RestSnapshotAction.doCatRequest() [行77]
            |
            +-- GetSnapshotsRequest(repository, ALL_SNAPSHOTS) [行78-79]
            +-- NodeClient.admin().cluster().getSnapshots() [行88]
                |
                +-- RestResponseListener.buildResponse() [行92]
                    |
                    +-- buildTable() [行123]
                    |   +-- SnapshotInfo loop [行125]
                    |       +-- duration計算 [行134-139]
                    |       +-- table.addCell() x 12 [行128-145]
                    |
                    +-- RestTable.buildResponse() [行93]
```

### データフロー図

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

HTTP GET Request   --> RestSnapshotAction               --> HTTP Response
  /_cat/snapshots       |                                   (text/plain
  /{repository}         +-> GetSnapshotsRequest              or JSON)
                        +-> GetSnapshotsResponse
                        |   (List<SnapshotInfo>)
                        +-> buildTable() with duration calc
                        +-> RestTable.buildResponse()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestSnapshotAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestSnapshotAction.java` | ソース | 帳票メインクラス（152行） |
| 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` | ソース | テーブルレスポンス構築 |
| SnapshotInfo.java | `server/src/main/java/org/opensearch/snapshots/SnapshotInfo.java` | ソース | スナップショット情報 |
| SnapshotState.java | `server/src/main/java/org/opensearch/snapshots/SnapshotState.java` | ソース | スナップショット状態列挙 |
| GetSnapshotsRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/get/GetSnapshotsRequest.java` | ソース | スナップショット取得リクエスト |
| GetSnapshotsResponse.java | `server/src/main/java/org/opensearch/action/admin/cluster/snapshots/get/GetSnapshotsResponse.java` | ソース | スナップショット取得レスポンス |
| ActionModule.java | `server/src/main/java/org/opensearch/action/ActionModule.java` | ソース | アクション登録 |
