# 通知設計書 37-スワップ領域モニター（SwapSpaceMonitor）

## 概要

本ドキュメントは、Jenkins のノードモニター機能のうち、エージェントノードのスワップ領域（仮想メモリ）の使用状況を監視する `SwapSpaceMonitor` の設計について記述する。

### 本通知の処理概要

スワップ領域モニター（SwapSpaceMonitor）は、Jenkins のエージェントノードの健全性を監視する `NodeMonitor` の一種であり、各ノードのスワップ領域の使用状況を定期的にチェックし、ノード一覧画面に表示する。

**業務上の目的・背景**：ビルドプロセスは多くのメモリを消費することがあり、物理メモリが不足するとスワップ領域が使用される。スワップ領域の使用量が過大になると、システムのパフォーマンスが著しく低下し、ビルドが遅延または失敗する可能性がある。SwapSpaceMonitor は、スワップ領域の使用状況を可視化し、管理者がメモリリソースの問題を早期に発見できるようにする。

**通知の送信タイミング**：NodeMonitor は定期的（デフォルト60分間隔）に全てのエージェントノードを監視する。各監視サイクルでノードのスワップ領域情報（総容量、空き容量）が取得され、ノード一覧画面に表示される。

**通知の受信者**：管理者およびノード一覧ページを閲覧するユーザーに対して、ノード一覧画面のスワップ領域カラムに情報が表示される。ただし、このモニターはノードをオフラインにする機能を持たない（`canTakeOffline()` が false を返す）。

**通知内容の概要**：スワップ領域の空き容量が表示される。空き容量が 256MB 未満、かつ使用率が 80% を超えている場合は、赤色でハイライトされて警告が表示される。

**期待されるアクション**：管理者は、スワップ領域の使用状況を確認し、必要に応じてメモリの増設、ビルドの並列度の調整、メモリリークの調査などの対処を行う。

## 通知種別

- アプリ内通知（ノード一覧画面）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（定期ポーリング） |
| 優先度 | 中（参考情報、オフライン化なし） |
| リトライ | 有（次の監視サイクルで再試行） |

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

全ての管理者および `Jenkins.ADMINISTER` 権限を持つユーザーが情報を確認できる。一般ユーザーにはスワップ領域カラムが非表示となる。

## 通知テンプレート

### ノード一覧画面の場合

| 項目 | 内容 |
|-----|------|
| 形式 | HTML（カラム表示） |

### 本文テンプレート

正常時：
```
{availableSwapSpace}
```

警告時（空き 256MB 未満かつ使用率 80% 超）：
```
<span class="error">{availableSwapSpace}</span>
```

スワップ情報が取得できない場合：
```
N/A
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| availableSwapSpace | スワップ空き容量 | `MemoryMonitor.monitor().availableSwapSpace` | Yes |
| totalSwapSpace | スワップ総容量 | `MemoryMonitor.monitor().totalSwapSpace` | Yes |
| availablePhysicalMemory | 物理メモリ空き容量 | `MemoryMonitor.monitor().availablePhysicalMemory` | No |
| totalPhysicalMemory | 物理メモリ総容量 | `MemoryMonitor.monitor().totalPhysicalMemory` | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| スケジュール | 定期監視（デフォルト60分間隔） | 常に実行 | AbstractNodeMonitorDescriptor による定期実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| availableSwapSpace == -1 | スワップ情報が取得できない場合は "N/A" を表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[定期監視タイマー発火] --> B[monitor実行]
    B --> C[全ノードに対してcreateCallable実行]
    C --> D[MonitorTaskをノードで実行]
    D --> E[MemoryMonitor.get取得]
    E --> F{取得成功?}
    F -->|Yes| G[MemoryUsage2生成]
    F -->|No| H[エラー処理]
    H --> I{初回エラー?}
    I -->|Yes| J[例外をスロー]
    I -->|No| K[nullを返す]
    G --> L[toHtml変換]
    L --> M{空き256MB未満 かつ 使用率80%超?}
    M -->|Yes| N[エラースパンで表示]
    M -->|No| O[通常表示]
    J --> P[エラーログ]
    K --> Q[N/A表示]
    N --> R[終了]
    O --> R
    P --> R
    Q --> R
```

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

### 参照テーブル一覧

