継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

Mackerel のカスタムプラグインを自作して FastAPI 関連プロセスを監視してみる

タダです.

Mackerel のプラグインには様々なものが既に用意されていますが,そのプラグインにないものがあれば作ってみようということで,FastAPI を動かすために必要な Uvicorn のプロセスを監視するプラグインを作ってみたのでこの記事でその模様をまとめます.

プラグインの種類

プラグインには2つの種類があり,メトリックプラグインとチェックプラグインがあります.前者はサーバーリソースの値をメトリック値を取得,送信するためのもので CPU やメモリなどが標準のサーバーのメトリックとしてありますが,標準のメトリック以外のものはカスタムメトリックとしてグラフに描画されます.後者はホスト上の特定プロセスの死活状況をチェックしたりするときに使い,メトリックプラグインのようにグラフの描画はないです.

メトリックプラグインとチェックプラグインを作る

それではメトリックプラグインとチェックプラグインを作っていきます.

メトリックプラグインを作る

Uvicorn のプロセスは uvicorn main:app --reload のように実行しても1プロセスしかあがらないようで,ドキュメント にも本番環境では gunicorn と一緒に使うことが推奨されているため下記のようなコマンドを実行したとします.

gunicorn example:app -w [ワーカー数] -k uvicorn.workers.UvicornWorker

www.uvicorn.org

メトリックプラグインのコードとして次のものを用意しました.メトリックプラグインのインターフェース仕様で {metric name}\t{metric value}\t{epoch seconds}というフォーマットで標準出力されることが求められているためスクリプトの最終行で echo -e "${metric_name}\t${metric}\t${date}" を行っている以外は大したことしてないかと思います.スクリプトの実行権限を chmod +x uvicorn-metrics.sh を与えることも忘れずにやりましょう.

uvicorn-metrics.s

#!/bin/sh

metric_name="uvicorn.test_metric.number"
metric=`ps aux |grep uvicorn | grep -v grep | wc -l`
date=`date +%s`

echo -e "${metric_name}\t${metric}\t${date}"

そして,/etc/mackerel-agent/mackerel-agent.conf にも下記の定義を追加して sudo systemctl restart mackerel-agent で再起動します.

[plugin.metrics.uvicorn]
command = "/xxx/xxx/uvicorn-metrics.sh"

数分待つと,メトリックのデータが送られてきてるのを確認できました.Uvicorn の8つのプロセスが記録されていることが確認できました.

f:id:sadayoshi_tada:20210630073845p:plain

チェックプラグインを作る

次にチェックプラグインをつくっていきますが,メトリックプラグイン同様にスクリプトとして次のようなものを用意しました.正常なプロセスの数はメトリックプラグインの記録された値として8を入れてその時は正常ですが,それ以外の値になったら Critical になるように設定しています(チェックプラグインの仕様はドキュメント に記載があります).スクリプトの実行権限を chmod +xuvicorn-ps-check.shで与えます.

uvicorn-ps-check.sh

#!/bin/sh

count=`ps aux |grep uvicorn | grep -v grep | wc -l`
if [ $count -eq 8(正常なプロセスの数) ]; then
  exit 0
else
  exit 2
fi

そして,/etc/mackerel-agent/mackerel-agent.conf にも下記の定義を追加して sudo systemctl restart mackerel-agent で再起動します.

[plugin.checks.uvicorn]
command = "/xxx/xxx/uvicorn-ps-check.sh"

数分待つと,Monitors のセクションに uvicorn が監視されていることを確認できました.

f:id:sadayoshi_tada:20210630074619p:plain

試しにプロセスを落としてアラートが出るかを確認してみます.

$ gunicorn main:app -w 8 -k uvicorn.workers.UvicornWorker
~中略~
[2021-06-29 22:20:44 +0000] [22251] [INFO] Waiting for application startup.
[2021-06-29 22:20:44 +0000] [22251] [INFO] Application startup complete.
^C[2021-06-29 22:47:40 +0000] [22246] [INFO] Handling signal: int
~中略~
[2021-06-29 22:47:40 +0000] [22246] [INFO] Shutting down: Master

Critical 扱いでアラートが出ることが確認できました.プロセスが落ちてもその状況をモニタリングできるようになりました.

f:id:sadayoshi_tada:20210630074922p:plain

まとめ

今回の開発で a-know (id:a-know)さんの記事を参考に Uvicorn のプロセス監視のプラグインを作っていきました.a-know さんありがとうございます! Go でも作っていきたいけどまずはさくっとシェルスクリプトプラグインを作れる体験を持てたのはとても大きかったです.こっからプラグイン開発に入り込んで行けたらなと思います.

blog.a-know.me