Grafana メトリクスのチャート作成
概要
PromQL クエリから、Grafana データソースプロキシ経由で取得したダークテーマの Grafana スタイル PNG 折れ線グラフをレンダリングします(Prometheus への直接ネットワークアクセスは不要、Grafana SA トークンのみで十分)。手動スクリーンショットとは異なり、再現可能でスクリプト化可能です。結果を直接 Jira 課題に添付できます。
既存のパネルにグラフが表示されている場合は、まずスナップショットを試してください。 Grafana Cloud スタックはサーバーサイドレンダリングを備えているため、gcx dashboards snapshot は実際のパネルを PNG として返します。このスキルはスナップショットでは得られないもの、つまり単一のパネルで表現できない複数クエリまたは時間範囲の横断比較や、Image Renderer プラグインがなくスナップショットがエラーになるセルフホストインスタンス向けです。
事前確認
ここでの Grafana 呼び出しはすべて gcx を介して行われます。セッションごとに一度確認してください:
command -v gcx >/dev/null || { echo "インストール: brew install gcx"; exit 1; }
gcx config check || { echo "未準備: gcx login"; exit 1; }
描画前にクエリを正しく設定してください。 このスキルは渡された PromQL をそのままレンダリングします。ダッシュボードよりもここで間違ったクエリを使用すると問題です。PNG は誰も再実行しない証拠としてチケットに残り、公式な見た目になります。クエリ自体に必要な背景知識: grafana-dashboards スキルの PromQL の基礎、集計の落とし穴、分布とテールの読み取り の各セクションを参照してください。比較チャートで特に問題となる点: rate の後で集計し、その前では決して行わない。ロールアウト時にポッドごとに 2 つの系列が残る場合は両側を max by (...) でラップする。基数 2 の指数ヒストグラムに対して histogram_quantile を使わない。すべてのサブクエリに明示的な step を指定する。
使用するタイミング
- 2 つ以上の系列を比較する場合: バージョン A vs B、カナリア vs コントロール、変更前後。
- 証拠を Jira チケット、MR、インシデントレポートに添付する場合。
- Grafana パネルレンダリングが失敗する場合(
gcx dashboards snapshotがエラーになる: そのセルフホストコンテキストに Image Renderer がない)。
使用しない場合: 対話的な探索(Grafana を使用)、単一値/テーブルデータ、Grafana Cloud 上の既存パネルのスクリーンショット(gcx dashboards snapshot)。
セットアップ(一度だけ)
matplotlib が必要です。ない場合は、分離された venv を使用してください(システム Python を汚染しない):
python3 -m venv ${CLAUDE_SKILL_DIR}/.venv
${CLAUDE_SKILL_DIR}/.venv/bin/pip install -q matplotlib
クイックリファレンス
| 必要なもの | フラグ |
|---|---|
| データソース | --datasource-uid(gcx datasources list またはパネルクエリで確認) |
| クエリ | --expr 'PromQL' |
| 時間ウィンドウ | --start now-6h --end now --step 60 |
| 系列ラベルソース | --legend-key instance(デフォルト、任意のメトリックラベル) |
| 見やすい名前 | --rename '{"raw-value":"ニックネーム"}' |
| 系列ごとの平均/最小/最大 | 保存後に標準出力に表示(追加クエリ不要) |
| ピークのコールアウト | --annotate-max "テキスト" |
| 使用する Grafana | --grafana-url https://<host>: そのホストをサーバーに持つ gcx コンテキストを使用(デフォルト: gcx の現在のコンテキスト) |
| 使用する gcx コンテキスト | --gcx-context <名前>(デフォルトは $GCX_CONTEXT); URL なしで命名されたインスタンスの場合、gcx config list-contexts から選択 |
| Jira に添付 | --attach-jira ABC-123(以下の環境変数と Workflow の承認ゲートを参照) |
環境
ハードコードされているものはありません: ホストもアドレスもありません。シェルプロファイルで設定してください。
| 変数 | 必要になる場面 | 備考 |
|---|---|---|
GRAFANA_URL + GRAFANA_TOKEN | 静的トークン | トークンは GRAFANA_URL のホストにのみ送信されます(その後は GRAFANA_SERVICE_ACCOUNT_TOKEN、GTOK) |
GCX_CONTEXT | gcx | 強制する gcx コンテキスト、--gcx-context と同じ |
JIRA_API_TOKEN JIRA_EMAIL JIRA_BASE | --attach-jira のみ | 3 つすべて必要、デフォルトなし |
解決順序はすべての Grafana スキルで同一です: --token; --gcx-context / $GCX_CONTEXT; --grafana-url($GRAFANA_URL のホストに対する環境トークン、そうでなければそのホストを提供する gcx コンテキスト、そうでなければ実行する gcx login を表示して終了); gcx の現在のコンテキスト; gcx がない場合の環境トークン。gcx を通じて、独自の OAuth 更新が適用され、このスクリプトはクレデンシャルを読み取ったりキャッシュしたりしません。リゾルバーは各スキルに意図的に重複して含まれており、単独でインストールされても機能します。
ワークフロー
- ダッシュボードからデータソース UID と PromQL を取得する(
gcx api /api/dashboards/uid/<uid>、panels[*].targets[*].exprを読む)か、自分でクエリを記述します。 - スクリプトを実行します(venv python 経由)。色は系列順に Grafana パレットから自動割り当てされます。凡例には系列ごとの平均/最大値が表示されます。
- 共有する前に PNG を読み返して目視確認します。
- オプションで
--attach-jiraを使用して Jira に添付します。これはチーム全体から見えるトラッカー書き込みです。まずticket-conventionsスキルの承認ゲートに従ってください(チケット ID と PNG を表示し、明示的な同意を待つ)。アップロードに失敗すると非ゼロで終了します。
例(正準例: HAProxy 3.2 vs 2.7 ノードメモリ)
VENV=${CLAUDE_SKILL_DIR}/.venv/bin/python
SKILL=${CLAUDE_SKILL_DIR}
export JIRA_API_TOKEN=$(zsh -l -c 'echo $JIRA_API_TOKEN') # 添付する場合のみ
export [email protected] JIRA_BASE=https://example.atlassian.net
DS_UID=abc123XYZ # `gcx datasources list` の結果
$VENV $SKILL/plot_grafana.py \
--datasource-uid $DS_UID \
--expr '(1 - (node_memory_MemAvailable_bytes{instance=~"lb-edge-dc1-(1|4)"} / node_memory_MemTotal_bytes{instance=~"lb-edge-dc1-(1|4)"})) * 100' \
--start now-6h --step 60 \
--title "lb-edge - ノードメモリ使用率 % · 3.2 vs 2.7 (dc1, 過去6h)" \
--ylabel "メモリ使用率 %" --ymin 0 --ymax 45 \
--rename '{"lb-edge-dc1-1":"HAProxy 3.2.20 (dc1-1)","lb-edge-dc1-4":"HAProxy 2.7.11 (dc1-4, control)"}' \
--annotate-max "リロード: 新旧ワーカー共存 → ノードメモリ約2倍" \
--grafana-url https://grafana.example.com \
--out ./mem-3.2-vs-2.7.png \
--attach-jira ABC-123
よくある間違い
- 誰も確認していないクエリからチャートを描画した → 上記の PromQL ポインタを参照。もっともらしい間違った数値がエラーではなく障害モードです。
- プロキシから 401 → 静的トークンの場合、そのホストに属していません。gcx 経由の場合、リフレッシュトークンが期限切れです(約月単位)。
gcx login <context>を実行してください。 - システムの
python3を使用している →ModuleNotFoundError: matplotlib。venv python を使用してください。 - 複数期待しているのに空または1本のフラットな線 →
--exprの正規表現が単一の系列に一致しています。ラベルマッチャーを広げてください。 - 系列名が「series」のまま / すべて「series」 →
--legend-keyがメトリックに存在しないラベルを指しています。存在するラベルを選んでください(生のクエリ結果を確認)。 - 凡例名に
:9100(または任意の:ポート番号)が含まれる → 派生系列名から自動的に削除されるため、--renameはクリーンなホスト名を対象にしてください(例:lb-edge-dc1-1、lb-edge-dc1-1:9100ではない)。両方の形式をリストする必要はありません。 - 相対時間は 1 つの数値と 1 つの単位、s/m/h/d(
now-90m、now-6h、now-2d)。複合(now-1h30m)、週(now-1w)、丸め(now/d)はサポートされていません。変換してください(now-90m、now-7d)。