# 帳票設計書 29-prometheus_sysctl_exporter - Prometheusメトリクスレポート

## 概要

本ドキュメントは、FreeBSDのprometheus_sysctl_exporterコマンドが出力するPrometheusメトリクスレポートの帳票設計書である。本コマンドはカーネルのsysctl値をPrometheus形式のメトリクスとして出力する。

### 本帳票の処理概要

prometheus_sysctl_exporterは、sysctlツリーを走査して全OIDの値を取得し、Prometheusのテキストエクスポート形式（text/plain; version=0.0.4）で出力する。HTTP応答モード(-h)とスタンドアロンモードに対応し、gzip圧縮(-g)も可能。OIDのラベル付け機構により、Prometheusのラベル構文でメトリクスを分類できる。

**業務上の目的・背景**：FreeBSDシステムの監視をPrometheusエコシステムに統合するために、カーネルの各種統計値をPrometheus形式で公開する必要がある。本ツールにより、Prometheusサーバーがscrape可能な形でsysctl値を提供できる。

**帳票の利用シーン**：Prometheus/Grafanaによるシステム監視ダッシュボードの構築、sysctl値のメトリクス収集、inetdと連携したHTTPエクスポーター運用、特定のsysctlツリーの選択的エクスポートなどで使用される。

**主要な出力内容**：
1. HELP行: メトリクスの説明（-d時）
2. メトリクス名: sysctl_で始まる名前（OIDパスをアンダースコアで結合）
3. ラベル: OIDラベル付きの場合は{label="value"}形式
4. 値: 整数値、浮動小数点数、温度（摂氏変換）、timeval（秒変換）

**帳票の出力タイミング**：コマンド実行時に即座に出力。inetd経由の場合はHTTPリクエスト受信時。

**帳票の利用者**：SRE（Site Reliability Engineer）、インフラ監視担当者、システム管理者

## 帳票種別

メトリクスエクスポート（Prometheus text format）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | コマンドライン / inetd | ターミナル / HTTP | `prometheus_sysctl_exporter [-dgh] [-e pattern] [-i pattern] [prefix ...]` |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Prometheus text format (text/plain; version=0.0.4) |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（標準出力 / HTTP応答） |
| 出力方法 | 標準出力 / HTTP応答（-h時） |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

```
┌──────────────────────────────────────────────┐
│ # HELP sysctl_kern_maxproc Maximum processes │
│ sysctl_kern_maxproc 4096                     │
│ # HELP sysctl_kern_openfiles Open files      │
│ sysctl_kern_openfiles 1234                   │
│ sysctl_hw_ncpu 4                             │
│ sysctl_dev_cpu_0_temperature_celsius 45.5    │
│              ...                             │
└──────────────────────────────────────────────┘
```

### ヘッダー部（HTTP応答モード時）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | HTTP/1.1 200 OK | HTTPステータス | 固定値 | テキスト |
| 2 | Content-Type | MIMEタイプ | 固定値 | text/plain; version=0.0.4 |
| 3 | Content-Length | ボディサイズ | 計算値 | 整数 |
| 4 | Content-Encoding | 圧縮方式（-g時） | 固定値 | gzip |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | HELP行 | メトリクス説明（-d時） | sysctl description | "# HELP %s %s\n" | 可変 |
| 2 | メトリクス名 | sysctl_を接頭辞としたOID名 | sysctl name + label | 文字列 | 可変 |
| 3 | 値 | OIDの現在値 | sysctl value | 整数/浮動小数点 | 可変 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| N/A | なし | フッターは出力されない | - | - |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| -d | 説明行（HELP）を出力 | No |
| -g | gzip圧縮出力 | No |
| -h | HTTP応答モード | No |
| -e pattern | 除外パターン（正規表現） | No |
| -i pattern | 包含パターン（正規表現） | No |
| prefix引数 | 特定sysctlツリーのみ出力 | No（全OID出力） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | sysctl OID順 | sysctlツリー順 |

### 改ページ条件

