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

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

順位を問うパネルをテーブルに移す

TT Labで続きを見る

目標

折れ線グラフ4本が重なったダッシュボードを受け取り、順位を問うパネルをテーブルに移して、reduce・organize・joinByFieldの変換で、読める形にします。

なぜ重要なのか

ダッシュボードが答えるべき質問は、大きく2つあります。「いつからこうなったのか」と「どれがいちばん悪いのか」です。前者は時間に沿った動きなので折れ線グラフが合っていますが、後者はある瞬間のソートされた一覧なので、折れ線グラフでは答えられません。系列4つの値が互いに近いと、線は絡み合い、順位を知るには、1つの時刻を選んで4つの値を読み、頭の中で並べ替える必要があります。8個になると、誰もその作業をしません。テーブルは、その並べ替えを画面が代わりに行う形で、変換は、時系列をテーブルが読める形に変える道具です。ただし、すべてのパネルをテーブルに変えると、かえって悪くなります。移すのは、順位を問うパネルだけです。

ステップ

  1. lab-start-grafanaでGrafanaを起動し、/opt/lab/gfd/gfd-table/ranking.jsonを、修正せず、そのままGrafanaにアップロードしてください(uidはファイルに書かれたgfd-table、パネルは4つ)。curlで/api/dashboards/dbにPOSTすればよいです。アップロードしたあと、Webプレビューの3000番ポートで一度開いて、4つのパネルがどう見えるかを、目で確認しておいてください。
  2. パネル1は、4つのハンドラーのp95を重ねて描きます。過ぎた時刻を1つ選び(今より1時間以上前、6時間以内)、その瞬間のp95をハンドラーごとに測って、/root/gfd-table/02-rank.txtに、at=、rank1=、rank2=、rank3=、rank4=、gap=の6行で書いてください。atはエポック秒、rank1からrank4までは、p95が大きいものから順に書いたハンドラー名、gapは1位と4位のp95の差(秒)です。
  3. まず、テーブルが何行になるかを測ってください。過ぎた区間を1つ選び(1時間以上、終わりは今より前)、パネル1のクエリをその区間にstep 60で投げて、/root/gfd-table/03-table.txtに、start=、end=、series=、points=、rows=の5行を書いてください。seriesは、同じクエリをendの時刻の瞬間値として投げたときに返ってきた系列の数、pointsは、区間クエリが系列1つに返した点の数、rowsは、その2つを掛けた値です。そして、パネル5を新しく作成してください。typeはtable、クエリはパネル1と同じものを、formatをtableにして、区間クエリで(instantは真にしないでください)投げます。
  4. パネル5にreduce変換を付けてください。transformations配列に、idがreduceの項目を1つ置き、options.modeはseriesToRows、options.reducersはlastNotNullだけを入れます。クエリは、そのまま区間クエリにしておきます。行を減らす作業を変換が行うかどうかを確かめるためです。直したダッシュボードを保存してください。
  5. パネル5のtransformations配列の、reduceの後ろに、idがorganizeの項目をもう1つ付けてください。options.renameByNameで、FieldとLast *の2つの列の名前を、それぞれ別の韓国語の名前に変え、options.indexByNameで、その2つの列の順序を0と1に固定してください。直したダッシュボードを保存してください。
  6. パネル6を新しく作成してください。typeはtable、クエリは2つです。refIdがAのものはsum by (handler) (rate(http_requests_total{job="shop-api"}[5m]))、refIdがBのものはパネル1と同じp95のクエリです。2つのクエリとも、instantを真に、formatをtableにしてください。そして、transformationsに、idがjoinByFieldの項目を1つ置き、options.byFieldをhandler、options.modeをouterにしてください。
  7. パネル6の既定のセル表示(fieldConfig.defaults.custom.cellOptions.type)はautoにしておき、fieldConfig.overridesに、p95の値の列1つだけを指名するオーバーライドを1つ追加してください。オーバーライドのmatcher.idはbyName、propertiesには、custom.cellOptions(typeをcolor-backgroundに)とthresholds(段階を2つ以上、最後の段階は数値のしきい値)を入れます。そして/root/gfd-table/07-cells.txtに、rule1=、rule2=、rule3=の3行で、テーブルのセルに色を付けるときに守るべきルールを、それぞれ40文字以上で、互いに異なる内容で書いてください。
  8. パネル2(핸들러별 5xx 비율、韓国語のタイトルは「ハンドラー別の5xx割合」という意味です)も、順位を問うパネルです。typeをtableに変えて、クエリはそのままにしたまま、instantを真に、formatをtableにし、organize変換でTime列を隠して(excludeByNameでTimeを真に)、残る2つの列の名前を変えてください。パネル4(전체 요청률)(韓国語のタイトルは「全体のリクエストレート」という意味です)には、手を付けないでください。順位を問うパネルではありません。そして、今アップロードされているダッシュボードをそのままダウンロードして、/root/gfd-table/fixed.jsonに保存し(.dashboardの本体だけ)、/root/gfd-table/08-review.mdに、R1=からR4=までの4行で、何をなぜ変えたかを、それぞれ30文字以上で書いてください。

