# バッチ設計書 79-GitlabPerformanceBarStatsWorker

## 概要

本ドキュメントは、パフォーマンスバーの統計情報を処理するバッチ `GitlabPerformanceBarStatsWorker` の設計仕様を記載する。

### 本バッチの処理概要

このバッチは、パフォーマンスバー（開発者向けのデバッグツール）で収集されたリクエスト統計をRedisから取得し、構造化ログとして出力するワーカーである。

**業務上の目的・背景**：GitLabのパフォーマンスバーは、開発者がページの読み込み時間やデータベースクエリ、Gitalyコール、Redisコールなどの詳細情報を確認できる機能である。これらの情報はRedisに一時保存され、このバッチがそれを取得・分析してKibanaなどで分析可能な構造化ログとして出力する。これにより、パフォーマンス問題の発見と解決が容易になり、GitLabの品質向上に貢献する。

**バッチの実行タイミング**：2分ごと（`*/2 * * * *`）にCronジョブとして実行される。

**主要な処理内容**：
1. Redisから保留中のリクエストIDリストを取得
2. リストを取得後、Redisのキーを削除（次回の重複処理を防止）
3. 各リクエストIDに対してStats.processを実行
4. クエリ情報を解析し、構造化ログに出力

**前後の処理との関連**：パフォーマンスバー機能がリクエストIDをRedis Setに追加し、このワーカーがそれを処理する。処理結果はPerformanceBar::Loggerを通じてログ出力される。

**影響範囲**：Redisのパフォーマンスバー統計キー、構造化ログ出力

## バッチ種別

ログ処理 / メトリクス集計

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 2分ごと |
| 実行時刻 | 毎時0, 2, 4, ... 58分 |
| 実行曜日 | 全曜日 |
| 実行日 | 毎日 |
| トリガー | cron（`*/2 * * * *`） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Redis接続 | Redis Cacheへの接続が可能であること |

### 実行可否判定

- 特別な実行可否判定なし
- 保留中のリクエストIDがない場合は処理をスキップ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| _uuid | String | No | nil | 後方互換性のため残存（未使用） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Redis (Cache) | Set | 保留中リクエストIDリスト |
| Redis (Cache) | String | 各リクエストのPeekデータ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| PerformanceBar::Logger | ログ | 構造化パフォーマンス統計 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ログファイル | PerformanceBar専用ログ |
| 形式 | JSON構造化ログ |
| 出力内容 | method_path, filename, query_type, request_id, count, duration_ms |

## 処理フロー

### 処理シーケンス

```
1. Redis接続
   └─ Gitlab::Redis::Cache.with で接続
2. リクエストIDリスト取得
   └─ STATS_KEY (performance_bar_stats:pending_request_ids) からsmembers
   └─ 取得後にキーを削除
3. 各リクエストの処理
   └─ Stats.process(id) を実行
   └─ peek:requests:#{id} からリクエストデータ取得
   └─ active-record, gitaly, redis のクエリを解析
4. ログ出力
   └─ 場所ごとにグループ化されたクエリ統計を出力
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[Redis接続]
    B --> C[リクエストIDリスト取得]
    C --> D[STATSキー削除]
    D --> E{リクエストあり?}
    E -->|No| F[処理終了]
    E -->|Yes| G[Stats.process実行]
    G --> H[リクエストデータ取得]
    H --> I[クエリ解析]
    I --> J[ログ出力]
    J --> K{次のリクエスト?}
    K -->|Yes| G
    K -->|No| F
```

## データベース操作仕様

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| なし | - | - | DBへの直接操作なし（Redisのみ） |

### Redis操作詳細

| 操作 | キー | 操作種別 | 備考 |
|-----|-----|---------|------|
| smembers | performance_bar_stats:pending_request_ids | READ | リクエストIDリスト取得 |
| del | performance_bar_stats:pending_request_ids | DELETE | 処理後に削除 |
| get | peek:requests:#{id} | READ | 各リクエストのデータ取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Redis接続エラー | Redis接続失敗時 | Sidekiqによる自動リトライ |
| - | JSONパースエラー | 不正なデータ形式 | エラーログ出力、処理継続 |
| - | リクエストデータなし | データ期限切れ | 例外を捕捉、エラーログ出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 3回 |
| リトライ間隔 | Sidekiqデフォルト |
| リトライ対象エラー | 標準例外 |

### 障害時対応

- 個々のリクエスト処理失敗はログに記録され、他のリクエスト処理は継続
- Redis接続失敗時は次回の2分後に再試行

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし（Redisのみ） |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 可変（パフォーマンスバー使用頻度に依存） |
| 目標処理時間 | 2分以内 |
| メモリ使用量上限 | リクエスト数に依存 |

## 排他制御

- STATS_KEYを取得後即座に削除することで、次回実行との重複を防止
- 各リクエストは独立して処理

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| INFOログ | 各クエリ統計 | method_path, filename, query_type, request_id, count, duration_ms |
| ERRORログ | 処理失敗時 | "failed to process request id #{id}: #{message}" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ失敗率 | 継続的な失敗 | Sidekiq監視システム |
| 処理遅延 | 2分超過 | 管理者通知 |

## 備考

- このワーカーは `idempotent!` として宣言されている
- feature_category は `observability`
- data_consistency は `always` に設定
- worker_resource_boundary は `cpu` に設定
- sidekiq_options retry: 3
- STATS_KEY の有効期限は30分（STATS_KEY_EXPIRE）
- 解析対象のクエリタイプ: active-record, gitaly, redis
- バックトレースからアプリケーションコードの呼び出し元を特定
- 除外対象のパス: ee/lib/ee/peek, lib/peek, lib/gitlab/database, lib/gitlab/gitaly_client.rb など