| ストレージ | 用途 | 備考 |
|-----------|------|------|
| nodeMonitors.xml | NodeMonitor設定の永続化 | |

### 参照項目詳細

該当なし（OSのシステム情報を直接取得）

### 更新テーブル一覧

該当なし（モニターデータはメモリ上のみで管理）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| MemoryMonitor取得失敗 | OSがサポートされていない場合 | 初回のみ例外、以降はnullを返す |
| LinkageError | ネイティブライブラリ関連エラー | 初回のみ例外、以降はnullを返す |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無制限（次の監視サイクルで自動再試行） |
| リトライ間隔 | 監視間隔（デフォルト60分） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 監視間隔 | デフォルト60分 |

### 配信時間帯

制限なし（常時監視）

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

- スワップ領域カラムは `Jenkins.ADMINISTER` 権限を持つユーザーにのみ表示される
- メモリ情報はシステムの状態を示すため、アクセス制御に注意

## 備考

- `SwapSpaceMonitor` は `@Symbol("swapSpace")` アノテーションを持ち、JCasC で `swapSpace` として設定可能
- このモニターは `canTakeOffline()` が false を返すため、ノードを自動的にオフラインにしない
- Jenkins 1.233 から存在する
- `org.jvnet.hudson.MemoryMonitor` ライブラリを使用してメモリ情報を取得

---

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

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

### 推奨読解順序

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

まず、メモリ情報を表現するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SwapSpaceMonitor.java | `core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java` 158-198行 | MemoryUsage2クラス（MemoryUsageのラッパー） |

**読解のコツ**: `MemoryUsage2` は `org.jvnet.hudson.MemoryUsage` を継承し、Stapler の `@Exported` アノテーションを追加したクラスである。

#### Step 2: モニター本体を理解する

SwapSpaceMonitor の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SwapSpaceMonitor.java | `core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java` 49-89行 | SwapSpaceMonitorの実装 |
| 2-2 | SwapSpaceMonitor.java | `core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java` 57-72行 | toHtml()メソッド |

**主要処理フロー**:
1. **57-72行**: `toHtml()` で表示用HTMLを生成
2. **59-60行**: `availableSwapSpace == -1` の場合は "N/A" を返す
3. **67行**: 空き容量 256MB 未満かつ使用率 80% 超の場合はエラースパンで囲む

#### Step 3: 監視タスクを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SwapSpaceMonitor.java | `core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java` 124-150行 | MonitorTaskクラス |

**主要処理フロー**:
- **127-129行**: `MemoryMonitor.get()` でメモリモニターを取得
- **130-133行**: 取得失敗時のエラーハンドリング
- **135行**: `MemoryUsage2` を生成して返す

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

```
Timer（定期実行）
    │
    └─ AbstractNodeMonitorDescriptor.triggerUpdate()
           │
           └─ monitor()
                  │
                  └─ createCallable(c)
                         │
                         └─ MonitorTask
                                │
                                ├─ MemoryMonitor.get()
                                │      └─ monitor()
                                │             └─ MemoryUsage
                                │
                                └─ new MemoryUsage2(mem)
                                       │
                                       ▼
                                 toHtml(usage)
                                       │
                                       ├─ [N/A]
                                       ├─ [正常表示]
                                       └─ [エラースパン]
```

### データフロー図

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

OS Memory Info ───▶ MemoryMonitor.get() ───▶ MemoryUsage
                           │
                           ▼
                    MonitorTask.call()
                           │
                           ▼
                    MemoryUsage2
                           │
                           ├─ totalPhysicalMemory
                           ├─ availablePhysicalMemory
                           ├─ totalSwapSpace
                           └─ availableSwapSpace
                                  │
                                  ▼
                           toHtml()
                                  │
                                  ▼
                           [ノード一覧画面]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SwapSpaceMonitor.java | `core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java` | ソース | SwapSpaceMonitorの実装 |
| NodeMonitor.java | `core/src/main/java/hudson/node_monitors/NodeMonitor.java` | ソース | 基底クラス |
| AbstractAsyncNodeMonitorDescriptor.java | `core/src/main/java/hudson/node_monitors/AbstractAsyncNodeMonitorDescriptor.java` | ソース | 非同期監視の基底Descriptor |
| Messages.properties | `core/src/main/resources/hudson/node_monitors/Messages.properties` | リソース | メッセージ定義 |
