# 画面設計書 133-Hookログ詳細

## 概要

本ドキュメントは、GitLabにおけるプロジェクトWebhookのログ詳細画面の設計を定義するものである。

### 本画面の処理概要

**業務上の目的・背景**：Webhookは外部サービスとの連携において重要な役割を果たす。しかし、Webhookリクエストが失敗した場合や、外部サービスへのデータ送信内容を確認したい場合、詳細なログ情報が必要となる。この画面では、特定のWebhookリクエストの詳細情報（リクエストデータ、レスポンスデータ、ヘッダー、実行時間など）を確認できる。これにより、連携の問題をデバッグしたり、セキュリティ監査のためにデータ送信内容を検証したりすることが可能となる。

**画面へのアクセス方法**：プロジェクト画面から「設定」>「Webhooks」に移動し、対象Webhookの「Recent events」で該当のログエントリをクリックすることでアクセスできる。URLパスは `/:namespace/:project/-/hooks/:hook_id/hook_logs/:id` となる。

**主要な操作・処理内容**：
1. Webhookリクエストの詳細情報（URL、HTTPメソッド、トリガーイベント）を確認
2. リクエストボディ（送信されたJSONデータ）を確認
3. リクエストヘッダーを確認
4. レスポンスステータス、ボディ、ヘッダーを確認
5. 内部エラーメッセージ（発生した場合）を確認
6. 同じリクエストを再送信（Resend Request）

**画面遷移**：
- 遷移元：Webhook編集画面（Recent events一覧）
- 遷移先：Webhook編集画面（再送信後）

**権限による表示制御**：プロジェクトのWebhook管理権限（`admin_web_hook`）を持つユーザーのみがこの画面にアクセスできる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 92 | プロジェクトWebhook | 主機能 | Webhookログの詳細表示・再送信処理 |

## 画面種別

詳細

## URL/ルーティング

| メソッド | パス | コントローラ#アクション |
|---------|------|------------------------|
| GET | `/:namespace_id/:project_id/-/hooks/:hook_id/hook_logs/:id` | `projects/hook_logs#show` |
| POST | `/:namespace_id/:project_id/-/hooks/:hook_id/hook_logs/:id/retry` | `projects/hook_logs#retry` |

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 入出力 | バリデーション | 説明 |
|--------|--------|-----|------|--------|---------------|------|
| Webhook ID | hook_id | Integer | Yes | 入力 | Webhook存在チェック | 親WebhookのID |
| Hook Log ID | id | Integer | Yes | 入力 | HookLog存在チェック | ログエントリのID |

## 表示項目

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| HTTPメソッド | method | String | POSTと表示 |
| URL | url | String | Webhookの送信先URL |
| トリガー | trigger | String | イベント種別（Push, Merge Request等） |
| 実行時間 | execution_duration | Float | リクエスト完了までの秒数 |
| 実行日時 | created_at | DateTime | リクエスト実行日時 |
| レスポンスステータス | response_status | String | HTTPステータスコード |
| レスポンスボディ | response_body | Text | レスポンスの本文 |
| レスポンスヘッダー | response_headers | Hash | レスポンスヘッダー一覧 |
| リクエストボディ | request_data | JSON | 送信されたJSONデータ |
| リクエストヘッダー | request_headers | Hash | リクエストヘッダー一覧 |
| 内部エラー | internal_error_message | String | 内部エラーメッセージ（該当時のみ） |

## イベント仕様

### 1-リクエスト再送信

**トリガー**：「Resend Request」ボタンクリック

**処理フロー**：
1. hook_log.oversize? でデータサイズをチェック
2. サイズ超過時はボタンが無効化され、再送信不可
3. サイズ許容内の場合、hook_log.present.retry_pathへPOSTリクエスト
4. WebHooks::HookLogActions#retry アクションでWebhookを再実行
5. Webhook編集画面にリダイレクト

**データフロー**：
```
Resend Request -> POST retry_path -> WebHooks::HookLogActions#retry -> WebHookService -> 外部サービス
```

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ログ表示 | web_hook_logs | SELECT | ログ詳細情報の取得 |
| リクエスト再送信 | web_hook_logs | INSERT | 新しいログエントリの作成 |

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

#### web_hook_logs（再送信時にINSERT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動採番 | Primary Key |
| INSERT | web_hook_id | 親WebhookのID | FK |
| INSERT | trigger | 元のログと同じ | トリガーイベント |
| INSERT | url | Webhookの送信先URL | - |
| INSERT | request_headers | HTTPヘッダー | JSON形式 |
| INSERT | request_data | 送信データ | JSON形式 |
| INSERT | response_headers | レスポンスヘッダー | JSON形式 |
| INSERT | response_body | レスポンスボディ | テキスト |
| INSERT | response_status | HTTPステータス | 文字列 |
| INSERT | execution_duration | 実行時間（秒） | 小数 |
| INSERT | internal_error_message | 内部エラー | 該当時のみ |
| INSERT | created_at | 現在時刻 | 実行日時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG001 | 情報 | Request data is too large | リクエストデータがサイズ上限を超過 |
| MSG002 | 情報 | Response body is empty | レスポンスボディが空 |
| MSG003 | 情報 | Response headers are empty | レスポンスヘッダーが空 |
| MSG004 | エラー | Internal error occurred while delivering this webhook. Error: {error} | 内部エラー発生時 |

