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

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

六か月間、一度も赤くならなかったダッシュボード

TT Labで続きを見る

目標

既定のしきい値が私たちの指標で何を意味するのかを計算したうえで、しきい値をSLOから引っ張ってきます。そして、絶対値のしきい値とパーセンテージのしきい値を使い分け、色だけでなく文字でも語らせるようにし、パネルのしきい値とすでにあるアラートのしきい値を、1つの値から引っ張ってくるように直します。

なぜ重要なのか

ダッシュボードの色は、判断を肩代わりします。だから、色に根拠がなければ、判断にも根拠がありません。Grafanaの既定のしきい値は80で赤になりますが、0と1のあいだで出る割合のパネルにその値が残っていると、そのパネルは何があっても緑です。説明できるしきい値は、ユーザーにした約束から計算されたものだけです。30日の可用性目標がエラーバジェットを決め、エラーバジェットがしきい値を決めます。ここにさらに2つが加わります。色だけで語る画面は、色覚特性のある人や白黒のキャプチャの前では何も語れないので、値と文字が一緒にある必要があります。また、パネルのしきい値とアラートのしきい値が別のファイルに手で書かれていると、いつか必ずずれて、「画面は赤いのに誰にもページが飛ばない」時間が生まれます。

ステップ

  1. lab-start-grafanaでGrafanaを起動し、/root/gfd-thresholds/dash.jsonにuidがgfd-threshのダッシュボードを作成してアップロードしてください。パネルは1つで、idは1、タイプはstat、タイトルは5xx 비율 (기본 문턱 그대로 - 비교용)(韓国語のタイトルは「5xx割合(既定のしきい値のまま、比較用)」という意味です)、クエリはsum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h]))、単位の識別子は0..1の割合のほうです。しきい値はGrafanaの既定値のままにしておきます。ベースが緑、80から赤、方式は絶対値です。そして/root/gfd-thresholds/01-default.txtに5行書いてください。now=<지금 이 쿼리가 내는 값>、red_at=<빨강 문턱 값>、max_possible=<이 쿼리가 낼 수 있는 가장 큰 값>、reachable=<빨강에 닿을 수 있으면 yes, 없으면 no>、reason=<왜 그런지 40자 이상>です(プレースホルダーは順に、今このクエリが出す値、赤のしきい値、このクエリが出しうる最大の値、赤に届くならyes・届かないならno、そうなる理由(40文字以上)です)。
  2. /opt/lab/gfd/gfd-thresholds/slo.ymlに、30日の可用性目標が書かれています。エラーバジェットは、1からその目標を引いた値です。同じダッシュボードに、idが2のstatパネルを追加してください。タイトルは5xx 비율 (SLO 문턱)(韓国語のタイトルは「5xx割合(SLOのしきい値)」という意味です)、クエリはパネル1と同じで、単位も同じです。しきい値は絶対値方式で3段階です。ベースはgreen、エラーバジェットの値で#EAB839、その2倍でredにします。そして/root/gfd-thresholds/02-slo.txtに5行書いてください。budget=<오류 예산>、warn=<노랑 문턱>、crit=<빨강 문턱>、now=<지금 값>、color_now=<지금 값의 색>です(プレースホルダーは順に、エラーバジェット、黄のしきい値、赤のしきい値、今の値、今の値の色です)。色は、パネルに書いた色の文字列をそのまま書きます。
  3. 同じダッシュボードに、idが3のgaugeパネルを追加してください。タイトルは남은 디스크(韓国語のタイトルは「残りディスク」という意味です)、クエリはnode_filesystem_avail_bytes{job="node",mountpoint="/data"}、単位は1024で縮めるバイトです。軸の最小値は0、最大値は/opt/lab/gfd/gfd-thresholds/slo.ymlのdata_volume_bytesの値です。しきい値はパーセンテージ方式(thresholds.modeがpercentage)で、3段階です。ベースがred、20で#EAB839、40でgreenにします。そして/root/gfd-thresholds/03-percentage.txtに4行書いてください。avail=<지금 남은 바이트>、max=<최댓값>、pct=<남은 비율을 퍼센트로, 소수 두 자리>、color=<지금 색>です(プレースホルダーは順に、今の残りバイト数、最大値、残りの割合をパーセントで小数第2位まで、今の色です)。
  4. パネル2に、値マッピングを3つ追加してください。すべてrangeルールで、順に、0から黄のしきい値までは정상(韓国語で「正常」を意味する語です)、黄のしきい値から赤のしきい値までは예산 소진 중(韓国語で「バジェット消費中」を意味する語です)、赤のしきい値から1までは사고(韓国語で「事故」を意味する語です)です。そして、このパネルのoptions.textModeをvalue_and_nameにして、数字と名前が一緒に表示されるようにしてください。/root/gfd-thresholds/04-text.txtに2行書いてください。now=<지금 값>、label=<지금 값에 걸리는 글자>です(プレースホルダーは順に、今の値、今の値が当てはまる文字です)。
  5. /root/gfd-thresholds/color.pyを作成してください。python3 color.py <값> [패널 id]で呼び出すと(プレースホルダーは順に、値とパネルのidです)、Grafanaからそのパネルのしきい値を読み取り、その値がどの色になるかを色の文字列1行で出力します(パネルidの既定値は2です)。ルールはGrafanaと同じです。段階を値の順に並べ替え、値がその段階以上である最後の段階の色を選び、値が空の先頭の段階はマイナス無限大として扱います。そして、そのツールで/root/gfd-thresholds/05-boundary.tsvを作成してください。ヘッダー行なしで6行、各行はタブで区切った2列<값> <색>で(プレースホルダーは順に、値と色です)、値は順に0・0.0049・0.005・0.0051・0.01・0.02です。
  6. /opt/lab/gfd/gfd-thresholds/alerts.ymlは、すでに本番に上がっているアラートルールです。このルールのしきい値とパネル2の赤のしきい値が、今は互いに違っています。2つの数字を1か所から引っ張ってくるように直してください。/root/gfd-thresholds/thresholds.envにWARN=<노랑 문턱>とCRIT=<빨강 문턱>の2行を書き(値はステップ2でSLOから計算したものです。プレースホルダーは順に、黄のしきい値と赤のしきい値です)、そのファイルのCRITの値でルールのしきい値を書き換えて、/root/gfd-thresholds/alerts.ymlに保存します。ルールのそれ以外の部分はそのままにします。そして/root/gfd-thresholds/06-match.tsvに、ヘッダー行なしで3行、各行はタブで区切った2列で、before・after・panelを順に書いてください。元のルールのしきい値、直したルールのしきい値、パネルの赤のしきい値です。
  7. 同じダッシュボードに、idが4のtimeseriesパネルを追加してください。タイトルはp99 응답 시간(韓国語のタイトルは「p99応答時間」という意味です)、クエリはhistogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h])))、単位は秒です。しきい値は絶対値方式の2段階で、ベースはgreen、/opt/lab/gfd/gfd-thresholds/slo.ymlのlatency_p99_target_secondsの値でredにします。そして/root/gfd-thresholds/07-latency.txtに4行書いてください。p99_now=<지금 값>、threshold_s=<초로 적은 문턱>、threshold_ms=<같은 문턱을 밀리초로 환산한 값>、color=<지금 색>です(プレースホルダーは順に、今の値、秒で書いたしきい値、同じしきい値をミリ秒に換算した値、今の色です)。
  8. /opt/lab/gfd/gfd-thresholds/broken.jsonは、本番から取り出してきたダッシュボードです(uidはgfd-thresh-fix)。4つのパネルすべてに、しきい値の欠陥があります。パネル1は、既定のしきい値がそのまま残っていて届かない状態です(赤をSLOのcritの値まで下げます)。パネル2は、パーセンテージ方式なのに最小値・最大値がありません(0とdata_volume_bytesを入れます)。パネル3は、大きいほど良い指標なのに段階の順序が逆になっています(ベースが赤で、上が緑でなければなりません)。パネル4は、秒単位のパネルに、ミリ秒の数字がしきい値として入っています(latency_p99_target_secondsに直します)。直したダッシュボードをuidgfd-thresh-fixでアップロードし、/root/gfd-thresholds/08-report.tsvに、ヘッダー行なしで4行、各行はタブで区切った3列<패널 id> <결함 코드> <무엇이 틀렸었나, 20자 이상이고 숫자를 하나 이상 포함>を書いてください(プレースホルダーは順に、パネルのid、欠陥コード、何が間違っていたか(20文字以上で、数字を1つ以上含む)です)。欠陥コードはunreachable・no-minmax・direction・scaleのいずれかで、行はパネルidの順です。