N/A（ストリーム出力）

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| CTL_SYSCTL+CTL_SYSCTL_NEXT | OIDツリー走査 | なし |
| CTL_SYSCTL+CTL_SYSCTL_NAME | OID名取得 | OIDで指定 |
| CTL_SYSCTL+CTL_SYSCTL_OIDFMT | OID書式取得 | OIDで指定 |
| CTL_SYSCTL+CTL_SYSCTL_OIDDESCR | OID説明取得 | OIDで指定 |
| CTL_SYSCTL+6（oidlabel） | OIDラベル取得 | OIDで指定 |
| sysctl(各OID) | OID値取得 | OIDで指定 |

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

#### sysctl OIDメタデータ

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| OID名 | メトリクス名の一部 | CTL_SYSCTL_NAME | ドット区切りパス |
| OIDラベル | メトリクスラベル | CTL_SYSCTL(6) | Prometheusラベル形式 |
| OIDフォーマット | 値の解釈 | CTL_SYSCTL_OIDFMT | CTLTYPE_*, IK等 |
| OID説明 | HELP行 | CTL_SYSCTL_OIDDESCR | -d時のみ使用 |
| OID値 | メトリクス値 | sysctl() | 型に応じた読み取り |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 温度変換 | value / 10^e - 273.15 | 小数6位 | IK形式（デシケルビン→摂氏） |
| timeval変換 | tv_sec + tv_usec/1000000 | 小数6位 | S,timeval形式→秒 |
| loadavg変換 | ldavg[0] / fscale | 小数6位 | S,loadavg形式→実数 |
| メトリクス名変換 | OIDパスの非英数字をアンダースコアに | N/A | Prometheus命名規則準拠 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[getopt - オプション解析]
    B --> C{prefix引数あり?}
    C -->|No| D[oid_get_root - ルートから走査]
    C -->|Yes| E[oid_get_by_name - 指定ツリーから走査]
    D --> F[OID走査ループ]
    E --> F
    F --> G[oid_get_format - フォーマット取得]
    G --> H[oid_get_value - 値取得]
    H --> I[oid_get_name - 名前取得]
    I --> J[oid_get_metric - メトリクス名生成]
    J --> K{フィルタチェック}
    K -->|除外| F
    K -->|包含| L[HELP行出力（-d時）]
    L --> M[メトリクス名 + 値 出力]
    M --> N[oid_get_next - 次のOID]
    N --> F
    F -->|走査完了| O{HTTP mode?}
    O -->|Yes| P[HTTP応答ヘッダー + ボディ出力]
    O -->|No| Q[終了]
    P --> Q
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 不正な正規表現 | -e/-iパターンのコンパイル失敗 | "bad regular expression" | 正しい正規表現を指定 |
| sysctl失敗 | 個別OID値の取得失敗 | スキップ（静かに無視） | 正常動作 |
| メモリ不足 | open_memstream/malloc失敗 | err()出力 | メモリ解放 |
| gzip圧縮失敗 | deflate失敗 | 非圧縮で出力 | フォールバック動作 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数千〜数万OID |
| 目標出力時間 | 数秒以内 |
| 同時出力数上限 | 1（inetd経由の場合） |

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

- sysctl値にはシステムの機密情報が含まれる可能性がある
- HTTP応答モード使用時、アクセス制御はinetdまたは外部のリバースプロキシに依存
- -e/-iオプションで出力するメトリクスを制限可能
- "(LEGACY)"を含む説明のOIDは自動的にスキップされる

## 備考

