# 通知設計書 18-遅延トリガー警告（SlowTriggerAdminMonitor）

## 概要

本ドキュメントは、Jenkins管理画面に表示される「遅延トリガー警告」通知の設計仕様を定義する。この通知は、トリガー（特にSCMポーリングなど）の実行時間が閾値を超えた場合に管理者に警告を表示する。

### 本通知の処理概要

この通知は、Jenkinsの管理画面（/manage）において警告として表示される管理者モニター機能である。トリガーの実行時間を監視し、CRON_THRESHOLD（デフォルト30秒）を超えた場合にその情報を記録し、管理者に通知する。

**業務上の目的・背景**：トリガーの実行時間が長すぎると、他のトリガーの実行が遅延し、システム全体のパフォーマンスに影響を与える。この警告により、管理者は問題のあるトリガーを特定し、最適化や設定変更を検討できる。

**通知の送信タイミング**：Trigger.Cronが毎分実行されるたびに、各トリガーの実行時間が測定される。CRON_THRESHOLD秒を超えた場合にSlowTriggerAdminMonitor.report()が呼び出され、エラー情報が記録される。

**通知の受信者**：Jenkins管理者（ADMINISTER権限を持つユーザー）。管理画面にアクセスできるユーザーのみがこの警告を確認可能。

**通知内容の概要**：実行時間が長すぎたトリガーのリスト（トリガー種別、ジョブ名、実行時間、発生日時）が表示される。

**期待されるアクション**：管理者は「Clear」ボタンでエラーリストをクリアするか、問題のあるジョブの設定を見直す（ポーリング頻度の削減、トリガー設定の最適化など）。

## 通知種別

アプリ内通知（Jenkins管理画面内のAdministrativeMonitor）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（トリガー実行時に記録、画面表示時に判定） |
| 優先度 | 中（パフォーマンス警告） |
| リトライ | 該当なし（画面表示のため） |

### 送信先決定ロジック

AdministrativeMonitorフレームワークにより、Jenkins管理画面（/manage）にアクセスした管理者権限を持つユーザーに対して自動的に表示される。

## 通知テンプレート

### 表示形式

| 項目 | 内容 |
|-----|------|
| 表示エリア | Jenkins管理画面上部の警告セクション |
| スタイル | AdministrativeMonitorのデフォルトスタイル |
| 形式 | HTML（Jellyテンプレート） |

### 本文テンプレート