参考

折れ線グラフ4本のダッシュボードを、そのままアップロードする

lab-start-grafanaでGrafanaを起動し、/opt/lab/gfd/gfd-table/ranking.jsonを、修正せず、そのままGrafanaにアップロードしてください(uidはファイルに書かれたgfd-table、パネルは4つ)。curlで/api/dashboards/dbにPOSTすればよいです。アップロードしたあと、Webプレビューの3000番ポートで一度開いて、4つのパネルがどう見えるかを、目で確認しておいてください。

保存APIは、ダッシュボードの本体をdashboardキーの中に入れ、overwriteを一緒に送ります。ファイルからその形を作るには、jq -n --slurpfileが便利です。Grafanaが起動するのに数十秒かかるので、/api/healthが応答するかどうかを、先に見てください。

折れ線グラフから順位を読んでみる

パネル1は、4つのハンドラーのp95を重ねて描きます。過ぎた時刻を1つ選び(今より1時間以上前、6時間以内)、その瞬間のp95をハンドラーごとに測って、/root/gfd-table/02-rank.txtに、at=、rank1=、rank2=、rank3=、rank4=、gap=の6行で書いてください。atはエポック秒、rank1からrank4までは、p95が大きいものから順に書いたハンドラー名、gapは1位と4位のp95の差(秒)です。

ある瞬間の値は、/api/v1/queryにtime=を一緒に送れば得られます。時刻を固定しておくと、あとでもう一度測っても同じ値が出ます。応答のmetric.handlerとvalue[1]を一緒に取り出して、sort -rnで並べれば、順位がすぐに出ます。4つの値がどれだけ近いかを見て、それを折れ線グラフで目で見分けられるかどうかを、考えてみてください。

同じ質問をテーブルに移す

まず、テーブルが何行になるかを測ってください。過ぎた区間を1つ選び(1時間以上、終わりは今より前)、パネル1のクエリをその区間にstep 60で投げて、/root/gfd-table/03-table.txtに、start=、end=、series=、points=、rows=の5行を書いてください。seriesは、同じクエリをendの時刻の瞬間値として投げたときに返ってきた系列の数、pointsは、区間クエリが系列1つに返した点の数、rowsは、その2つを掛けた値です。そして、パネル5を新しく作成してください。typeはtable、クエリはパネル1と同じものを、formatをtableにして、区間クエリで(instantは真にしないでください)投げます。

区間クエリは/api/v1/query_rangeで、start・end・stepを一緒に送ります。返ってきたJSONのdata.result[0].valuesの長さが、系列1つの点の数です。パネルを新しく作るときは、ダッシュボードをダウンロードして、panels配列に1つ加え、そのままもう一度保存すれば済みます。gridPosが重ならないように、yを下にずらしておいてください。

変換で、系列ごとに数字を1つだけ残す

パネル5にreduce変換を付けてください。transformations配列に、idがreduceの項目を1つ置き、options.modeはseriesToRows、options.reducersはlastNotNullだけを入れます。クエリは、そのまま区間クエリにしておきます。行を減らす作業を変換が行うかどうかを確かめるためです。直したダッシュボードを保存してください。

