# 帳票設計書 12-JMXメトリクスレポート

## 概要

本ドキュメントは、Apache FlinkのJMX（Java Management Extensions）メトリクスレポーター機能に関する設計書である。FlinkのメトリクスをMBeanとしてJMX経由で公開し、標準的なJMXクライアントからアクセス可能にするための仕組みを定義する。

### 本帳票の処理概要

JMXメトリクスレポートは、Apache Flinkで収集された各種メトリクス（Counter、Gauge、Histogram、Meter）をJMX MBeanとしてMBeanServerに登録し、JConsole、VisualVM、JMXクライアントライブラリなどの標準的なJMXツールからアクセス可能にする機能である。

**業務上の目的・背景**：Java/JVM環境における標準的な監視プロトコルであるJMXを活用することで、既存のJava監視インフラストラクチャとの統合を容易にする。多くのエンタープライズ監視ツール（Nagios、Zabbix、Datadog等）はJMXエージェントをサポートしており、追加のカスタム連携なしにFlinkメトリクスを既存の監視システムに組み込むことができる。また、JDK標準のJConsoleやVisualVMを使用した即座のデバッグ・分析も可能となる。

**帳票の利用シーン**：本レポーターは以下のシーンで利用される。(1)JConsoleによるリアルタイムメトリクス確認、(2)VisualVMでのJVMモニタリングとFlinkメトリクス統合、(3)エンタープライズ監視ツールとのJMX連携、(4)カスタムJMXクライアントによるプログラマティックなメトリクス取得、(5)リモートJMX接続によるクラスタ監視。

**主要な出力内容**：
1. JmxCounter - カウンター値をgetCount()メソッドで公開
2. JmxGauge - ゲージ値をgetValue()メソッドで公開
3. JmxHistogram - ヒストグラム統計値（count, mean, stddev, max, min, median, percentiles）を公開
4. JmxMeter - メーター値（rate, count）を公開

**帳票の出力タイミング**：メトリクスがFlinkメトリクスシステムに登録されると即座にMBeanとしてMBeanServerに登録される。JMXはプル型プロトコルのため、クライアントがアクセスした時点で現在値が取得される。

**帳票の利用者**：Flinkクラスタ運用者、Javaアプリケーション運用者、監視システム管理者、開発者（デバッグ用途）。

## 帳票種別

JMX MBean（Management Bean）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | 設定ファイル | flink-conf.yaml | metrics.reporter.jmx.* 設定 |
| N/A | JConsole | service:jmx:rmi:///jndi/rmi://host:port/jmxrmi | JMXクライアント接続 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | N/A（MBean登録） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | JMX MBean公開（プル型） |
| 文字コード | UTF-8 |

### JMX固有設定

| 項目 | 内容 |
|-----|------|
| ドメイン接頭辞 | org.apache.flink. |
| ObjectName形式 | domain:key1=value1,key2=value2 |
| ポート設定 | オプション（JMXService経由） |
| プロトコル | RMI over JMX |

## 帳票レイアウト

### レイアウト概要

JMX ObjectNameとMBean属性でメトリクスが構造化される。

```
org.apache.flink.<scope>.<metricName>:host=xxx,job_id=xxx,...
    └── 属性: count, value, rate, mean, etc.
```

### MBean種別ごとの属性構成

#### JmxCounter (JmxCounterMBean)

| No | 属性名 | 説明 | データ取得元 | 型 |
|----|-------|------|-------------|-----|
| 1 | Count | カウンター値 | counter.getCount() | long |

#### JmxGauge (JmxGaugeMBean)

| No | 属性名 | 説明 | データ取得元 | 型 |
|----|-------|------|-------------|-----|
| 1 | Value | ゲージ値 | gauge.getValue() | Object |

#### JmxHistogram (JmxHistogramMBean)

| No | 属性名 | 説明 | データ取得元 | 型 |
|----|-------|------|-------------|-----|
| 1 | Count | サンプル数 | histogram.getCount() | long |
| 2 | Mean | 平均値 | statistics.getMean() | double |
| 3 | StdDev | 標準偏差 | statistics.getStdDev() | double |
| 4 | Max | 最大値 | statistics.getMax() | long |
| 5 | Min | 最小値 | statistics.getMin() | long |
| 6 | Median | 中央値 | statistics.getQuantile(0.5) | double |
| 7 | 75thPercentile | 75パーセンタイル | statistics.getQuantile(0.75) | double |
| 8 | 95thPercentile | 95パーセンタイル | statistics.getQuantile(0.95) | double |
| 9 | 98thPercentile | 98パーセンタイル | statistics.getQuantile(0.98) | double |
| 10 | 99thPercentile | 99パーセンタイル | statistics.getQuantile(0.99) | double |
| 11 | 999thPercentile | 99.9パーセンタイル | statistics.getQuantile(0.999) | double |

