PythonでのPrometheus監視とその仕組み


[![Group2261.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4075813/922fec87-ccb3-424c-a79b-1507594fdbad.png)](https://leapcell.io/)



**[Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)**


# Prometheus のデータ型と原理  

## 1. はじめに  
**Prometheus** は、SoundCloud で開発されたオープンソースのシステムモニタリングおよびアラートツールキットです。Prometheus の核心となるのは、監視メトリクスを表すためのデータ型を定義したデータモデルです。これらのデータ型を理解することは、Prometheus を用いてモニタリングデータを収集、保存、照会するための鍵となります。本稿では、Prometheus のデータ型について詳説し、その使用方法を示す Python のコード例を提供し、1分間および5分間の時間経過に伴う変化を分析し、その背後にある変化の原理を説明します。最後に、英語の bash ボックス図を用いた Prometheus のフローチャートを示します。  


## 2. Prometheus のデータ型  

### 2.1 カウンター  
Prometheus の **カウンター (Counter)** は、累積的なメトリクスであり、単一の数値で表され、常に増加のみを許容するものです。典型的には、処理されたリクエスト数、完了したタスク数、発生したエラー数などのイベントをカウントするために使用されます。  

**Python のコード例**  
```python  
from prometheus_client import Counter  

# カウンターメトリクスを作成  
request_counter = Counter('http_requests_total', 'Total number of HTTP requests')  

# 複数の HTTP リクエストをシミュレート  
for _ in range(10):  
    request_counter.inc()  

print(request_counter._value.get())  
```  

**説明**:  
- `prometheus_client` ライブラリから `Counter` クラスをインポートします。  
- `http_requests_total` という名前のカウンターを、説明文字列を付けて作成します。  
- カウンターを10回インクリメントすることで、10件の HTTP リクエストをシミュレートします。  
- 現在のカウンターの値を出力します。  

**時間経過に伴うデータの変化**  
- **1分間**:  
  たとえば、Web サーバーが1分間に10件のリクエストを受け取るとします。カウンターの初期値が50であれば、1分後には60に増加します。  
- **5分間**:  
  1分間10件の一定のレートであれば、5分間で50件増加し、初期値50から100に達します。  

**変化の原理**:  
カウンターは、追跡対象のイベントが発生するたびに1ずつインクリメントされます。Prometheus は、時間の経過に伴う累積値を保存し、値が自然に減少することはありません。このため、長期的なイベントの傾向を追跡するのに適しています。  


### 2.2 ゲージ  
**ゲージ (Gauge)** は、任意に増減することができる単一の数値を表すメトリクスです。温度、メモリ使用量、同時接続数などの値を測定するために使用されます。  

**Python のコード例**  
```python  
from prometheus_client import Gauge  

# ゲージメトリクスを作成  
memory_usage_gauge = Gauge('memory_usage_bytes', 'Memory usage in bytes')  

# メモリ使用量の変化をシミュレート  
memory_usage_gauge.set(1024)  
memory_usage_gauge.inc(512)  
memory_usage_gauge.dec(256)  

print(memory_usage_gauge._value.get())  
```  

**説明**:  
- `Gauge` クラスをインポートし、`memory_usage_bytes` という名前のゲージを作成します。  
- 初期値を1024バイトに設定し、512バイト増加させ、256バイト減少させます。  
- 最終的なゲージの値（1280バイト）を出力します。  

**時間経過に伴うデータの変化**  
- **1分間**:  
  メモリ使用量は急激に変動する可能性があります。例えば、初期値が1024バイトで、プロセスが追加で300バイトを消費すれば、ゲージの値は1324バイトに上昇します。プロセスが100バイトを解放すれば、1224バイトに低下します。  
- **5分間**:  
  値は複数回変化する可能性があります（例: 5分間で1024 → 1324 → 1200 → 1500 → 1400 → 1600バイト）。  

**変化の原理**:  
ゲージの値は、明示的に設定、インクリメント、またはデクリメントすることができます。Prometheus は、各サンプリング間隔での現在値を記録し、監視対象のリアルタイムな状態を反映します。  


### 2.3 ヒストグラム  
**ヒストグラム (Histogram)** は、観測値（例: リクエストの応答時間、レスポンスサイズ）をサンプリングし、設定可能なバケットにカウントします。また、すべての値の合計も提供します。  

**Python のコード例**  
```python  
from prometheus_client import Histogram  
import random  

# 特定のバケットを持つヒストグラムメトリクスを作成  
request_duration_histogram = Histogram(  
    'http_request_duration_seconds',  
    'HTTP request duration in seconds',  
    buckets=(0.1, 0.2, 0.3, 0.4, 0.5)  
)  

# 20件のリクエスト応答時間をシミュレート  
for _ in range(20):  
    duration = random.uniform(0, 0.6)  
    request_duration_histogram.observe(duration)  

# 結果を出力  
print(f"Sum: {request_duration_histogram._sum.get()}")  
print(f"Count: {request_duration_histogram._count.get()}")  
for bucket, count in request_duration_histogram._buckets.items():  
    print(f"Bucket {bucket}: {count.get()}")  
```  

**説明**:  
- 0.1～0.5秒のバケットを持つヒストグラムを定義します。  
- `observe()` メソッドを使用して、20件のリクエスト応答時間をシミュレートして記録します。  
- 合計値、カウント、およびバケットの分布を出力します。  

**時間経過に伴うデータの変化**  
- **1分間**:  
  新しい観測値（例: 1分間に25件のリクエスト）がカウントと合計を増加させ、バケットのカウントは実際の応答時間に基づいて更新されます。  
- **5分間**:  
  蓄積された観測値により、カウントと合計が大きくなります。長時間の応答が多く発生すれば、バケットの分布も変化します。  

**変化の原理**:  
各観測値はバケットに割り当てられ、合計値が更新されます。ヒストグラムは、時間の経過に伴うデータの分布を構築し、値の範囲と大きさの分析を可能にします。  


### 2.4 サマリー  
**サマリー (Summary)** は、観測値をサンプリングし、分位点（例: 中央値、90パーセンタイル）を計算することでデータの分布を要約します。ヒストグラムと異なり、固定されたバケットを使用しません。  

**Python のコード例**  
```python  
from prometheus_client import Summary  

# エンドポイントをラベルとしたサマリーを作成  
response_size_summary = Summary(  
    'http_response_size_bytes',  
    'HTTP response size in bytes',  
    labelnames=['endpoint']  
)  

# 異なるエンドポイントの観測値を記録  
response_size_summary.labels(endpoint='/api/v1/users').observe(1024)  
response_size_summary.labels(endpoint='/api/v1/posts').observe(2048)  

# 結果を出力  
print(f"Sum: {response_size_summary._sum.get()}")  
print(f"Count: {response_size_summary._count.get()}")  
for quantile, sum_val in response_size_summary._quantile_sum.items():  
    print(f"Quantile {quantile}: {sum_val.get()}")  
```  

**説明**:  
- `endpoint` というラベルを用いて、API ルートを区別するサマリーを作成します。  
- 2つのエンドポイントのレスポンスサイズを記録し、合計値、カウント、および分位点のデータを出力します。  

**時間経過に伴うデータの変化**  
- **1分間**:  
  新しいリクエストにより、カウント、合計、分位点が更新されます。例えば、大きなレスポンスがあれば、90パーセンタイルの値が上昇する可能性があります。  
- **5分間**:  
  蓄積されたデータにより、分位点の精度が向上します。カウントと合計は増加し、分布は長期的な傾向を反映します。  

**変化の原理**:  
観測値は、累積合計、カウント、および分位点の計算（移動ウィンドウなどのアルゴリズムを使用）を更新します。分位点は、最新のデータ分布を反映するように動的に調整されます。  


## 3. Prometheus のフローチャート（英語の bash ボックス図）  
```  
+-------------------+  
| Prometheus Server |  
+-------------------+  
|                   |  
|  Data Collection  |  
|  (Pull Model)     |  
|                   |  
|  Targets         |<---+  
|  (Exporters)     |    |  
|                   |    |  
+-------------------+    |  
                        |  
+-------------------+    |  
|  Exporter         |    |  
|  (e.g., Node     |    |  
|  Exporter)       |    |  
+-------------------+    |  
                        |  
|  Metrics          |    |  
|  (Counter, Gauge, |    |  
|  Histogram,       |    |  
|  Summary)         |    |  
+-------------------+    |  
                        |  
|  Push Metrics      |<---+  
|  to Prometheus    |  
+-------------------+  
|                   |  
|  Data Storage     |  
|  (TSDB - Time -    |  
|  Series Database) |  
|                   |  
+-------------------+  
|                   |  
|  Querying        |  
|  (PromQL)        |  
|                   |  
+-------------------+  
|                   |  
|  Visualization   |  
|  (e.g., Grafana) |  
|                   |  
+-------------------+  
```  

**フローチャートの説明**:  
1. **Prometheus サーバー** は、プルモデルを使用してターゲット（エクスポーター）からメトリクスを取得します。  
2. **エクスポーター**（例: Node Exporter）は、システムからメトリクスを収集し、Prometheus 互換の形式で公開します。  
3. メトリクス（カウンター、ゲージ、ヒストグラム、サマリー）は、Prometheus サーバーに送信されます。  
4. サーバーは、メトリクスをタイムシリーズデータベース（TSDB）に保存します。  
5. ユーザーは、**PromQL** を使用してメトリクスを照会します。  
6. 照会されたデータは、Grafana などのツールを用いて視覚化されます。  


## 4. まとめ  
Prometheus のデータ型を理解することは、効果的なシステムモニタリングのための必須条件です：  
- **カウンター** は累積的なイベントを追跡します。  
- **ゲージ** は変動する値を監視します。  
- **ヒストグラム** はバケット内のデータ分布を分析します。  
- **サマリー** は分位点に基づいた洞察を提供します。  

Python の例では、実装方法と時間的な変化を示しており、フローチャートでは、データの収集から視覚化までの Prometheus のデータフローを概説しています。これらの知識を活用することで、ユーザーは Prometheus を用いて効率的にシステムの監視と管理を行うことができます。  


# [Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)  
**Leapcell** は、Python サービスをデプロイするための最適なプラットフォームです。  

[![brandpic7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4075813/b0689961-656c-4fa5-bf79-bae832b81bd3.png)](https://leapcell.io/)



### 🚀 好きな言語で開発  
JavaScript、Python、Go、Rust など、あなたのお好みの言語で簡単に開発できます。  

### 🌍 無料で無制限のプロジェクトをデプロイ  
リソース使用量にのみ課金されます — リクエストがなければ料金が発生しません。  

### ⚡ 使った分だけ請求、隠れた料金はありません  
アイドル時の料金は一切なく、シームレスにスケーリングできます。  

[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4075813/c7b7b31c-c232-42a0-bba3-dddd1b56b765.png)](https://leapcell.io/)


[📖 ドキュメントを確認する](https://docs.leapcell.io/)  
🔹 Twitter でフォローして最新情報を入手: [@LeapcellHQ](https://x.com/LeapcellHQ)