## 例外処理

| 例外条件 | 処理内容 | 遷移先 |
|---------|---------|--------|
| HookLog未検出 | 404 Not Found | Not Found画面 |
| Webhook未検出 | 404 Not Found | Not Found画面 |
| 権限不足 | 404 Not Found（render_404） | Not Found画面 |
| 再送信失敗 | エラーメッセージ表示 | 同一画面 |

## 備考

- レイアウトは `project_settings` を使用
- リクエストデータはJSON形式で整形表示される（Gitlab::Json.pretty_generate）
- サイズが大きすぎるリクエストデータは「Request data is too large」と表示され、再送信ボタンが無効化される
- 時刻表示は `time_ago_with_tooltip` ヘルパーで相対時刻とツールチップを表示
- WebHooks::HookLogActions モジュールを include して共通処理を再利用

---

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

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

### 推奨読解順序

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

HookLogモデルと関連データ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | web_hook_log.rb | `app/models/web_hook_log.rb` | HookLogモデルの定義、関連付け |
| 1-2 | web_hook.rb | `app/models/web_hook.rb` | 親Webhookモデル |

**読解のコツ**: HookLogはWebhookの実行履歴を保存するモデル。`request_data`、`response_body`等のカラムでリクエスト・レスポンスの全情報を保持する。

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

ビューテンプレートとコントローラの処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | show.html.haml | `app/views/projects/hook_logs/show.html.haml` | ログ詳細画面のビュー構造 |
| 2-2 | hook_logs_controller.rb | `app/controllers/projects/hook_logs_controller.rb` | コントローラ定義、権限チェック |
| 2-3 | hook_log_actions.rb | `app/controllers/concerns/web_hooks/hook_log_actions.rb` | 共通アクション（show, retry） |

**主要処理フロー**:
1. **行4**: `authorize_admin_hook!` で権限チェック
2. **行12-14**: `hook` メソッドでWebhook取得
3. HookLogActionsモジュールの `show` アクションでログ取得・表示

#### Step 3: 共有パーシャルを理解する

ログ表示の共有コンポーネントを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _content.html.haml | `app/views/shared/hook_logs/_content.html.haml` | ログ詳細表示パーシャル |
| 3-2 | _status_label.html.haml | `app/views/shared/hook_logs/_status_label.html.haml` | ステータスラベル表示 |

**主要処理フロー**:
1. **行1-5**: URL、HTTPメソッド、トリガー表示
2. **行7-8**: 実行時間、相対時刻表示
3. **行12-17**: 内部エラーメッセージ（該当時）
4. **行19-29**: レスポンス情報
5. **行40-52**: リクエスト情報

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

```
projects/hook_logs/show.html.haml
    │
    ├─ パンくずリスト（Webhook settings）
    │
    ├─ Resend Request ボタン
    │      │
    │      └─ hook_log.present.retry_path -> POST
    │             │
    │             └─ HookLogActions#retry
    │                    │
    │                    └─ WebHookService#execute
    │
    └─ shared/hook_logs/_content.html.haml
           │
           ├─ URL, trigger, 実行時間表示
           │
           ├─ 内部エラーメッセージ（該当時）
           │
           ├─ レスポンス情報
           │      ├─ ステータスラベル
           │      ├─ レスポンスボディ
           │      └─ レスポンスヘッダー
           │
           └─ リクエスト情報
                  ├─ リクエストボディ（JSON整形）
                  └─ リクエストヘッダー
```

### データフロー図

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

hook_id, id ──────▶ HookLogsController#show ──────▶ @hook_log
                           │
                           ▼
                    authorize_admin_hook!
                           │
                           ▼
                    WebHookLog.find
                           │
                           ▼
               shared/hook_logs/_content render
                           │
                           ▼
                    詳細画面表示


[再送信時]

Resend Request ──────▶ HookLogActions#retry ──────▶ WebHookService
                           │                              │
                           ▼                              ▼
                    元のリクエストデータ取得      外部サービスへPOST
                                                          │
                                                          ▼
                                                   新HookLog INSERT
                                                          │
                                                          ▼
                                                   Webhook編集画面へ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| show.html.haml | `app/views/projects/hook_logs/show.html.haml` | テンプレート | Hookログ詳細画面のビュー |
| hook_logs_controller.rb | `app/controllers/projects/hook_logs_controller.rb` | コントローラ | HTTPリクエスト処理 |
| hook_log_actions.rb | `app/controllers/concerns/web_hooks/hook_log_actions.rb` | Concern | 共通アクション定義 |
| _content.html.haml | `app/views/shared/hook_logs/_content.html.haml` | パーシャル | ログ詳細表示コンポーネント |
| _status_label.html.haml | `app/views/shared/hook_logs/_status_label.html.haml` | パーシャル | ステータスラベル |
| web_hook_log.rb | `app/models/web_hook_log.rb` | モデル | HookLogエンティティ |
| web_hook.rb | `app/models/web_hook.rb` | モデル | 親Webhookエンティティ |
| project.rb | `config/routes/project.rb` | ルーティング | URLルーティング定義（行456-460） |
