TT Lab
はじめる
学ぶ 学習パス コース

Grafana — ダッシュボードは問いだ

ダッシュボードを一つ開く値段はいくらか

TT Labで続きを見る

一言でいうと

ダッシュボード1つを開く値段は「パネル数」ではなく、クエリ数に自動リフレッシュの回数を掛けたものであり、その値を誰も数えていません。

なぜ必要なのか

モニタリングが遅くなったという報告は、たいてい「クエリが1つ重い」で始まり、「ダッシュボードが多すぎる」で終わります。ところが、その2つのあいだに、誰も数えていない数字が1つあります。ダッシュボード1つを1回開くのに、クエリが何回飛ぶのかです。

数え方は難しくありません。パネルごとにクエリが1つ以上付いているので、そのクエリをすべて足し、画面上部の変数のうち、一覧をサーバーに問い合わせるものがあれば、その分を足します。パネルが8つ、クエリが10個、変数クエリが2つなら、1回開くのに12回です。ここに自動リフレッシュが掛け算されます。10秒間隔なら、1分に60回、1時間に3,600回です。壁掛けのディスプレイ1台が1日に8万回を投げ、その画面を誰も見ていない夜にも、同じように投げ続けます。

さらに悪いのは、このコストが画面にまったく表れないことです。パネルを1つ追加する作業はクリック3回で、コストは別のチームのPrometheusで発生します。そのため、ダッシュボードはいつも、重くなる方向にしか育ちません。

どう動くのか

コストは3つの層で積み上がります。

層 何を数えるか どこで読むか
クエリ回数 開くときに何回、1分に何回 ダッシュボードJSONのパネル・クエリ・変数・refresh
系列数 クエリ1つが何行を返すか クエリを実際に投げて、結果の行を数えます
点の数 系列1つに点がいくつ来るか 時間範囲を解像度で割ったもの

1つ目の層は、JSONを見るだけで数えられます。ダッシュボードJSONモデルには、panels配列と各パネルのtargets、そして自動リフレッシュの間隔であるrefreshが、そのまま書かれています(ダッシュボードJSONモデルのドキュメント)。変数はtemplating.listにあり、そのうち、サーバーに一覧を問い合わせるのは、typeがqueryのものです。

2つ目の層は、投げてみないとわかりません。sum by (handler) (...)は系列を4つ返しますが、集計を外してrate(http_request_duration_seconds_bucket{...}[5m])をそのまま描くと、ハンドラー4×バケット12で、48行が来ます。同じパネル1枠に48本の線が描かれますが、その画面から読み取れるものは何もありません。系列数は、ブラウザーが描くべき点の数を決め、そのため、画面が遅くなる本当の理由になります。

3つ目の層は、時間範囲と解像度です。区間クエリはstart・end・stepを受け取り、そのあいだをstep間隔で区切って返します(PrometheusクエリAPIのドキュメント)。2時間を15秒間隔で見ると、系列1つに481個、300秒間隔なら25個です。同じ質問なのに、20倍の差が出ます。6時間の画面で15秒の解像度が必要になることは、ほとんどありません。

減らす方法のうち、いちばん安上がりなのは、すでにわかっている答えを、あらかじめ計算しておくことです。48個のバケット系列から毎回分位数を計算する代わりに、Prometheusが決まった間隔で、その計算を1回行い、結果を新しい時系列として残すようにします。レコーディングルールです。ダッシュボードは、その新しい時系列を読むだけで済みます。名前には慣例があり、レコーディングルールの慣例では、수준:지표:연산の形で書きます(プレースホルダーは順に、集計レベル、指標、演算です)。

現場での姿

データプラットフォームチームのPrometheusが、毎日午後になると遅くなりました。犯人は、人が開くダッシュボードではなく、会議室の壁に映していた2つの画面でした。どちらも、リフレッシュが5秒で、クエリがそれぞれ14個でした。誰も見ていない時間にも、1分に336回が飛んでいました。リフレッシュを1分に変えて、使っていない変数を3つ削除しただけで、その負荷が28分の1になりました。パネルは1つも削除していません。

もう1つよくあるのは、誰も使っていない変数です。画面上部のドロップダウンは、一度作ると削除する人がいませんが、ダッシュボードを開くたびに、一覧を埋めるためのクエリが飛びます。その変数をどのパネルも参照していなくても、同じです。

この環境で判定できることとできないこと

コストをミリ秒で測る作業は、このPodでは意味がありません。2つのCPUを学習者のプロセスと採点ツールが分け合って使い、同じMac上で別のコンテナも一緒に動いているので、同じクエリでも測るたびに違う時間が出ます。そのため、ここでは個数だけで判定します。ダッシュボードJSONから数え直したパネル・クエリ・変数の数、実際に投げて得られた系列の数、区間クエリが返した点の数です。レコーディングルールは、Prometheusに実際に反映して、値が元のクエリと合っているかを見ます。画面が実際にどれだけ速く表示されるかは、結局、ブラウザーで目で見る必要があります。

次のラボですること

バジェットを超えたダッシュボードを1つ受け取って、値段を付けます。JSONでパネル・クエリ・変数クエリを数えて、「1回開くときのクエリ数」を出し、各クエリを実際に投げて系列数を測り、いちばん重いパネルを見つけます。時間範囲と解像度を変えながら、返ってくる点の数を測り、リフレッシュ間隔を掛けて、毎分のクエリ数を出します。重い分位数の計算はレコーディングルールに移して、同じ値をより安く得て、バジェットをファイルに書いたあと、そのバジェットを検査するスクリプトを作り、縮小したダッシュボードがその検査を通ることまで確認します。