【徹底解説】Prometheusエクスポーター

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/7b52ebc4-f460-2f7d-100c-e6260e41a710.png)


Prometheusエクスポーターの作成は複雑なこともありますが、そうである必要はありません。 この記事では、Prometheusの基本を学び、Pythonに基づいたエクスポーターの実装を示す2つの段階的なガイドを紹介していきます。 最初のガイドは、監視するアプリケーションに関するメトリックをスタンドアロンで公開するサードパーティのエクスポーターについてです。 2つ目は、組み込みアプリケーションメトリックを公開するエクスポーターをカバーしていきます。

#Prometheus概要
[Prometheus](https://prometheus.io/)は、2012年の導入以来、独自の概念を適用してきた時系列メトリックの主要なモニタリングツールです。具体的には、Prometheusのデータ収集のプルアプローチは、エクスポーターと柔軟な視覚化とともに、[Graphite](https://graphiteapp.org/)や[InfluxDB](https://www.influxdata.com/products/influxdb-overview/)などの他の一般的なモニタリングツールと比較しても、際立っています。 

###プル型のデータ収集
データ収集のプルアプローチは、サーバーコンポーネント（Prometheusサーバー）がクライアントコンポーネントから定期的にメトリックを取得することで構成されます。 このプルは、Prometheusの世界では一般的に「スクレイプ」と呼ばれています。 スクレイピングを介して、クライアントコンポーネントはメトリックの生成とスクレイピングに利用できるようにすることのみを担当します。

Graphique、InfluxDB、その他の多くのツールは、クライアントコンポーネントがメトリックを生成してサーバーコンポーネントにプッシュするプッシュ型アプローチを使用します。 したがって、クライアントは、サーバーがデータを必要とするかどうか、またはデータを収集する準備ができているかどうかに関係なく、いつデータをプッシュするかを決定します。

Prometheusのプルアプローチは革新的です。クライアントではなくサーバーにスクレイピングを要求することにより、サーバーが稼働していてデータが準備できたときにのみメトリックを収集するからです。 このアプローチでは、各クライアントコンポーネントがPrometheusエクスポーターと呼ばれる特定の機能を有効にする必要があります。

###Prometheusエクスポーター

エクスポーターは、Prometheusモニタリング環境に不可欠な要素です。 Prometheusクライアントとして機能する各プログラムは、その中心にエクスポーターを保持します。 エクスポーターは、メトリックデータを生成するソフトウェア機能と、特定のエンドポイントを介して利用可能な生成されたメトリックを公開するHTTPサーバーで構成されます。 メトリックは、Prometheusサーバーが読み取りおよび取り込み（スクレイピング）できる特定の形式に従って公開されます。 この記事の後半で、メトリックの作成方法とそのフォーマット、およびそれらをスクレイピングに使用できるようにする方法について説明します。

###柔軟な視覚化
Prometheusサーバーによってメトリックが取得されて保存されると、次にそれらを視覚化することになりますが、その方法にはさまざまなものがあります。 最も簡単な方法は、[Prometheus Expression Browser](https://prometheus.io/docs/visualization/browser/)を使用することです。 ただし、それには基本的な視覚化機能しかないため、式ブラウザーは主にデバッグの目的で使用されます（特定のメトリックの可用性または最後の値を確認します）。 より優れた高度な視覚化のために、ユーザーはGrafana[https://grafana.com/]などの他のツールを選択されることが多いです。 さらに、一部のコンテキストでは、ユーザーは、視覚化する必要があるメトリックを取得するために[Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/)に直接クエリするカスタムメイドの視覚化システムを持っている場合があります。

下図でサーバーコンポーネント、2つのクライアントコンポーネント、および外部視覚化システムを備えたPrometheus環境の基本アーキテクチャが紹介されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/33704e81-843f-6da2-cb16-e2745118b863.png)

#Prometheusエクスポーターの実装
アプリケーションの観点から、Prometheusエクスポーターを実装できる状況には、組み込みのアプリケーションメトリックのエクスポートと、スタンドアロンまたはサードパーティのツールからのメトリックのエクスポートの2種類があります。

###アプリケーション組み込みエクスポーター
これは通常、システムまたはアプリケーションが主要なメトリックをネイティブに公開する場合に当てはまります。 最も興味深い例は、アプリケーションがゼロから構築された場合です。これは、Prometheusクライアントとして機能するために必要なすべての要件を設計を通じて調査および統合できるためです。 場合によっては、エクスポーターを既存のアプリケーションに統合する必要があります。 これには、Prometheusクライアントとして機能するために必要な機能を追加するために、コード（さらにはデザイン）を更新する必要があります。 既存のアプリケーションへの統合は、慎重に行わないと、アプリケーションのコア機能に回帰が生じる可能性があるため、リスクを伴う可能性があります。 これを行う必要がある場合は、アプリケーションに回帰を引き起こさないように、十分なテストを実施してください（たとえば、コードや設計の変更によるバグやパフォーマンスのオーバーヘッド）。

###スタンドアロン/サードパーティのエクスポーター
必要なメトリックが外部で収集または計算される場合があります。 この例は、アプリケーションがメトリックデータを取得できるAPIまたはログを提供する場合です。 このデータはそのまま使用できますが、メトリックを生成するためにさらに処理が必要になる場合があります（このMySQLエクスポーターがその例です）。

専用システムによる集計プロセス全体でメトリックを計算する必要がある場合は、外部エクスポーターも必要になる場合があります。 例として、ラベルでグループ化されたポッドのセットによって使用されているCPUリソースを示すメトリックが必要なKubernetesクラスターを考えてみます。 このようなエクスポーターはKubernetes APIに依存する可能性があり、次のように機能します。

1. 現在のCPU使用率と個々のポッドのラベルを取得する

2. ポッドラベルに基づいて使用量を合計する

3. 結果をスクレイピングに利用できるようにする

#Pythonを使用したエクスポーター実装の例
このセクションでは、Pythonを使用してPrometheusエクスポーターを実装する方法をステップごとに示します。 次のメトリックタイプをカバーする2つの例を示します。

- カウンター：値が時間の経過とともにのみ増加できるメトリックを表します。 この値は再起動時にゼロにリセットされます。 このようなメトリックは、システムの稼働時間（そのシステムの最後の再起動からの経過時間）をエクスポートするために使用できます。

- ゲージ：値が時間の経過とともに任意に増減できるメトリックを表します。 時間の経過とともにメモリとCPUの使用状況を公開するために使用できます。
 

2つのシナリオを検討します。最初のシナリオでは、スタンドアロンのエクスポーターがシステムのCPUとメモリの使用状況を公開することを検討します。 2番目のシナリオは、リクエストの応答時間と稼働時間を公開するFlask Webアプリケーションです。

###スタンドアロン/サードパーティのエクスポーター
このシナリオは、システムのCPUとメモリの使用状況を定期的に収集して公開する専用のPythonエクスポーターを示しています。

このプログラムでは、Python用のPrometheusクライアントライブラリをインストールする必要があります。

```
$ pip install prometheus_client
```

また、システムリソースの消費を抽出するために、強力なライブラリであるpsutilをインストールする必要があります。

```
$ pip install psutil
```

最終的なエクスポーターコードは次のようになります（ソースの要旨を参照）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/d3e2e708-95c9-e268-4e1e-47b34c30ab9f.png)