参考

既定のしきい値80が私たちの指標で何を意味するのかを問う

lab-start-grafanaでGrafanaを起動し、/root/gfd-thresholds/dash.jsonにuidがgfd-threshのダッシュボードを作成してアップロードしてください。パネルは1つで、idは1、タイプはstat、タイトルは5xx 비율 (기본 문턱 그대로 - 비교용)(韓国語のタイトルは「5xx割合(既定のしきい値のまま、比較用)」という意味です)、クエリはsum(rate(http_requests_total{job="shop-api",status=~"5.."}[1h])) / sum(rate(http_requests_total{job="shop-api"}[1h]))、単位の識別子は0..1の割合のほうです。しきい値はGrafanaの既定値のままにしておきます。ベースが緑、80から赤、方式は絶対値です。そして/root/gfd-thresholds/01-default.txtに5行書いてください。now=<지금 이 쿼리가 내는 값>、red_at=<빨강 문턱 값>、max_possible=<이 쿼리가 낼 수 있는 가장 큰 값>、reachable=<빨강에 닿을 수 있으면 yes, 없으면 no>、reason=<왜 그런지 40자 이상>です(プレースホルダーは順に、今このクエリが出す値、赤のしきい値、このクエリが出しうる最大の値、赤に届くならyes・届かないならno、そうなる理由(40文字以上)です)。