```html
<div class="jenkins-alert">
    <form method="post" action="${rootURL}/${it.url}/clear">
        <button>Clear</button>
    </form>
    トリガーの実行時間が長すぎます。
    <!-- エラーリスト -->
    <table>
        <tr>
            <td>トリガー種別</td>
            <td>ジョブ名</td>
            <td>実行時間</td>
            <td>発生日時</td>
        </tr>
        <!-- 各エラーについて繰り返し -->
    </table>
</div>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| it.errors | エラー情報マップ | SlowTriggerAdminMonitor.getErrors() | Yes |
| entry.key | トリガークラス名 | Map.Entry.getKey() | Yes |
| entry.value.trigger | トリガーDescriptorクラス | Value.getTrigger() | Yes |
| entry.value.fullJobName | ジョブのフルパス名 | Value.getFullJobName() | Yes |
| entry.value.duration | 実行時間（ミリ秒） | Value.getDuration() | Yes |
| entry.value.timeString | 発生日時文字列 | Value.getTimeString() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| バッチ処理 | トリガー実行完了 | duration > CRON_THRESHOLD * 1000 | 実行時間が閾値超過 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| errors.isEmpty() | エラーが記録されていない場合は非表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Trigger.Cron毎分実行] --> B[checkTriggers呼び出し]
    B --> C[各トリガーについてループ]
    C --> D[trigger.run実行]
    D --> E[実行時間測定]
    E --> F{duration > CRON_THRESHOLD?}
    F -->|はい| G[SlowTriggerAdminMonitor.report]
    F -->|いいえ| H[次のトリガー]
    G --> I[errorsに追加]
    I --> H
    H --> J{次のトリガー?}
    J -->|あり| C
    J -->|なし| K[管理画面アクセス]
    K --> L[AdministrativeMonitor.all取得]
    L --> M[SlowTriggerAdminMonitor.isActivated]
    M --> N{errors非空?}
    N -->|はい| O[警告メッセージ表示]
    N -->|いいえ| P[表示スキップ]
    O --> Q{ユーザーアクション}
    Q -->|Clear| R[errors.clear]
    R --> S[終了]
    P --> S
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| 該当なし | - | メモリ上の状態を参照 |

### メモリ参照

#### SlowTriggerAdminMonitor

| 参照項目 | 用途 | 取得条件 |
|-------------------|------|---------|
| errors | エラー情報マップ | ConcurrentHashMap<String, Value> |

### 更新処理

| 操作 | 対象 | 更新値 | 備考 |
|-----|-----------------|-------|------|
| PUT | errors | Value | report()呼び出し時（MAX_ENTRIES制限あり） |
| CLEAR | errors | 空 | doClear()呼び出し時 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| トリガー実行遅延 | CRON_THRESHOLD超過 | トリガー設定見直し推奨 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 該当なし（画面操作のため） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（画面表示のため） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（管理画面アクセス時に常時判定）

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

- doClear()メソッドは@RequirePOSTアノテーションでCSRF対策
- doClear()はJenkins.ADMINISTER権限チェックを実施
- エラー情報の表示には管理者権限が必要

## 備考

- @Restricted(NoExternalUse.class)で内部API制限されている
- CRON_THRESHOLDのデフォルト値は30秒（Jenkins 2.289以降、以前はミリ秒単位）
- MAX_ENTRIESのデフォルト値は10（システムプロパティで変更可能）
- 同じトリガー種別の複数発生は最新の情報で上書きされる
- エントリ数がMAX_ENTRIESを超えると、最も古いエントリが削除される

---

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

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

### 推奨読解順序

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

まず、遅延情報の構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SlowTriggerAdminMonitor.java | `core/src/main/java/hudson/triggers/SlowTriggerAdminMonitor.java` | Valueクラス（行97-128）の構造を理解 |

**読解のコツ**: Valueクラスは、trigger（トリガー種別）、fullJobName（ジョブ名）、duration（実行時間）、time（発生日時）を保持する。

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

処理の起点となるAdministrativeMonitorクラスを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SlowTriggerAdminMonitor.java | `core/src/main/java/hudson/triggers/SlowTriggerAdminMonitor.java` | クラス全体（行26-129）を確認 |

**主要処理フロー**:
1. **行29**: errorsフィールド（ConcurrentHashMap）でエラー情報を保持
2. **行31-32**: MAX_ENTRIESでエントリ上限を設定
3. **行37-39**: getInstance()でシングルトンアクセス
4. **行45-48**: isActivated()でerrors非空チェック
5. **行62-81**: report()でエラー情報を登録（上限管理付き）
6. **行88-94**: doClear()でエラーリストをクリア

#### Step 3: 呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Trigger.java | `core/src/main/java/hudson/triggers/Trigger.java` | checkTriggers()メソッド（行256-330）でのreport呼び出し箇所を確認 |

**主要処理フロー**:
- **行302-314**: トリガー実行時間を測定し、CRON_THRESHOLD超過時にreport()を呼び出し

#### Step 4: UIテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | description.jelly | `core/src/main/resources/hudson/triggers/SlowTriggerAdminMonitor/description.jelly` | 警告メッセージの構造を確認 |

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

```
Trigger.Cron.doRun()（毎分実行）
    │
    └─ checkTriggers(cal)
           │
           ├─ trigger.run()
           │      └─ 実行時間測定
           │
           └─ 実行時間 > CRON_THRESHOLD?
                  │
                  └─ SlowTriggerAdminMonitor.getInstance().report(...)
                         └─ errors.put(trigger.getName(), new Value(...))

Jenkins管理画面（/manage）
    │
    ├─ AdministrativeMonitor.all()
    │      └─ SlowTriggerAdminMonitor.isActivated()
    │             └─ !errors.isEmpty()
    │
    └─ message.jelly（表示時）
           └─ getErrors()

Clearボタン押下
    │
    └─ doClear()
           ├─ Jenkins.get().checkPermission(Jenkins.ADMINISTER)
           └─ errors.clear()
```

### データフロー図

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

cronトリガー発火 ───▶ trigger.run() ───▶ 実行時間測定
                           │
                    CRON_THRESHOLD比較
                           │
                    report()呼び出し
                           │
管理画面アクセス ───▶ isActivated() ───▶ 警告表示/非表示
                           │
                    errors.isEmpty()

Clearボタン ───▶ doClear() ───▶ errors.clear()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SlowTriggerAdminMonitor.java | `core/src/main/java/hudson/triggers/` | ソース | モニター定義、エラー管理 |
| Trigger.java | `core/src/main/java/hudson/triggers/` | ソース | トリガー実行、遅延検出 |
| description.jelly | `core/src/main/resources/hudson/triggers/SlowTriggerAdminMonitor/` | テンプレート | モニター説明 |
| Messages.properties | `core/src/main/resources/hudson/triggers/` | 設定 | 国際化メッセージ |