#### JmxMeter (JmxMeterMBean)

| No | 属性名 | 説明 | データ取得元 | 型 |
|----|-------|------|-------------|-----|
| 1 | Rate | レート（件/秒） | meter.getRate() | double |
| 2 | Count | 累積カウント | meter.getCount() | long |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| port | JMXサーバーポート（非推奨、JMXServerOptions.JMX_SERVER_PORT推奨） | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| N/A | ObjectName | 登録順 |

### 改ページ条件

N/A（MBean登録）

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A（メモリ内MBeanServer） | MBean管理 | N/A |

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

#### MBeanServer内部レジストリ

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| registeredMetrics | 登録済みメトリクス | 全登録MBean | Map<Metric, ObjectName> |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ObjectName | JMX_DOMAIN_PREFIX + logicalScope + "." + metricName | N/A | 文字列結合 |
| パーセンタイル | statistics.getQuantile(percentile) | N/A | 統計ライブラリ依存 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Flinkメトリクス登録] --> B[notifyOfAddedMetric呼び出し]
    B --> C[generateJmxDomain実行]
    C --> D[generateJmxTable実行]
    D --> E[ObjectName生成]
    E --> F{メトリクス種別判定}
    F -->|GAUGE| G[JmxGauge作成]
    F -->|COUNTER| H[JmxCounter作成]
    F -->|HISTOGRAM| I[JmxHistogram作成]
    F -->|METER| J[JmxMeter作成]
    G --> K[mBeanServer.registerMBean]
    H --> K
    I --> K
    J --> K
    K --> L[registeredMetrics.put]
    L --> M[終了]
```

### 削除フロー

```mermaid
flowchart TD
    A[Flinkメトリクス削除] --> B[notifyOfRemovedMetric呼び出し]
    B --> C[registeredMetrics.remove]
    C --> D{ObjectName取得成功?}
    D -->|Yes| E[mBeanServer.unregisterMBean]
    D -->|No| F[無視]
    E --> G[終了]
    F --> G
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| MalformedObjectNameException | ObjectName不正 | Implementation error. The domain or table does not conform to JMX rules. | 実装エラー確認 |
| NotCompliantMBeanException | MBean不適合 | Metric did not comply with JMX MBean rules. | 実装エラー確認 |
| InstanceAlreadyExistsException | 重複登録 | A metric with the name {jmxName} was already registered. | 既存メトリクス確認 |
| InstanceNotFoundException | 削除時未存在 | N/A（無視） | 正常動作 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | メトリクス数に依存（数百〜数千MBean） |
| 目標出力時間 | MBean登録は即時（ミリ秒オーダー） |
| 同時出力数上限 | N/A（MBeanServer制限に依存） |

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

- JMXリモートアクセスには認証設定を推奨
- SSL/TLS暗号化の設定が可能
- ファイアウォールによるJMXポートのアクセス制御
- 機密メトリクスへのアクセス制限を検討

## 備考

- Dropwizard metricsライブラリのJmxReporterを参考に実装
- プラットフォームMBeanServer（ManagementFactory.getPlatformMBeanServer()）を使用
- 文字列フィルタリングで不正文字を置換（"は削除、スペースは_、特殊文字は-に置換）

---

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

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

### 推奨読解順序

#### Step 1: インターフェース定義を理解する

JMXで公開されるMBeanのインターフェースを最初に理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | 内部インターフェース定義（行268-424） |