既定のしきい値は{"mode": "absolute", "steps": [{"color": "green", "value": null}, {"color": "red", "value": 80}]}です。先頭の段階のvalueがnullになっているものがベースで、マイナス無限大を意味します。このクエリは割合なので、分子が分母と等しくなるときが最大値です。その値と80を比べてみてください。

しきい値を目標から引っ張ってくる

/opt/lab/gfd/gfd-thresholds/slo.ymlに、30日の可用性目標が書かれています。エラーバジェットは、1からその目標を引いた値です。同じダッシュボードに、idが2のstatパネルを追加してください。タイトルは5xx 비율 (SLO 문턱)(韓国語のタイトルは「5xx割合(SLOのしきい値)」という意味です)、クエリはパネル1と同じで、単位も同じです。しきい値は絶対値方式で3段階です。ベースはgreen、エラーバジェットの値で#EAB839、その2倍でredにします。そして/root/gfd-thresholds/02-slo.txtに5行書いてください。budget=<오류 예산>、warn=<노랑 문턱>、crit=<빨강 문턱>、now=<지금 값>、color_now=<지금 값의 색>です(プレースホルダーは順に、エラーバジェット、黄のしきい値、赤のしきい値、今の値、今の値の色です)。色は、パネルに書いた色の文字列をそのまま書きます。

目標が0.995なら、エラーバジェットは0.005です。色は手で選ばず、ルールで決めてください。Grafanaはしきい値を値の順に並べ替えたあと、「値がそのしきい値以上」である最後の段階の色を選びます。境界は含みます。今の値は、promqやデータソースプロキシでクエリを投げて得ます。

絶対値のしきい値とパーセンテージのしきい値は、別の問いに答える

