Mackerelのカスタムダッシュボードにアラートの一覧を表示する
このエントリはMackerel Advent Calendar 2022の24日目の記事です。
本エントリでは、MackerelのAPIを使ってカスタムダッシュボードに欲しいけど『ない』機能を補う代替機能のアイデアを紹介したいと思います。
TL;DR
カスタムダッシュボードのご紹介
Mackerelには、監視の運用に合わせたオリジナルのダッシュボードが実装できるカスタムダッシュボードがあります。
カスタムダッシュボードには以下の4種類のウィジェットが用意されているので、これらを組み合わせることでより自由度の高いダッシュボードを構成できます。
- グラフウィジェット
- 各種グラフが表示できる
- 数値ウィジェット
- 各種メトリックの最新の値を数値で表示できる
- Markdownウィジェット
- Markdown形式で自由に内容を記述できる
- アラートステータスウィジェット
- 特定のロールに所属している全てのホストのアラートステータスを表示できる
この4つのウィジェットだけでもダッシュボードを構成するのに充分ですが、ここにはないウィジェットで、次のようなウィジェットのご要望をよくいただきます。
どちらも2022年時点では対応していないのですが、アラートの一覧についてはMarkdownウィジェットで代用できそうなので、実装してみることにしました。
実装していく
この記事では主にLinux環境で動かすことを想定して、bashで実装します。他の環境、言語でももちろん実装できるので参考になればと思います。
必要なもの
bashやcurl以外に以下を事前にインストールしてください。
mkrのインストールはヘルプの手順が参考になります。
ダッシュボードを取得する
アラート一覧を表示したいダッシュボードを取得します。
あらかじめダッシュボードには、アラート一覧用のMarkdownウィジェットを登録しておいてください。
ダッシュボードの取得は、ダッシュボード取得API、mkrのどちらでもできます。
mkr dashboards pull
mkrの場合、カレントディレクトリにdashboards-<ダッシュボードID>.json
が保存されます。ただ今回はローカルにファイルを残したくなかったので、curlでAPIを叩くようにします。
curl \ -X GET \ -s https://api.mackerelio.com/api/v0/dashboards/${DASHBOARD_ID} \ -H "Content-Type: application/json" \ -H "X-Api-Key: ${API_KEY}" \ -f
ダッシュボードの構成に合わせて、次のようなJSONがレスポンスされます。
{ "id": "xxxxxxxxxxx", "title": "毎日見たいダッシュボード", "urlPath": "xxxxxxxxxxx", "createdAt": 1234567890, "updatedAt": 1234567890, "memo": "", "widgets": [ { "type": "markdown", "title": "直近のアラート", "layout": { "x": 0, "y": 0, "width": 12, "height": 6 }, "metric": null, "graph": null, "range": null, "markdown": "ここにアラートの一覧を表示する。" }, { "type": "markdown", "title": "別のMarkdownウィジェット", "layout": { "x": 12, "y": 0, "width": 12, "height": 6 }, "metric": null, "graph": null, "range": null, "markdown": "こっちは更新されたくない。" } ] }
このダッシュボードには2つのMarkdownウィジェットが登録されていて、今回は「直近のアラート」というタイトルがつけられた方のウィジェットに対してアラート一覧を反映します。
ちなみにダッシュボードにはユニークに払い出されたIDを持ちますが、ウィジェットにはIDが払い出されません。そのため、ウィジェットのtitle
をキーとして使用します。
アラートの一覧を取得する
現在オープンしているアクティブなアラートを取得します。
アラートの取得はアラート取得APIからできますが、 mkr を使うと次のような感じでいい感じにフォーマットされた内容が取得できます。
mkr alerts list
4Hrxxxxxx79 2022-12-07 03:10:32 CRITICAL 死活監視 IP-xxxxxxxx working [Service:Role] 4HrxxxxxxX3 2022-12-07 02:55:24 WARNING Service - Windows - CPU % cpu% 0.00 > 70.00 IP-xxxxxxxx working [Service:Role] 4HaxxxxxxSm 2022-12-01 14:47:30 CRITICAL Event Log CRITICAL: 0 warnings, 1 criticals. EC2AMAZ-xxxxxxx working [Service:Role]
アラートID、発生日時、アラートレベル、メッセージなどが含まれるので、今回はこれをそのまま使用します。
この結果をもとに、次のようにMarkdownでリスト化して各アイテムにアラートへのリンクを貼ることで、ダッシュボードからアラートを開けるので便利になりそうです。
- [アラートの情報](アラートへのリンク) - [アラートの情報](アラートへのリンク) :
mkr alerts listの結果のうち、アラートIDはリンクに、それ以外をアラート情報として一覧に表示する形式にしたいですが、awkを使うことで簡単に整形できます。
mkr alerts list | awk '{m="";for(i=2;i<=NF;i++) m=m $i " "; print "- [" m "](https://mackerel.io/orgs/オーガニゼーション名/alerts/" $1 ")"}'
- [2022-12-07 03:10:32 CRITICAL 死活監視 IP-xxxxxxxx working [Service:Role] ](https://mackerel.io/orgs/xxx/alerts/4Hrxxxxxx79) - [2022-12-07 02:55:24 WARNING Service - Windows - CPU % cpu% 0.00 > 70.00 IP-xxxxxxxx working [Service:Role] ](https://mackerel.io/orgs/xxx/alerts/4HrxxxxxxX3) - [2022-12-01 14:47:30 CRITICAL Event Log CRITICAL: 0 warnings, 1 criticals. EC2AMAZ-xxxxxxx working [Service:Role] ](https://mackerel.io/orgs/xxx/alerts/4HaxxxxxxSm)
この結果をMarkdownウィジェットに反映していきましょう!
ダッシュボードを更新する
取得したダッシュボードのJSONのうち、以下の条件にあてはまる要素の内容を生成したアラート一覧の内容で書き換えます。
type
がmarkdown
title
が直近のアラート
ここで役に立つのがjq
です。次のように|=
で代入することで内容を書き換えることができます。
jq '(.widgets[] | select(.type == "markdown" and .title == "直近のアラート") | .markdown) |= "整形されたアラート一覧のMarkdown"'`
これをダッシュボード更新APIから定期的に更新することで、カスタムダッシュボードにアラート一覧を表示できます。
完成したスクリプト
これらを組み合わせたBashスクリプトが次のようになります。
#!/bin/bash API_KEY=APIキー ORG_NAME=オーガニゼーション名 DASHBOARD_ID=ダッシュボードID WIDGETS_TITLE=直近のアラート result=0 # ダッシュボードの取得 DASHBOARD_JSON=$( \ curl \ -X GET \ -s https://api.mackerelio.com/api/v0/dashboards/${DASHBOARD_ID} \ -H "Content-Type: application/json" \ -H "X-Api-Key: ${API_KEY}" \ -f \ ) || result=$? if [ "$result" -ne 0 ]; then echo "failed to retrieve dashboard." exit 1 fi # アラート一覧の取得 ALERT_LIST=$( \ mkr alerts list | \ awk \ -v ORG_NAME=${ORG_NAME} \ '{m="";for(i=2;i<=NF;i++) m=m $i " "; print "- [" m "](https://mackerel.io/orgs/" ORG_NAME "/alerts/" $1 ")"}' \ ) || result=$? if [ "$result" -ne 0 ]; then echo "failed to retrieve the alert list." exit 1 fi # アラート一覧のMarkdownウィジェットを修正 MODIFIED_JSON=$( \ echo $DASHBOARD_JSON | \ jq -c \ --arg ALERT_LIST "$ALERT_LIST" \ --arg WIDGETS_TITLE "$WIDGETS_TITLE" \ '(.widgets[] | select(.type == "markdown" and .title == $WIDGETS_TITLE) | .markdown) |= $ALERT_LIST' \ ) || result=$? if [ "$result" -ne 0 ]; then echo "failed to correct dashboard." exit 1 fi # ダッシュボードの更新 curl \ -X PUT \ -s https://api.mackerelio.com/api/v0/dashboards/${DASHBOARD_ID} \ -H "Content-Type: application/json" \ -H "X-Api-Key: ${API_KEY}" \ -d "${MODIFIED_JSON}" \ -f \ > /dev/null 2>&1 \ || result=$? if [ "$result" -ne 0 ]; then echo "failed to update dashboard." exit 1 fi
API_KEY, ORG_NAME, DASHBOARD_ID, WIDGETS_TITLE は環境に応じて設定してください。
これをcronで定期的に実行することで、最新のアラート一覧をこんな感じでダッシュボード上に反映できるようになるはずです!
まとめ
いかがでしたでしょうか。
今回は主にLinux環境を想定してシェルで実装していますが、Windows環境だとPowerShellで実装したり、AWS Lambdaなどサーバーレスな環境でも実装することができると思います。
アイデア次第で色々と拡張できるので、ぜひ色々と試してみてください!
明日はアドベントカレンダー最終日、id:wtatsuruさんです!お楽しみに!