スキップしてメイン コンテンツに移動

Grafana で「あれ、どうやるんだっけ?」を思い出すためのヒント集

Raspberry Piのデータが全部飛んでゼロから構築しなおすことになったのだが、数年ぶりにやったらダッシュボードの作り方を忘れていて結構詰まった。

二度と調べ直したくないので備忘録を書き起こす。

Grafanaのバージョンは11.0.0。Debian用の公式手順に沿って入れただけで特に工夫はしていない。


パネルタイトルを非表示にしたい (Time series)

Time series(通常のグラフ表示)であればPanel optionsのTitleを空にすることで実現できる

ちなみに、完全に空にせずスペース1個だけ入れとくと「タイトルは非表示にしつつタイトルの表示スペースだけは残す」みたいな感じになり、表示位置の微調整に使えなくもない。


ここをクリアする


変更前


変更後
左上の「瞬時電力」が消えている


パネルタイトルを非表示にしたい (Stat)

Statパネルの場合はTitleを空にすることができない。その代わりに Stat styles > Text mode で Value を選ぶことで同じ結果を実現できる。

Grafanaダッシュボード上で「動的に書き換わる文字列」を表示する方法 でもStatパネルを使っており、このTipsが適用できる。


ここ


変更前

変更後


クエリに書く last() とか mean() とか fill() がわからない

基本はSQLを覚えて、あとはあれこれ触った反応を見ながら感じ取るとよい。自分も体系だって知識を入れたわけではないので以下の記述は間違っている可能性がある。ひとまず自分がしている理解をここに書いておく。



last や mean はどちらも代表値を選出するための方法を指定するものである

  • 前提として、Grafanaは表示対象に設定した期間内の全レコードをグラフに表示しない。これが標準の動作である
    • あまり時間解像度を細かくしても大雑把なグラフ表示では視認できない
    • 現在の縮尺に合わせて表示するデータポイント数を増減させるのが効率的なはず
  • すると縮尺によっては複数のレコードをまとめて表示することになる
    • グラフに表示するのは、まとめられた内から選出する代表値1つだけになる
    • last は最後のデータを選ぶ。mean は平均値を代表として出す
    • 他に max や sum などもある
  • ちなみにlastの「最後のデータ」とは必ずしも「時系列における最新」を意味しない
    • これはSQLで取得したデータの最終行というふうに理解するのが正しい
    • なので last(order by time asc) と first(order by time desc) は等価になる


fill はデータが存在しない区間をどう処理するかを規定する。

  • データ点はあらゆる時間に存在するわけではない
    • 1分に1回の計測値であれば、少なくとも59秒間はデータがない区間が発生する
    • 計測が失敗して部分的に歯抜けになることも考慮したい
  • データ点がない期間を愚直にグラフ表示すると普通に読みづらい
    • なので欠損があっても視覚的には間を埋める処理を書くことになる
  • データ補完することで、データポイントのタイミングがズレている別々グラフ同士で、算術演算ができるようになる
    • ……のだと思われる。自分は使ったことがない


fill(0) はデータがない区間の値を0であるとして補完する。例は5分に1回の計測データである。

fill(null) はデータがない区間をnullとして処理する。グラフの表示はとびとびになる(表示設定でなめらかにつなぐことは可能)。


fill(previous) は、データが存在しない時間帯はその直前の値と同じであるとみなす。グラフは階段状になる。


fill(liner) は前の値と次の値が直線でつながるように補完をかける。


fill(none) はnoneという値で埋める(のだと思う)。

noneの場合にどのような表示とするかはグラフ側の表示設定に委ねられている。Graph styles > Line interpolation あたりの設定が反映される。


fillを行わないこともできる。fill() の右にある×を押せばそのように設定される。挙動としては fill(null) に似る。

この場合データ補完がなくなるが、その状態でもグラフ表示設定の方でなめらかな線をつなぐことはできる。Graph styles > Connect null values を変更するとわかりやすい。


別々の単位をもつ値を1つのグラフに表示したい(たとえば、気温と湿度)

Time seriesのパネルで以下のようなものを実現する方法。


まず2つの系列をDBから取得してくる。これは以下のようにクエリを複数書くだけ。



クエリ「A」に適用する表示スタイルをStandard optionsで設定する。

例では単位(℃)とグラフ色(黄色)を設定している。


Overridesのタブに入る。クエリ「B」で変更したい項目をここで指定する。

例ではFields with nameでクエリ「B: 湿度」を指定し、単位(℃→%)とグラフ色(黄色→水色)を上書きしている。


グラフの表示範囲とかもクエリごとに指定できる。たとえば「気温の表示範囲は0-40だけど、湿度の表示範囲は20-100にしよう」みたいなことが実現できる。


特定のパネルだけ表示時間幅を変更したい