同じダッシュボードに、idが3のgaugeパネルを追加してください。タイトルは남은 디스크(韓国語のタイトルは「残りディスク」という意味です)、クエリはnode_filesystem_avail_bytes{job="node",mountpoint="/data"}、単位は1024で縮めるバイトです。軸の最小値は0、最大値は/opt/lab/gfd/gfd-thresholds/slo.ymlのdata_volume_bytesの値です。しきい値はパーセンテージ方式(thresholds.modeがpercentage)で、3段階です。ベースがred、20で#EAB839、40でgreenにします。そして/root/gfd-thresholds/03-percentage.txtに4行書いてください。avail=<지금 남은 바이트>、max=<최댓값>、pct=<남은 비율을 퍼센트로, 소수 두 자리>、color=<지금 색>です(プレースホルダーは順に、今の残りバイト数、最大値、残りの割合をパーセントで小数第2位まで、今の色です)。

パーセンテージのしきい値は、値そのものではなく、「最小値と最大値のあいだのどこにあるか」をしきい値と比べます。そのため、最大値を書かないと、Grafanaが画面にあるデータから推測し、時間範囲を変えるたびに色が変わります。残り容量は大きいほど良い値なので、段階の順序が逆になります。ベースが赤です。

色だけで語らない

パネル2に、値マッピングを3つ追加してください。すべてrangeルールで、順に、0から黄のしきい値までは정상(韓国語で「正常」を意味する語です)、黄のしきい値から赤のしきい値までは예산 소진 중(韓国語で「バジェット消費中」を意味する語です)、赤のしきい値から1までは사고(韓国語で「事故」を意味する語です)です。そして、このパネルのoptions.textModeをvalue_and_nameにして、数字と名前が一緒に表示されるようにしてください。/root/gfd-thresholds/04-text.txtに2行書いてください。now=<지금 값>、label=<지금 값에 걸리는 글자>です(プレースホルダーは順に、今の値、今の値が当てはまる文字です)。

値マッピングの1つ分は、{"type": "range", "options": {"from": 0, "to": 0.005, "result": {"text": "정상", "index": 0}}}という形です(韓国語の文字列は「正常」という意味です)。マッピングは上から順に見て最初に当てはまったルールが勝ち、両端をどちらも含むので、境界値は前のルールが取ります。色覚特性のある人には赤と緑が区別できない、というのがこのステップの理由です。

しきい値の順序と境界を、実際の値で確認する

/root/gfd-thresholds/color.pyを作成してください。python3 color.py <값> [패널 id]で呼び出すと(プレースホルダーは順に、値とパネルのidです)、Grafanaからそのパネルのしきい値を読み取り、その値がどの色になるかを色の文字列1行で出力します(パネルidの既定値は2です)。ルールはGrafanaと同じです。段階を値の順に並べ替え、値がその段階以上である最後の段階の色を選び、値が空の先頭の段階はマイナス無限大として扱います。そして、そのツールで/root/gfd-thresholds/05-boundary.tsvを作成してください。ヘッダー行なしで6行、各行はタブで区切った2列<값> <색>で(プレースホルダーは順に、値と色です)、値は順に0・0.0049・0.005・0.0051・0.01・0.02です。

ダッシュボードはcurl -s http://127.0.0.1:3000/api/dashboards/uid/gfd-threshで取得し、.dashboard.panels[] | select(.id == 2) | .fieldConfig.defaults.thresholds.stepsから段階を取り出します。使うのは標準ライブラリだけです(json、sys、urllib.request)。境界値0.005が前の色になるのか、後ろの色になるのかが、このステップの核心です。

画面は赤いのに誰にもページが飛ばない状態をなくす

