# 帳票設計書 4-メモリ使用量モニター

## 概要

本ドキュメントは、Jenkins CI/CDサーバーにおけるメモリ使用量モニター機能の帳票設計書である。JVMのメモリ使用量を監視し、時系列グラフとして可視化する診断機能について記述する。

### 本帳票の処理概要

この帳票は、JenkinsサーバーのJVMメモリ使用量を監視し、ヒープメモリと非ヒープメモリの使用状況を時系列グラフとして表示する。Java Management API（JMX）を使用してメモリプールの情報を取得し、MultiStageTimeSeriesを使用して3段階の時間解像度でデータを保持する。

**業務上の目的・背景**：Jenkinsサーバーの安定運用において、メモリ使用量の監視は重要な診断タスクである。OutOfMemoryErrorの予防、メモリリークの検出、GCチューニングの判断材料として、メモリ使用量の推移を可視化する機能が必要とされる。本機能は管理画面の診断ツールとして提供される。

**帳票の利用シーン**：システム管理者がJenkinsのパフォーマンス問題を調査する際、またはメモリ関連の設定変更後の効果を確認する際に利用される。定期的なシステム健全性チェックの一環としても活用される。

**主要な出力内容**：
1. ヒープメモリ使用量の時系列グラフ（使用量: 赤、最大値: 青）
2. 非ヒープメモリ使用量の時系列グラフ（使用量: 赤、最大値: 青）

**帳票の出力タイミング**：管理画面の診断ツールページにアクセスした際に、10秒/1分/1時間の時間スケールでリアルタイムに生成される。

**帳票の利用者**：Jenkinsシステム管理者、インフラ運用担当者

## 帳票種別

統計グラフ（システム診断）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | メモリ使用量モニター | `/jenkins.diagnosis.MemoryUsageMonitorAction/heap/graph` | ページアクセス時に自動表示 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PNG（画像） |
| 用紙サイズ | 500x400 ピクセル（デフォルト） |
| 向き | 横 |
| ファイル名 | 動的生成（ストリームとして出力） |
| 出力方法 | HTTP レスポンスとして直接配信 |
| 文字コード | - |

### PNG固有設定

| 項目 | 内容 |
|-----|------|
| 背景色 | 白（#FFFFFF） |
| グリッド線 | 黒（横方向のみ） |
| フォント | Sans-Serif 10pt |

## 帳票レイアウト

### レイアウト概要

時系列折れ線グラフの形式で、メモリ使用量（赤）と最大メモリ（青）を同一グラフ上に表示する。

```
┌─────────────────────────────────────┐
│            凡例（Legend）            │
├─────────────────────────────────────┤
│  Y軸                                │
│  (KB)     ┌────────────────────┐   │
│           │   最大メモリ（青）    │   │
│           │ ────────────────── │   │
│           │   使用量（赤）       │   │
│           └────────────────────┘   │
│                X軸（時刻）          │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 凡例 | 各データ系列の名称と色 | MultiStageTimeSeries.title | テキスト+色見本 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | 使用量 | GC後のメモリ使用量（KB） | MemoryGroup.used | 折れ線（赤） | - |
| 2 | 最大値 | メモリの最大サイズ（KB） | MemoryGroup.max | 折れ線（青） | - |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | X軸ラベル | 時刻表示 | System.currentTimeMillis() | 時間スケールに応じた形式 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| type | 時間スケール（SEC10/MIN/HOUR） | No（デフォルト: MIN） |
| 権限 | SYSTEM_READ または MANAGE | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 時刻 | 昇順（古い→新しい） |

### 改ページ条件

単一画像のため改ページなし

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

### 参照テーブル一覧

本帳票はデータベースを参照せず、Java Management API（JMX）からメモリ情報を取得する。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| MemoryPoolMXBean | メモリプール情報取得 | JMX API |
| MemoryUsage | 使用量・最大値取得 | getCollectionUsage() |
| MultiStageTimeSeries | 時系列データの保持 | 3段階の時間解像度 |

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

#### MemoryPoolMXBean

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| getCollectionUsage().getUsed() | used | GC後の値 | バイト→KB変換 |
| getCollectionUsage().getMax() | max | GC後の値 | バイト→KB変換 |
| getType() | メモリグループ判定 | HEAP / NON_HEAP | グループ分け |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 使用量（KB） | getUsed() / 1024 | 整数（切り捨て） | バイトからKBへ変換 |
| 最大値（KB） | getMax() / 1024 | 整数（切り捨て） | バイトからKBへ変換 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[HTTPリクエスト /graph] --> B[権限チェック]
    B -->|許可| C[TimeScaleパラメータ解析]
    B -->|拒否| Z[403 Forbidden]
    C --> D[TrendChart生成]
    D --> E[used, maxシリーズ取得]
    E --> F[CategoryDataset作成]
    F --> G[JFreeChartでグラフ生成]
    G --> H[PNG画像をレスポンスに書き込み]
    H --> I[終了]
```

### データ収集フロー

