Hi! アンバサダーです!

みなさん、Mackrelのカスタムダッシュボード使ってますか?
ダッシュボード作ってるとなんかワクワクしてきますよね!

ということで、私も先日ウィジェットが50近くあるようなカスタムダッシュボードを作ったんですね。
作ってる時はいいんですけど、いざ作り終えると「これ、もう一回作れと言われても無理やな」と思うし、作ったのがご操作等でなくなったり定義が変わって変な表示になったりすると復旧が大変です。
(Mackerelのダッシュボードはそんなに変な表示にはならんと思うけど)

ちなみに、このダッシュボード、同じようなロール・ホスト構成の別のサービス(本番・ステージングでMackerelのサービス分けてるような感じを想像してください)でも使いたいとかあると、同じ物を複製するのは新規で作るときよりモチベーションがダダ落ちします。

ということで、ダッシュボードの定義情報をテキストとしてGitとかで管理したくなったんですけど、mkr(のv0.44以上なら)管理できますよ、という記事です。

それでは行ってみましょう!



とりあえず、テキストの定義情報で管理するなら mkr でできるかどうかを確認します。


訓練されてるので、おもむろにヘルプページを見ます。
「お、dashboardsコマンドあるやんけ!」ということで見てみましたが、どうもその時点(2021年2月18日)ではまだレガシーダッシュボードにしか対応してなさそうです。

これは困った。困った時は「サポートチームに連絡」です。Mackerelで一番好きな機能です。
やりたいこととか、サポートして欲しい機能とかを書いて、どうやったら実現できそうか、(将来的にでも)実装予定はあるか、みたいなことを質問します。
Mackerelのサポートへの返事は早いので、遅くとも1日待てば返事はきます。

今回はなんと、数時間後に返事がきました。
「まだアナウンスできてないけど、先日(DockerHub調べで2月16日)リリースしたmkrのv0.44.0でそのあたりの機能はサポートしているので試してみて」という返事でした。なんというジャストタイミング!早速試してみましょう。
(ちなみに、ちょうどサポートに問い合わせした前後くらいにv0.44.1がリリースされています)

GitHubのリリースページはこれです。確かに「add dashboard list, pull, push, and migrate commands for current dashboards. 」という一文が見えます。レガシーダッシュボードに対して「current dashboards」って呼んでるのかな?


とりあえず、作業用のEC2にインストールしてるmkrをアップデートします。

$ yum check-update
...
mkr.x86_64        0.44.1-1.amzn2        mackerel
...
$ sudo yum update -y mkr
...
Complete!
$ mkr --version
mkr version 0.44.1 (rev:fa78822)
$ mkr dashboards --help
NAME:
   mkr dashboards -
    Manipulate custom dashboards. With no subcommand specified, this will show all dashboards. See https://mackerel.io/docs/entry/advanced/cli


USAGE:
   mkr dashboards command [command options] [arguments...]

COMMANDS:
   generate  Generate custom dashboard
   pull      Pull custom dashboards
   push      Push custom dashboard
   migrate   Migrate a legacy dashboard

OPTIONS:
   --help, -h  show help

ちゃんとdashboardsコマンドに pull / push あたりがあります。
まだヘルプにファイルの形式とか反映されてないのでとりあえず今あるダッシュボードをpullして定義を見てみることにします。
$ mkr dashboards pull
      info Dashboard file is saved to 'dashboard-hogehoge.json'(title:HogeHoe)
      ....
      info Dashboard file is saved to 'dashboard-fugafuga.json'(title:FugaFuga)
なるほど、新しいダッシュボードの定義はJSONなんですね(レガシーダッシュボードの定義はYAMLだったはず)。
ちなみに、 「dashboard-hogehoge.json」のhogehoge部分はダッシュボードのID(カスタムURLを変更してなければURLのパス)になります。
カスタムURLを変更していてもIDで落ちてくるので、注意です。(とは言え、親切にtitleを一緒に出してくれるのでどれがどのダッシュボードのファイルかはわかると思います。ファイル内にもダッシュボード名は入っています)

ダッシュボードの定義JSONのサンプルは以下のような感じになります。


type / title / layout / metric / graph / range / markdownあたりのキーが見えます。
詳しく見ていくと、typeによって設定するキーが違うように見えます。
typeがgraphだとgraphに定義を書いて、valueだとmetric、markdownだとmarkdownに書いていくように見えます。layoutはダッシュボードの編集画面みたことがある人はわかると思いますが、グリッド上の配置を記載していますね。

ということで、このjsonを少し修正(idを別の空のダッシュボードにセット、createdAtとかupdatedAtとかを削除)してpushしてみます。
pushコマンドは --file-path もしくは -F オプションでファイルを指定します。

$ mkr dashboards push -F dashboards-hogehoge.json
     error API request failed: Invalid Parameter: obj.widgets[1] 'roleFullname' is undefined on object: {"type":"alertStatus","title":"Alert Status","layout":{"x":6,"y":0,"width":4,"height":3},"metric":null,"graph":null,"range":null}.
はい、エラーが出ました。
「AlertStasusなウィジェットに必要な定義 `roleFullname` がないぞ」というエラーですね。
JSONみた時にそんな気はしてました。
なので、push試す前にサポートに「これ、AlertStatusに定義なくて大丈夫?」という追加の質問していますし、pushでエラーが出たのを確認して追加の情報として上記のエラーメッセージも伝えていますので、そのうち直ると思います。

ということで、AlertStatusのウィジェットは一旦消して再度pushをしたところ、無事に成功して新しいカスタムダッシュボードができていました!バンザイ!


そんなこんなで、このダッシュボードの定義をGitで管理できるようにやっていきます。
とりあえず、個人的にJSONで管理するのは辛いので、yqを使ってYAMLに変換します。
その後、サービス固有の情報(ダッシュボードのID、タイトル、サービス名、ホストID等)を変数化していきます。例えば、サービス名を「${SERVICE_NAME}」という形に変換しておきます。
サービス名等はenvファイルとかにして別ファイルで管理します。
こいつはGitでは管理しない想定ですが、特にクレデンシャルな情報が入っているわけでもない(せいぜい、Mackerel上でのIDくらい?)ので、Gitにコミットしてしまってもいいかもしれません。

で、環境が増えたり、Webでダッシュボードをついうっかり壊してみたり、ダッシュボードの定義を少し変更してみたりした場合には以下のコマンドで簡単にダッシュボードを復元できるようになります。

# 環境ごとのenvファイルを読み込み
$ . .env
# YAML上の変数を実際の値に置き換えてJSONに変換
$ envsubst < dashboards-hogehoge.yml | yq . > dashboards-hogehoge.json
$ mkr dashboards push -F dashboards-hogehoge.json

結論

便利

捕捉というか注意というか

近いうちに公式からアナウンスが出て、ヘルプページも更新されると思うので、詳細はそちらを見ることをオススメします。

追記(2021/02/24 09:30 頃)

2/22に公式からアナウンス出ましたね。


さらに、Alert Statusのウィジェット対応も進められているようです。
mackerelio/mackerel-client-go#120