/opt/lab/gfd/gfd-thresholds/alerts.ymlは、すでに本番に上がっているアラートルールです。このルールのしきい値とパネル2の赤のしきい値が、今は互いに違っています。2つの数字を1か所から引っ張ってくるように直してください。/root/gfd-thresholds/thresholds.envにWARN=<노랑 문턱>とCRIT=<빨강 문턱>の2行を書き(値はステップ2でSLOから計算したものです。プレースホルダーは順に、黄のしきい値と赤のしきい値です)、そのファイルのCRITの値でルールのしきい値を書き換えて、/root/gfd-thresholds/alerts.ymlに保存します。ルールのそれ以外の部分はそのままにします。そして/root/gfd-thresholds/06-match.tsvに、ヘッダー行なしで3行、各行はタブで区切った2列で、before・after・panelを順に書いてください。元のルールのしきい値、直したルールのしきい値、パネルの赤のしきい値です。

元のファイルを作業ディレクトリにコピーしてから、数字だけを書き換えれば済みます。ルールファイルの文法はpromtool check rules /root/gfd-thresholds/alerts.ymlで確認してください。採点ツールも同じコマンドを使います。アラートルールを新しく作る方法は、ここでは扱いません。このステップで見るのは、2つの数字が同じかどうか、ただ1つです。

応用①: レイテンシのしきい値はパネルの単位に合わせる

同じダッシュボードに、idが4のtimeseriesパネルを追加してください。タイトルはp99 응답 시간(韓国語のタイトルは「p99応答時間」という意味です)、クエリはhistogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job="shop-api"}[6h])))、単位は秒です。しきい値は絶対値方式の2段階で、ベースはgreen、/opt/lab/gfd/gfd-thresholds/slo.ymlのlatency_p99_target_secondsの値でredにします。そして/root/gfd-thresholds/07-latency.txtに4行書いてください。p99_now=<지금 값>、threshold_s=<초로 적은 문턱>、threshold_ms=<같은 문턱을 밀리초로 환산한 값>、color=<지금 색>です(プレースホルダーは順に、今の値、秒で書いたしきい値、同じしきい値をミリ秒に換算した値、今の色です)。

しきい値は、パネルが描く値と同じ単位で書く必要があります。このパネルの値は秒で出るので、目標が1秒ならしきい値は1であって、1000ではありません。ミリ秒で書くと、そのパネルは絶対に赤くなりません。ステップ1で見たのと同じ種類の事故です。色は、ステップ5で作ったツールにパネルidを渡せば求められます。

応用②: 本番ダッシュボードのしきい値の欠陥をすべて直して提出する

/opt/lab/gfd/gfd-thresholds/broken.jsonは、本番から取り出してきたダッシュボードです(uidはgfd-thresh-fix)。4つのパネルすべてに、しきい値の欠陥があります。パネル1は、既定のしきい値がそのまま残っていて届かない状態です(赤をSLOのcritの値まで下げます)。パネル2は、パーセンテージ方式なのに最小値・最大値がありません(0とdata_volume_bytesを入れます)。パネル3は、大きいほど良い指標なのに段階の順序が逆になっています(ベースが赤で、上が緑でなければなりません)。パネル4は、秒単位のパネルに、ミリ秒の数字がしきい値として入っています(latency_p99_target_secondsに直します)。直したダッシュボードをuidgfd-thresh-fixでアップロードし、/root/gfd-thresholds/08-report.tsvに、ヘッダー行なしで4行、各行はタブで区切った3列<패널 id> <결함 코드> <무엇이 틀렸었나, 20자 이상이고 숫자를 하나 이상 포함>を書いてください(プレースホルダーは順に、パネルのid、欠陥コード、何が間違っていたか(20文字以上で、数字を1つ以上含む)です)。欠陥コードはunreachable・no-minmax・direction・scaleのいずれかで、行はパネルidの順です。

cp /opt/lab/gfd/gfd-thresholds/broken.json /root/gfd-thresholds/fixed.jsonでコピーを作り、直してアップロードすれば済みます。色の文字列はそのままにして、値と順序だけを直せばよいパネルもあれば、色の位置を入れ替える必要があるパネルもあります。直したあとは、ステップ5のツールにいくつか値を入れてみると、向きが合っているかがすぐにわかります。パネルidを2つ目の引数として渡せばよいです(ただし、そのツールはuidがgfd-threshのダッシュボードを見ます)。