```mermaid
flowchart TD
    A[PeriodicWork起動] --> B[10秒経過]
    B --> C[heap.update]
    C --> D[MemoryPoolMXBean走査]
    D --> E[HEAP タイプのプール合算]
    E --> F[used.update / max.update]
    F --> G[nonHeap.update]
    G --> H[NON_HEAP タイプのプール合算]
    H --> I[used.update / max.update]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 権限エラー | SYSTEM_READ/MANAGE 権限なし | 403 Forbidden | 管理者に連絡 |
| データ不可 | getCollectionUsage() が null | スキップして次のプールへ | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | SEC10: 2160点、MIN: 2880点、HOUR: 1344点 |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | 特に制限なし（メモリ依存） |
| データ収集間隔 | 10秒 |

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

- SYSTEM_READ または MANAGE 権限を持つユーザーのみアクセス可能
- メモリ使用量はシステム診断情報であり、一般ユーザーには非公開
- MemoryUsageMonitorAction は @Restricted(NoExternalUse.class) で外部利用を制限

## 備考

- データはGC後の値（getCollectionUsage()）を使用するため、実際のライブオブジェクトのフットプリントを反映
- ヒープと非ヒープは別々のMemoryGroupとして管理
- MemoryUsageMonitor は @Extension として自動登録され、PeriodicWorkとして10秒ごとに実行

---

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

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

### 推奨読解順序

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

まず、メモリデータを保持するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | MemoryGroup内部クラス（行55-100） |
| 1-2 | MultiStageTimeSeries.java | `core/src/main/java/hudson/model/MultiStageTimeSeries.java` | 時系列データ保持の仕組み |

**読解のコツ**: `MemoryGroup` は `used` と `max` の2つの `MultiStageTimeSeries` を持つ。`update()` メソッド（行75-91）でMemoryPoolMXBeanからデータを収集している点に注目。

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

HTTPリクエストを受け付けるエンドポイントを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | `MemoryGroup.doGraph()` メソッド（行96-99） |
| 2-2 | MemoryUsageMonitorAction.java | `core/src/main/java/jenkins/diagnosis/MemoryUsageMonitorAction.java` | URLルーティング（行43-52） |

**主要処理フロー**:
1. **行96-99**: `doGraph(@QueryParameter String type)` でHTTPリクエストを受け付け
2. **行97**: 権限チェック（SYSTEM_READ または MANAGE）
3. **行98**: `MultiStageTimeSeries.createTrendChart()` でグラフ生成

#### Step 3: データ収集ロジックを理解する

メモリデータがどのように収集されるかを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | コンストラクタ（行105-109） |
| 3-2 | MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | `doRun()` メソッド（行117-120） |

**主要処理フロー**:
- **行105-109**: コンストラクタでMemoryPoolMXBeanリストを取得し、HEAP/NON_HEAPに分類
- **行111-114**: `getRecurrencePeriod()` で10秒間隔を返却
- **行117-120**: `doRun()` で heap と nonHeap を更新

#### Step 4: MemoryGroup.update() の詳細を理解する

メモリ使用量の計算ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | `MemoryGroup.update()` メソッド（行75-91） |

**主要処理フロー**:
- **行76-77**: used と max を0で初期化
- **行78-84**: 各メモリプールの getCollectionUsage() を取得し合算
- **行86-87**: バイトからKBへ変換（/1024）
- **行89-90**: MultiStageTimeSeries.update() を呼び出し

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

```
MemoryUsageMonitorAction.getHeap()
    │
    └─ ExtensionList.lookupSingleton(MemoryUsageMonitor.class).heap
           │
           └─ MemoryGroup.doGraph(type)
                  │
                  ├─ Jenkins.get().checkAnyPermission(SYSTEM_READ, MANAGE)
                  │
                  └─ MultiStageTimeSeries.createTrendChart(timeScale, used, max)
                         │
                         └─ TrendChart.generateResponse()
```

```
PeriodicWork (10秒ごと)
    │
    └─ MemoryUsageMonitor.doRun()
           │
           ├─ heap.update()
           │      └─ MemoryPoolMXBean (HEAP) の合算
           │
           └─ nonHeap.update()
                  └─ MemoryPoolMXBean (NON_HEAP) の合算
```

### データフロー図

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

ManagementFactory
    │
    ▼
MemoryPoolMXBean ────────▶ MemoryUsageMonitor.doRun()
(JMX API)                        │
                                 ▼
                        MemoryGroup.update()
                                 │
                        ┌────────┴────────┐
                        ▼                 ▼
                   used.update()    max.update()
                   (赤色シリーズ)    (青色シリーズ)
                        │                 │
                        └────────┬────────┘
                                 ▼
                    MultiStageTimeSeries に保存
                                 │
                                 ▼
HTTPリクエスト ──────▶ MemoryGroup.doGraph()
   /graph                        │
   ?type=MIN                     ▼
                        TrendChart.generateResponse() ────▶ PNG画像
                                                          (HTTPレスポンス)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MemoryUsageMonitor.java | `core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java` | ソース | メモリ監視のメインクラス、MemoryGroup定義 |
| MemoryUsageMonitorAction.java | `core/src/main/java/jenkins/diagnosis/MemoryUsageMonitorAction.java` | ソース | URLルーティング、RootAction実装 |
| MultiStageTimeSeries.java | `core/src/main/java/hudson/model/MultiStageTimeSeries.java` | ソース | 時系列データ管理、TrendChart生成 |
| PeriodicWork.java | `core/src/main/java/hudson/model/PeriodicWork.java` | ソース | 定期実行の基底クラス |
| ColorPalette.java | `core/src/main/java/hudson/util/ColorPalette.java` | ソース | グラフの色定義（RED, BLUE） |
| Messages.java | `core/src/main/java/hudson/diagnosis/Messages.java` | ソース（生成） | ローカライズメッセージ（USED, TOTAL） |