- Nuxi (https://nuxi.nl/) により開発
- Prometheus text format version 0.0.4に準拠
- zlib使用（gzip圧縮）
- inetdと組み合わせてHTTPエクスポーターとして運用可能
- OIDラベル機能により、sysctlのラベル付きOIDをPrometheusのラベルとしてマッピング
- CTLTYPE_OPAQUEの特殊形式（timeval, loadavg）に対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | prometheus_sysctl_exporter.c | `usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c` | struct oid（行52-55）: sysctlOIDカーソル。id配列とlenで位置を管理 |
| 1-2 | prometheus_sysctl_exporter.c | 同上 | struct oidformat（行107-110）: OIDのkindとformat文字列。CTLTYPE判定に使用 |
| 1-3 | prometheus_sysctl_exporter.c | 同上 | struct oidvalue（行150-157）: OID値。SIGNED/UNSIGNED/FLOAT共用体 |
| 1-4 | prometheus_sysctl_exporter.c | 同上 | struct oidname（行319-323）: OID名とラベル。names/labelsバッファ |
| 1-5 | prometheus_sysctl_exporter.c | 同上 | struct oiddescription（行450-452）: OID説明 |

**読解のコツ**: 5つの構造体がOIDの異なる側面（位置、書式、値、名前、説明）を表す。oid_get_*関数群がsysctl APIラッパー。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | prometheus_sysctl_exporter.c | 同上 | main()関数（行569-706）。オプション解析後、OIDツリーを走査してoid_print()を繰り返し呼び出す |

**主要処理フロー**:
1. **行581**: include/exclude/gzip/http/print_descriptionsフラグ初期化
2. **行582-614**: getopt()による-d, -e, -g, -h, -iオプション解析
3. **行619-625**: HTTP mode時にopen_memstream()でバッファリング
4. **行627**: oidname_init()
5. **行628-636**: 引数なし時 - oid_get_root()からoid_get_next()で全OID走査
6. **行639-657**: 引数あり時 - oid_get_by_name()で指定ツリーのみ走査
7. **行660-703**: HTTP mode時 - gzip圧縮（任意）→ HTTPヘッダー出力 → ボディ出力

#### Step 3: OID処理パイプラインを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | prometheus_sysctl_exporter.c | 同上 | oid_print()（行489-537）: 単一OIDの出力。format取得→value取得→name取得→metric生成→フィルタ→出力 |
| 3-2 | prometheus_sysctl_exporter.c | 同上 | oid_get_value()（行235-314）: OID値の取得。CTLTYPE別のsysctl呼び出しとIK温度変換 |
| 3-3 | prometheus_sysctl_exporter.c | 同上 | oid_get_metric()（行375-433）: メトリクス名とラベルの生成。"sysctl_"プレフィックス付与とラベル構文生成 |

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

```
main() [行569]
    │
    ├─ getopt() - オプション解析 [行582]
    ├─ regcomp() - 正規表現コンパイル [行588, 603]
    ├─ open_memstream() - HTTPバッファ [行621]
    ├─ oidname_init() [行627]
    │
    ├─ oid_get_root() / oid_get_by_name() - 開始位置設定
    │
    └─ OID走査ループ
           │
           └─ oid_print() [行489]
                  ├─ oid_get_format() [行129] - sysctl(OIDFMT)
                  ├─ oid_get_value() [行235] - sysctl(値取得)
                  │      ├─ GET_VALUE マクロ [行241-254]
                  │      ├─ oidformat_is_timeval() → timeval変換
                  │      ├─ oidformat_is_temperature() → 摂氏変換
                  │      └─ S,loadavg → loadavg変換
                  ├─ oid_get_name() [行337] - sysctl(NAME)
                  ├─ oid_get_metric() [行375] - メトリクス名+ラベル生成
                  ├─ regexec() - フィルタチェック [行505, 508]
                  ├─ oid_get_description() [行457] - HELP行
                  └─ fprintf() - メトリクス行出力 [行533-536]
```

### データフロー図

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

CTL_SYSCTL_NEXT         ───▶ oid_get_next()           ───▶ OIDカーソル
CTL_SYSCTL_OIDFMT       ───▶ oid_get_format()         ───▶ kind, format
CTL_SYSCTL_NAME         ───▶ oid_get_name()           ───▶ names, labels
CTL_SYSCTL(6)           ───▶ oid_get_name() (labels)  ───▶ ラベル情報
CTL_SYSCTL_OIDDESCR     ───▶ oid_get_description()    ───▶ HELP文
sysctl(OID)             ───▶ oid_get_value()          ───▶ 値（変換済み）
                               │
                               ▼
                          oid_get_metric()             ───▶ メトリクス名
                               │                           {ラベル}
                               ▼
                          regexec() フィルタ
                               │
                               ▼
                          fprintf()                    ───▶ 標準出力
                                                           / HTTP応答
                                                           (gzip可能)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| prometheus_sysctl_exporter.c | `usr.sbin/prometheus_sysctl_exporter/prometheus_sysctl_exporter.c` | ソース | 全ロジック（707行の単一ファイル） |
| Makefile | `usr.sbin/prometheus_sysctl_exporter/Makefile` | ビルド | ビルド設定（zlib依存） |
