Mackerel plugin (mackerel-plugin-prometheus-exporter) を書いてみた #mackerelio

この記事はMackerelアドベントカレンダー23日目の記事です。

22日はshiimaxxさんのMackerelで負荷テスト中のリソースモニタリングを行うでした!

そして今日はMackerel Day #2ですね!

Mackerel 5周年おめでとうございます! 🎉🎉🎉🎉🎉

Mackerel pluginを書いたことがない

実は私、Mackerelアンバサダーになっていたのでした(公ではじめて言った)*1

ただ、まだMackerel pluginを書いたことがない のでした。

そして今回 id:a-know さんにたまたまツイートを拾ってもらいアドベントカレンダーにお誘いを受けたので、「とても良い機会!」ということで書いてみました。

Mackerel pluginの作り方は公式マニュアルに完璧にまとめられていた

f:id:k1LoW:20191221152806p:plain
プラグインの作り方を調べてまとめようと思っていた

Mackerel pluginの作り方ってどんな感じなのかなーと調べたら公式マニュアルにサンプルコードも含めて完璧にまとまっていました ので、当初考えていたエントリはここで終了となりました。

「終了」だけだとあれなので、プラグインの開発からリリースまでに見た方が良さそうなマニュアルの箇所だけ列挙しておきます。

完璧なマニュアルでした!!

Mackerel pluginを書いてみる

ではMackerel pluginを書いていきます。

お題選定

お題はこれです。

選定の理由は「そーだいさんが求めていたから」というのもありますが、2018年のMackerel Meetup #11でも実装が検討されていたようなので、お題で書くとはいえMackerelユーザの一定の割合の人が興味あるかもと思ったからです。

また、私は普段の業務でMackerelだけでなくPrometheusを触ることも多く、マニアックなExporterも書いていたりするので、いけるんじゃないかなと。

Mackerel pluginは標準出力にメトリクスを出力する、シンプルなコマンドラインツール

公式マニュアルにもあるようにmackerel-agentとMackerel pluginは標準出力を通じて連携しています。

ようは、取得したメトリクスをMackerelが指定しているフォーマットで標準出力に出力すれば良いわけですね。

Goで書くのであれば、github.com/mackerelio/go-mackerel-plugin パッケージを活用すれば、提供されているインターフェースを満たせば終わりです。そしてそのサンプルコードは公式マニュアルにあります

私はコマンドラインツール作成用ライブラリは、github.com/spf13/cobraが好きなので、これで雛形を生成します。

$ cobra init mackerel-plugin-prometheus-exporter --pkg-name github.com/k1LoW/mackerel-plugin-prometheus-exporter --viper=false

あとは cmd/root.go に、公式マニュアルのサンプルコードを参考に実装を書いていくだけです。

Prometheus ExporterはHTTPリクエストに対して text/plain でメトリクスを出力する、シンプルなWebアプリケーション

Prometheus ExporterもMackerel pluginとほとんど同じで、Prometheusが読めるフォーマットでテキストを出力しているだけです。ただそれが標準出力ではなく、HTTPリクエストに対するレスポンスというだけです。

ようは、ExporterにHTTPリクエストして受け取ったテキストをパースすれば良いわけですね。

そして、Prometheusのエコシステムの中で、この「ExporterにHTTPリクエストをしてテキストをパースしている」のはPrometheusになります。

たまたまPrometheusもGoで書かれていて読めそうなので見にいってみます。

github.com

実際にパースしているのは github.com/prometheus/prometheus/pkg/textparse パッケージのようなので、テストケースなどを参考に使い方を把握します。

mackerel-plugin-prometheus-exporter

ここまでのまとめです。

  1. mackerel-agentからMackerel pluginが実行される
  2. github.com/prometheus/prometheus/pkg/textparse パッケージを使って任意のExporterからメトリクスを取得する
  3. 取得したメトリクスを github.com/mackerelio/go-mackerel-plugin パッケージのルールに合わせて詰め直す
  4. mackerel-agentが標準出力経由でメトリクスを取得してMackerelに送信する

. . .

できました!

github.com

具体的には以下のようなアーキテクチャになります。

f:id:k1LoW:20191221172030p:plain
mackerel-plugin-prometheus-exporterのメトリクス収集アーキテクチャ

使ってみる

使ってみます。

まず mackerel-plugin-prometheus-exporter をインストールします。

$ sudo mkr plugin install k1LoW/mackerel-plugin-prometheus-exporter

node_exporterを起動しておきます。

$ node_exporter # brew install node_exporter
INFO[0000] Starting node_exporter (version=0.18.1, branch=, revision=)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.13.4, user=Homebrew, date=)  source="node_exporter.go:157"
INFO[0000] Enabled collectors:                           source="node_exporter.go:97"
INFO[0000]  - boottime                                   source="node_exporter.go:104"
INFO[0000]  - cpu                                        source="node_exporter.go:104"
INFO[0000]  - diskstats                                  source="node_exporter.go:104"
INFO[0000]  - filesystem                                 source="node_exporter.go:104"
INFO[0000]  - loadavg                                    source="node_exporter.go:104"
INFO[0000]  - meminfo                                    source="node_exporter.go:104"
INFO[0000]  - netdev                                     source="node_exporter.go:104"
INFO[0000]  - textfile                                   source="node_exporter.go:104"
INFO[0000]  - time                                       source="node_exporter.go:104"
INFO[0000] Listening on :9100                            source="node_exporter.go:170"

mackerel-agent.confに設定を追記します。

[plugin.metrics.prometheus-exporter]
command = ["/opt/mackerel-agent/plugins/bin/mackerel-plugin-prometheus-exporter", "--target", "http://:9100/metrics"]

mackerel-agentを再起動します。

f:id:k1LoW:20191222221106p:plain
メトリクス数が多すぎて見えない

node_exporterのメトリクスがMackerelに取り込まれました!

もし利用するときは exclude_pattern の設定は必須ですね。

MackerelとPrometheus

MackerelとPrometheusは様々な点で設計思想が異なっています。

取得できたメトリクスを見てみるとわかるように、mackerel-plugin-prometheus-exporter経由でExporterから取得したメトリクスをMackerelで有用なグラフにするには exclude_pattern や、カスタムグラフなどを活用してグラフを整形する必要がありそうです。

もしPrometheusプロセスがどこかにいるのであれば、fujiwara さんが作成されたmackerel-plugin-prometheus-query でPrometheusを経由してPromQLで整形後にMackerelに送信するのがMackerelの思想的にも良さそうです(今日のMackerel Day #2でmackerel-plugin-prometheus-queryも含めた発表があるみたいです!楽しみですね!)。

もしくはMackerelのQueringの機能(具体的にはカスタムグラフ作成時に使用可能な関数)がさらに充実してくると、 mackerel-plugin-prometheus-exporter が使える範囲も広がってくるかもです。

というわけでMackerel pluginを作ってみたエントリでした!

明日は setoazusa さんです!

*1:Mackerelとも連携するmetrの作成が評価されたそうです! https://k1low.hatenablog.com/entry/2019/08/23/090831