ポン酢ブログ(β)

The harder you work, the luckier you get. - Gary Player

Grafanaのグラフを画像にしてSlackでシュッと取得&共有したい

Grafanaのダッシュボードって結構見るの億劫になりますよね。例えばNode Exporterとかで取得しているCPUのグラフだけ見たいんだけど、みたいな時にSlackでサクッと取れたら便利だなと思ったのでそういうSlack スラッシュコマンドを実装しました。

ソースコードGitHubで公開しています。バイナリとかDockerイメージも上がってるので試してみてください。

github.com

仕組み

実態はSlackのスラッシュコマンドとして動作します。バイナリは、スラッシュコマンドを受けるためのサーバ兼Grafanaクライアントとなっています。使い方は、まずSlack側でスラッシュコマンドと、files:writeの権限を与えたトークンをもらっておきます。そして、http://server/slashへSlackのスラッシュコマンドのリクエストURLに指定して、/graphなどで起動しておけるようにしておきます。

ここで注意ですが、Grafanaは標準では画像でグラフをエクスポートする機能はついていません。RRDToolとかに慣れていると画像で出てこないのは何か寂しい気持ちになります。プラグインとか流石にあるかな?と思ったら、Grafana Image Rendererというのがあるようで、これを使っています。

Grafana Image Rendererは、中でPuppeteer + Headless Chromeを使ってGrafanaからグラフを持ってきてそれをキャプチャしているみたいな感じの作りになっています。プラグインさえ入れてしまえば、以下のようなURLで特定のグラフパネルのキャプチャを取得できます。

http://grafana/render/d-solo/<dashboardId>/<dashboardName>?orgId=<orgId>&panelId=<panelId>

上記で実装したSlack スラッシュコマンドは、このURLからグラフを持ってきて、Slackにアップロードするだけの実装になっています。いちいちグラフのパネルIDなどを設定するのは面倒くさいので、以下のようなYAMLを記述して、/graph <name>で指定された設定のグラフパネルを持ってくるという仕組みになっています。

dashboards:
   -  name: disk
      dashboardId: "000000012"
      dashboardName: alerts-linux-nodes
      orgId: 1
      panelId: 1
   -  name: cpu
      dashboardId: "000000012"
      dashboardName: alerts-linux-nodes
      orgId: 1
      panelId: 4
   -  name: memory
      dashboardId: "000000012"
      dashboardName: alerts-linux-nodes
      orgId: 1
      panelId: 5

例えば、/graph cpuとやるとCPUのグラフパネルだけ持って来れます。

先ほどの/renderのURLは、時間指定も可能で、クエリパラメータにfromtoを付ければ大丈夫です。Grafanaを使ったことのある方なら、from=now-1hのような表記を見たことがあるかと思いますが、そのように指定して問題ありません。例えば、1時間のグラフを引っ張りたいときはfrom=now-1h&to=nowとなります。

今回のスラッシュコマンドでは、/graph cpu 1hのようにやって時間指定できるようにしてあって、任意の範囲で画像を取得できるようにしてあります。

仕組みとしては単純ですが、これでSlackで気になったときにグラフの画像を共有して残しておけるので便利になりました。本来であれば直接時刻を指定して、ダッシュボードへのリンクとかもあると親切なのかもしれません。(気が向いたら実装します)

余談

余談としては、クライアント証明書認証に対応しています。GrafanaでAuth Proxyを利用していて、利用しているリバースプロキシがクライアント証明書認証に対応している場合、クライアント証明書認証を使ってGrafanaにアクセスできるようにしています。Golangでクライアント証明書認証してhttp.Clientを使う練習になりました。

その他にも、一般的に使われているであろうAPIキーによる認証にも対応しています。というか、APIキーといいつつ、/api以外のパスにアクセスできるんですね・・・。(ということを確認してしまいました)