コードはダウンロードしてファイルに保存できます。

```
$ curl -o prometheus_exporter_cpu_memory_usage.py \
-s -L https://git.io/Jesvq
```

次のコマンドを使用すると、エクスポーターを開始できます。

```
$ python ./prometheus_exporter_cpu_memory_usage.py
```

ローカルブラウザー　http://127.0.0.1:9999
を介して公開されたメトリックをチェックできます。 Prometheusライブラリによって有効になっている他の組み込みメトリックの中で、次のメトリックはエクスポーターによって提供される必要があります（値はコンピューターの負荷に応じて異なる場合があります）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/0452253f-58ca-e920-50b2-35d37d563c62.png)

シンプルですね。 これは、Golang、Java、Python、Rubyで公式に利用できるPrometheusクライアントライブラリの魔法によるものです。 それらはボイラープレートを隠し、エクスポーターの実装を容易にします。 私たちのエクスポーターの基本は、次のエントリで要約できます。

- PrometheusクライアントPythonライブラリをインポートします（1行目）。
- HTTPサーバーをインスタンス化して、ポート9999（行10）でメトリックを公開します。
- ゲージメトリックを宣言し、system_usageという名前を付けます（6行目）。
- メトリックの値を設定します（13行目と14行目）。
- メトリックは、多次元データモデルの概念を利用して、ラベル（resource_type、6行目）で宣言されます。 これにより、単一のメトリック名を保持し、ラベルを使用してCPUとメモリのメトリックを区別できます。 ラベルを使用する代わりに、2つのメトリックを宣言することもできます。 どちらの方法でも、メトリックの名前とラベルに関するベストプラクティスを読むことを強くお勧めします。