ダッシュボード全体の表示時間幅と独立して、パネル単位で時間幅を変更するための方法。



設定方法は、クエリを書くところでQuery optionsを押す

知らないと気付けない、悪いUI

押したところが展開されるのでRelative timeに設定したい表示時間幅を入れる。


下にはTime shift(時間ずらし)機能もある。例えばここに1hと入れると現在ではなく1時間分過去のグラフが表示される。


値に応じてグラフ色を変更する

例はStatパネル。



Thresholdsの項目で色変更の閾値を書くことができる。


ここでは「現在値が4500以上、3000以上、500以上、それ以外」で表示色を分岐させている。


別のフィールドの値に応じてグラフ色を変更する

実現したいのは以下のような表示である。

2つのパネルがあり、どちらも同じルールで色を変更する。


最大降水確率が60%のケース

同じく40%のケース

元データは以下のようになっている

display_text1   display_text2   max_chance_percent   risk_color
--------        --------        -------------        -------------
18時-24時: 20%   翌0時-6時: 40%    40                   #fade2a

パネルはStatビジュアライゼーションで、表示する値はdisplay_text1および2の「18時-24時: 20%」といった文字列だ。

ここでやりたいことは直近12時間における最大降水確率を元にした色分けである。降らなそうであればグリーン、降りそうであればイエローやオレンジになる。


max_chance_percent フィールドに対してThresholdsを設定すれば実現できそうに思える。しかし残念ながらStatでは「Thresholdsは表示する値に対してのみ設定可能」という制約がある。

そしてThresholdsは数値の大小比較であるから、"18時-24時: 20%" という文字列に対してこれを指定するということはできない。


この要件はGrafana単体で実現するのは難しい(Pluginを探せば可能かもしれないが、バージョンアップ時に足かせとなりうる)。

プログラム側で値を元に色を判定し、それを元データに含めてしまう方がなにかと融通が効く。それが risk_color フィールドである。

riskColor = '#73bf69' if maxRainChancePercent < 30 
       else '#fade2a' if maxRainChancePercent < 60 
       else '#ff7330'


プログラム側で色を指定し元データに含めたら、Grafana側は2つのクエリでA 降水確率とB リスク色を取得する。


次にTransform dataタブを開いて、Config from query results を設定する。


フォームの意味をざっくり説明をすると

  • 上3行
    • クエリBの結果を、クエリA 降水確率の表示オプションとして使う
    • ※ここで選ばれたクエリBは、グラフ表示の対象値としては使えなくなる
  • 下3行
    • クエリBの結果のうち「リスク色」の値を表示オプション Color の値として適用する
      • 複数行取得された場合は、NULLでない最新の値を採用する
    • クエリBの結果の「Time」フィールドは特に使わないので無視する

という感じになっている。これで「直近12時間の最大降水確率によって色が変わる2つのパネル」を実現できる。


ちなみにクエリBでConfig用の結果を複数行取得させ、行ごとに2つのフィールドの値をValue mappingsやThresholdsのペアに登録させる…… といったこともできる。ユースケースによってはこの方が合致することもあろう。

この機能は言葉での説明だけでは理解が難しいので、公式のデモダッシュボードをいじって把握するのがよいと思う。

参考:https://community.grafana.com/t/dynamic-thresholds-from-queried-fields/89517


値そのものでなく状態変化の内容で可視化する

実現したいのは以下のようなパネル(家族の在宅状況)である。


元データは以下の形式(スマホのWi-fi MACアドレスがLAN配下にいるかどうかを記録している)

time                    in_house    member
----                    --------    ------
2024-05-28T07:35:28Z    0           Alice
2024-05-28T07:35:28Z    1           Bob
2024-05-28T07:36:28Z    0           Alice
2024-05-28T07:36:28Z    1           Bob
2024-05-28T07:37:12Z    1           Alice
2024-05-28T07:37:12Z    1           Bob
2024-05-28T07:38:11Z    1           Alice
2024-05-28T07:38:11Z    1           Bob
2024-05-28T07:39:12Z    1           Alice
2024-05-28T07:39:12Z    1           Bob


VisualizationにはState timelineを選択し、クエリは以下のように書く


元データが1分ごとなのでGroupByも1分でまとめている(これをやらないと1分のうち59秒間はデータなし表示になってしまう)。

次にValue mappingsを書く。


Color schemeはSingle colorを選択。

Thresholdsを書くとうまくいかないので空にしておく。

State timelineでMerge equal consecutive values(同じ値が連続したら)を有効にし、Show valuesをAlwaysあたりにすると、グラフ内に「在宅」「外出」といったラベルを表示できる。


ここの表示をNeverにして、代わりにLegendの方を有効にしてもよい。その場合はグラフ外に色分けの凡例が表示される。


関連記事


コメント