Grafanaのパネルが「No data」で埋まると、監視基盤が止まったように見えます。ですが、可視化が空であることと、テレメトリの配管が止まったことは同じではありません。
今回の監視スタックでは、OpenTelemetry Collectorが受信したメトリクスは40,020点、spanは20件でした。failedとrefusedはいずれも0です。Prometheusのターゲットは2系統ともupで、GPUノード2台の使用率は58%と98%、最終サンプルは約15秒前でした。Tempoもspanを21件受信しています。
それでもGrafanaの収集ヘルス表示は「No data」でした。調べると、保存済みダッシュボードは0件でした。データソースは設定され、配管も動いていたのに、見るためのパネル集合が保存されていなかったのです。
「No data」は診断名ではなく症状名です。まずは、何が無いのかを順番に分けます。
Collectorの受信カウンタから確認する
自宅ラボの監視を運用していて、障害なのか表示だけの問題なのかを短時間で判断したい人にとって、最初の判断は「Grafanaが赤いか」ではありません。送信元からCollectorまで届いているかです。
受信の生死は、たとえば次のようなPromQLで確認します。
rate(otelcol_receiver_accepted_metric_points[5m])
拒否の有無は、次の形です。
rate(otelcol_receiver_refused_metric_points[5m])
acceptedが増えており、refusedやfailedが増えていなければ、少なくとも「そもそも送っていない」「Collectorが受け取れずに捨てている」という候補は大きく後退します。今回もこの時点で、配管そのものは健全と判断できました。
OpenTelemetry Collectorを最小構成で立ち上げ、意図的に壊して観測する基本は、OpenTelemetry Collectorで「流れないtelemetry」を作って観測するにまとめています。今回はその次の段階、受信できているのに表示できないケースです。
送信・受信・変換・保存・表示の順に切り分ける
| 候補原因 | 確認するもの | 切り分けの目安 |
|---|---|---|
| そもそも送っていない | acceptedの増加 | 受信カウンタが増えなければ、送信元からCollectorまでを確認する |
| 送ったがCollectorで拒否・失敗している | refused / failedの増加 | 値が増えるなら、受信設定や送信形式を疑う |
| 受信できているが、クエリ名が違う | Prometheusに存在する実メトリクス名 | 推測した名前ではなく、実在する名前に照合する |
| 配管もクエリも正常だが、ダッシュボードが無い | 保存済みダッシュボードとUID | 期待するパネル集合が保存・配備されているか確認する |
この順序は、受信カウンタ → メトリクス名 → ダッシュボードです。先にパネル設定を何時間も眺めるより、accepted / refused / failedを見た方が速く状況を絞れます。
Prometheusの実在メトリクス名を確認する
もう一つの原因は、PromQLが存在しない名前を参照していたことでした。この環境のCollectorでは、受信カウンタはotelcol_receiver_accepted_metric_pointsでした。
_totalが付く前提でクエリを組むと、存在しない系列を参照することがあります。たとえばotelcol_exporter_send_failed_metric_points_totalのような名前を当然のように使うと、配管が正常でも「No data」になります。
_totalの有無は、Collectorのバージョンや公開されるスキーマに依存します。名前を見慣れた形式から補完せず、Prometheus側で現在存在するメトリクス名を列挙して照合するのが安全です。
これはログでも似た形で起こります。届いているはずのデータが検索や画面に出ないときの観測手順は、Loki+Promtailを家庭ラボに入れる前に「ログが流れない」失敗を作って観測するも参考になります。
optional系列はor vector(0)で0表示する

失敗数や拒否数は、無いことが正常な系列です。しかしPrometheusでは、値が0の系列が常に存在するとは限りません。素のクエリでは空の結果になり、Statパネルは「No data」と表示します。
障害なしを「データなし」と見せないため、optionalな系列はor vector(0)で包みます。
((sum(increase(otelcol_receiver_failed_metric_points[24h]))) or vector(0))
複数のoptional系列を合算する場合も、各項を先に0で包みます。
(<A> or vector(0)) + (<B> or vector(0)) + (<C> or vector(0))
受信が動いていてもアプリ由来のサンプルが古い場合は別の問題です。アプリ側の鮮度はtime() - timestamp(<app_metric>)という一般形で確認し、運用に合った閾値で監視します。
GPUが使用中に見えても処理の進捗が止まる問題については、nvidia-smiは正常なのにGPUが動かない:16時間ハングを見逃した監視の盲点で、状態と進捗を分けて見る必要を扱いました。
ダッシュボードをコードから冪等に配る
今回、Grafanaのデータソースは設定済みでしたが、保存済みダッシュボードは0件でした。修理後は、Overview、GPU、Collection Health、OTLP Pipeline Healthの4種をコード化して配備し、同じUIDへのoverwrite: trueを使って冪等に更新しました。旧UIDも同じJSONで上書きし、古いブックマークから陳腐なパネルが開かれないようにしています。
再配備後は、すべてのパネルのPromQLターゲットがデータを返しました。手動チェックでは、総系列数7,116、24時間のAI関連系列72、トレース検索ヒット1、エクスポータキューは0/1000でした。
導入範囲を決める条件
この切り分けとコード配備が向いているのは、複数のサービスやノードを見ていて、「監視が赤いが、実際に止まっているのか」をすぐ判断したい人です。ダッシュボードを再構築する機会がある、あるいは既存パネルの由来が曖昧になっている環境にも合います。
一方、メトリクスがまだ1系統だけで、まず送受信そのものを学びたい段階なら、ダッシュボードの整備を急ぐ必要はありません。最初はaccepted / refused / failedを確実に読める状態を作れば十分です。ただし、手作業で作ったパネルに重要な判断を任せるようになった時点で、再生成できる形への移行を検討します。
Grafanaより先にデータ経路を確認する
「No data」は、少なくとも四つの原因に分かれます。送っていない、Collectorに拒否・失敗された、メトリクス名が違う、そして配管は正常でもダッシュボードが保存されていない。
- ダッシュボードをコードから同じUIDで再生成できるか
- 失敗数・拒否数のようなoptional系列を、正常時に0として表示できるか
- パネルのメトリクス名を、現在のPrometheusのスキーマといつ照合したか
所長の画面が再び「No data」になっても、最初に見る場所は受信カウンタです。症状に名前を付けて終わらせず、経路を順番に確認すれば、必要以上に不安を増やさずに済みます。
この検証を回している環境
この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。
ラボ構成のまとめを見る →