reduceは、系列1つを数字1つに減らします。seriesToRowsは、系列ごとに1行を作り、その行には、系列名が入ったField列と、選んだ計算値の列ができます。lastNotNullの列名はLast *です。次のステップで、この名前を使います。変換は、ダッシュボードJSONのパネルごとにあるtransformations配列に、順に入ります。

列の名前と順序を、人が読めるようにする

パネル5のtransformations配列の、reduceの後ろに、idがorganizeの項目をもう1つ付けてください。options.renameByNameで、FieldとLast *の2つの列の名前を、それぞれ別の韓国語の名前に変え、options.indexByNameで、その2つの列の順序を0と1に固定してください。直したダッシュボードを保存してください。

organizeは、列を隠し(excludeByName)、順序を決め(indexByName)、名前を変える(renameByName)、1つの変換です。3つのオプションとも、列名をキーにしたオブジェクトです。変換は、配列に書かれた順に、順番に適用されるので、前の変換が作り出した列名を、後ろの変換が受け取ることになります。Fieldは系列名の列、Last *は最後の値の列です。

2つのクエリをラベルで結合して、1つのテーブルに載せる

パネル6を新しく作成してください。typeはtable、クエリは2つです。refIdがAのものはsum by (handler) (rate(http_requests_total{job="shop-api"}[5m]))、refIdがBのものはパネル1と同じp95のクエリです。2つのクエリとも、instantを真に、formatをtableにしてください。そして、transformationsに、idがjoinByFieldの項目を1つ置き、options.byFieldをhandler、options.modeをouterにしてください。

瞬間値クエリは、系列ごとに1行を返すので、変換なしでもテーブルが短くなります。そのため、ここではreduceが必要ありません。2つの結果に共通してある列は、ラベル名そのままのhandlerです。結合したあと、値の列はValue #A・Value #Bで区別されます。outerは、片方にしかない行も残し、innerは、両方にある行だけを残します。

色は、しきい値のある列1つにだけ付ける

パネル6の既定のセル表示(fieldConfig.defaults.custom.cellOptions.type)はautoにしておき、fieldConfig.overridesに、p95の値の列1つだけを指名するオーバーライドを1つ追加してください。オーバーライドのmatcher.idはbyName、propertiesには、custom.cellOptions(typeをcolor-backgroundに)とthresholds(段階を2つ以上、最後の段階は数値のしきい値)を入れます。そして/root/gfd-table/07-cells.txtに、rule1=、rule2=、rule3=の3行で、テーブルのセルに色を付けるときに守るべきルールを、それぞれ40文字以上で、互いに異なる内容で書いてください。

パネルの既定値に色を設定すると、名前の列まで塗られます。色が意味を持つには、その色がしきい値を超えたということを伝える必要があり、そのためには、しきい値のある列にだけ付ける必要があります。オーバーライドは、fieldConfig.overrides配列の項目で、どの列に設定するかはmatcherが、何を変えるかはpropertiesが決めます。結合したあとのp95の値の列の名前を、先に確認してください。

まだ線のまま残っている順位のパネルを、テーブルに変える

パネル2(핸들러별 5xx 비율、韓国語のタイトルは「ハンドラー別の5xx割合」という意味です)も、順位を問うパネルです。typeをtableに変えて、クエリはそのままにしたまま、instantを真に、formatをtableにし、organize変換でTime列を隠して(excludeByNameでTimeを真に)、残る2つの列の名前を変えてください。パネル4(전체 요청률)(韓国語のタイトルは「全体のリクエストレート」という意味です)には、手を付けないでください。順位を問うパネルではありません。そして、今アップロードされているダッシュボードをそのままダウンロードして、/root/gfd-table/fixed.jsonに保存し(.dashboardの本体だけ)、/root/gfd-table/08-review.mdに、R1=からR4=までの4行で、何をなぜ変えたかを、それぞれ30文字以上で書いてください。

瞬間値クエリをformat: tableで受け取ると、列はTime・handler・Valueの3つです。ある瞬間の一覧に、時刻の列は何の情報も与えないので、隠します。ファイルと画面が食い違わないようにするには、直したあとにもう一度ダウンロードする必要があります。記録の4行は、それぞれ、なぜテーブルに変えたのか、なぜ瞬間値クエリなのか、どの変換をなぜ付けたのか、どのパネルをなぜ折れ線グラフのまま残したのかを書く場所です。