###Flaskアプリケーションのエクスポーター
このシナリオでは、Flaskウェブアプリケーション用のPrometheusエクスポーターを示します。スタンドアロンとは異なり、Flaskウェブアプリケーションのエクスポーターには、リクエストをFlaskクライアントとPrometheusクライアントの両方にルーティングするゲートウェイとして機能するWSGIディスパッチアプリケーションがあります。これは、Flaskによって有効にされたHTTPサーバーを一貫して使用してPrometheusクライアントとしても機能させることができないために発生します。また、Prometheusクライアントライブラリによって有効にされたHTTPサーバーは、Flaskリクエストを処理しません。

[WSGI](https://wsgi.readthedocs.io/en/latest/)ラッパーアプリケーションとの統合を可能にするために、Prometheusは、メトリックを提供するWSGIアプリケーションを作成するための特定のライブラリメソッド（make_wsgi_app）を提供しています。

次の例（[ソースの要点](https://gist.github.com/rchakode/a992f1a3780e449ec040a1b6ca51c33f)）-ランダムな応答時間でリクエストを処理するようにわずかに変更されたFlask hello-worldアプリケーション-は、Flaskアプリケーションに沿って動作するPrometheusエクスポーターを示しています。 （18行目のhelloメソッドを参照）。 Flashアプリケーションはルートコンテキスト（/エンドポイント）を介してアクセスできますが、Prometheusエクスポーターは/ metricsエンドポイントを介して有効になります（WSGIディスパッチアプリケーションが作成される23行目を参照）。 Prometheusエクスポーターに関しては、2つのメトリックが公開されています。

- 最後のリクエストの応答時間：これはゲージ（10行目）で、前の例のようにsetメソッドを使用する代わりに、ビジネスコードをクリーンに保ちながら同じ仕事をするPrometheusデコレーター関数（17行目）を導入しました。

- サービス稼働時間：これは、アプリケーションの最後の起動以降に経過した時間を公開するカウンター（8行目）です。専用スレッド（33行目）により、カウンターは毎秒更新されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/ab6b9b9d-ef1e-3bda-2999-5d7d232b60f2.png)

プログラムが機能するように、追加の依存関係をインストールします。

```
$ pip install uwsgi
```
 
次に、WGSIを使用してプログラムを起動します。

```
$ curl -o prometheus_exporter_flask.py \

-s -L https://git.io/Jesvh
```
  

次に、サービスをWSGIアプリケーションとして開始します。

```
$ uwsgi --http 127.0.0.1:9999 \

--wsgi-file prometheus_exporter_flask.py \

--callable app_dispatch
```

--wsgi-fileはPythonプログラムファイルを指す必要がありますが、-callableオプションの値は、プログラムで宣言されているWSGIアプリケーションの名前と一致する必要があります（23行目）。

ここでも、ローカルブラウザを通じて公開されたメトリックを確認できます：http://127.0.0.1:9999/metrics
Prometheusライブラリによって公開されている他の組み込みメトリックの中で、エクスポーターによって公開されている次のメトリックを見つける必要があります（値はコンピューターの負荷によって異なる場合があります）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/850c2ff1-a4cc-80a8-9c40-fd955d4daa92.png)

これで、さまざまなエクスポーターがPrometheusサーバーによってスクレイピングされる準備が整いました。 これについて詳しくは、こちらをご覧ください。

#まとめ
この記事では、最初にPrometheusエクスポーターの基本的な概念について説明し、次に、Pythonを使用した2つの文書化された実装例について説明しました。 これらの例では、Prometheusのベストプラクティスを活用しているため、特定のアプリケーションのニーズに応じて独自のエクスポーターを構築するための開始点として使用できます。 Prometheusサーバーとの統合や、Grafanaなどのツールで処理できる視覚化については特に大きく取り上げませんでした。 これらのトピックに興味がある場合は、[こちら](https://qiita.com/MetricFire/items/cc9fe9741288048f4588)をご確認ください。

Prometheusを試してみたいが、セットアップやメンテナンスの苦労を考えたくない、または時間をかけたくないと思われる方は、[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=First%20Contact%20with%20Prometheus%20Exporters)が提供するHosted Prometheusの[無料トライアル](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=First%20Contact%20with%20Prometheus%20Exporters)を是非お試してみてください。 [デモを予約](https://calendly.com/metricfire-chatwithus/chat?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=First%20Contact%20with%20Prometheus%20Exporters)して、Prometheusモニタリングソリューションについて直接お問い合わせいただくこともできます。

それでは、またの記事で！