**読解のコツ**: MetricMBean、JmxCounterMBean、JmxGaugeMBean、JmxHistogramMBean、JmxMeterMBeanの各インターフェースと実装クラスの関係を理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | JMXReporterFactory.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporterFactory.java` | ファクトリ実装、ポート設定の受け渡し（行25-34） |
| 2-2 | JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | コンストラクタ、MBeanServer取得（行73-83） |

**主要処理フロー**:
1. **行30-32**: ファクトリでportsConfig取得してJMXReporter生成
2. **行73-83**: コンストラクタでMBeanServer取得、JMXService開始

#### Step 3: メトリクス登録処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | notifyOfAddedMetric実装（行106-159） |

**主要処理フロー**:
- **行107**: generateJmxDomain呼び出しでドメイン名生成
- **行108**: generateJmxTable呼び出しでJMXテーブル生成
- **行112-113**: ObjectName生成
- **行125-144**: メトリクス種別に応じたMBean作成（switch文）
- **行147-148**: MBeanServer.registerMBeanとregisteredMetrics登録

#### Step 4: ユーティリティメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | generateJmxDomain（行195-200）、generateJmxTable（行185-193）、replaceInvalidChars（行215-261） |

**主要処理フロー**:
- **行195-200**: JMX_DOMAIN_PREFIX + logicalScope + "." + metricNameでドメイン生成
- **行185-193**: 変数をHashtableに変換（不正文字置換済み）
- **行215-261**: 文字置換ロジック（"削除、スペース→_、特殊文字→-）

#### Step 5: MBean内部クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | JmxCounter（行277-288）、JmxGauge（行295-307）、JmxHistogram（行335-397）、JmxMeter（行406-423） |

**主要処理フロー**:
- **行277-288**: JmxCounterがCounterをラップしてgetCount()を公開
- **行295-307**: JmxGaugeがGaugeをラップしてgetValue()を公開
- **行335-397**: JmxHistogramが統計情報（11属性）を公開
- **行406-423**: JmxMeterがrate/countを公開

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

```
JMXReporterFactory.createMetricReporter(Properties)
    │
    └─ new JMXReporter(portsConfig)
           │
           ├─ ManagementFactory.getPlatformMBeanServer()
           │
           ├─ JMXService.startInstance(portsConfig) [portsConfig != null時]
           │
           ├─ notifyOfAddedMetric(Metric, String, MetricGroup)
           │      ├─ generateJmxDomain(metricName, group)
           │      │      └─ LogicalScopeProvider.castFrom(group).getLogicalScope()
           │      │             └─ replaceInvalidChars()
           │      │
           │      ├─ generateJmxTable(group.getAllVariables())
           │      │      └─ replaceInvalidChars() [各key/value]
           │      │
           │      ├─ new ObjectName(domain, table)
           │      │
           │      ├─ switch(metric.getMetricType())
           │      │      ├─ GAUGE → new JmxGauge(gauge)
           │      │      ├─ COUNTER → new JmxCounter(counter)
           │      │      ├─ HISTOGRAM → new JmxHistogram(histogram)
           │      │      └─ METER → new JmxMeter(meter)
           │      │
           │      └─ mBeanServer.registerMBean(jmxMetric, jmxName)
           │             └─ registeredMetrics.put(metric, jmxName)
           │
           ├─ notifyOfRemovedMetric(Metric, String, MetricGroup)
           │      ├─ registeredMetrics.remove(metric)
           │      └─ mBeanServer.unregisterMBean(jmxName)
           │
           ├─ getPort()
           │      └─ JMXService.getPort()
           │
           └─ close()
                  └─ [何もしない]
```

### データフロー図

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

Flink Metrics             JMXReporter                  MBeanServer
    │                          │                            │
    │ Counter                 │                            │
    │ Gauge      ──────────▶ │ notifyOfAddedMetric()      │
    │ Histogram               │     │                      │
    │ Meter                   │     ▼                      │
    │                          │ generateJmxDomain()        │
    │                          │     │                      │
    │                          │     ▼                      │
    │                          │ generateJmxTable()         │
    │                          │     │                      │
    │                          │     ▼                      │
    │                          │ new JmxXxx(metric)         │
    │                          │     │                      │
    │                          │     ▼                      │
    │                          │ registerMBean() ─────────▶│ MBean登録
    │                          │                            │
    │                          │                            │
JMXクライアント  ◀────────────────────────────────────────────│
(JConsole等)                   │                            │
    │                          │                            │
    │ getAttribute()           │                            │
    └─────────────────────────────────────────────────────▶│ 値取得
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| JMXReporter.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporter.java` | ソース | メインレポータークラス、MBeanインターフェース定義 |
| JMXReporterFactory.java | `flink-metrics/flink-metrics-jmx/src/main/java/org/apache/flink/metrics/jmx/JMXReporterFactory.java` | ソース | ファクトリクラス |
| JMXService.java | `flink-core/src/main/java/org/apache/flink/management/jmx/JMXService.java` | ソース | JMXサーバー管理サービス |
| JMXServerOptions.java | `flink-core/src/main/java/org/apache/flink/configuration/JMXServerOptions.java` | ソース | JMXサーバー設定オプション |
