Charting Grafana metrics
概述
從 PromQL 查詢渲染深色主題、Grafana 風格的 PNG 折線圖,透過 Grafana 資料來源代理獲取(因此不需要直接存取 Prometheus 網路,Grafana SA token 即可)。可重現且可腳本化,有別於手動截圖。可直接將結果附加到 Jira 問題。
如果面板已顯示該圖表,請先使用快照。 Grafana Cloud 堆疊支援伺服器端渲染,因此 gcx dashboards snapshot 會返回真實面板的 PNG。此技能用於快照無法提供的功能:跨查詢或時間範圍的並排比較(沒有單一面板能編碼),以及沒有 Image Renderer 外掛程式的自託管實例(快照會出錯)。
前置檢查
此處的每次 Grafana 呼叫都透過 gcx 進行。每次工作階段檢查一次:
command -v gcx >/dev/null || { echo "install: brew install gcx"; exit 1; }
gcx config check || { echo "not ready: gcx login"; exit 1; }
在繪製前先確保查詢正確。 此技能會渲染您提供的任何 PromQL,錯誤查詢的後果比在儀表板中更糟:PNG 會作為凍結的證據存留在工單中,無人重播,而且看起來是官方資料。
查詢本身所需的背景知識: 使用 grafana-dashboards 技能,章節 PromQL 基礎、聚合陷阱 和 解讀分佈與尾端。在比較圖表中容易出錯之處:在 rate 後聚合,且絶對不要在前;當部署讓每個 pod 產生兩個序列時,在兩邊加上 max by (...);永遠不對以 2 為底的指數直方圖使用 histogram_quantile;為每個子查詢指定明確的 step。
使用時機
- 比較 2 個以上序列:版本 A vs B、金絲雀 vs 對照、變更前/後。
- 將證據附加到 Jira 工單、合併請求或事件報告。
- 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":"Nice Name"}' |
| 每個序列的平均/最小/最大 | 儲存後輸出到 stdout(無需額外查詢) |
| 在峰值上標註 | --annotate-max "text" |
| 哪個 Grafana | --grafana-url https://<host>:使用其伺服器包含該主機的 gcx 上下文(預設:gcx 的當前上下文) |
| 哪個 gcx 上下文 | --gcx-context <name>(預設 $GCX_CONTEXT);對於沒有 URL 命名的實例,從 gcx config list-contexts 中選取 |
| 附加到 Jira | --attach-jira ABC-123(參見下方的環境變數和工作流程中的核准閘門) |
環境變數
沒有任何東西是硬編碼的:沒有主機、沒有位址。請在您的 shell 配置檔中設定這些變數。
| 變數 | 用於 | 備註 |
|---|---|---|
GRAFANA_URL + GRAFANA_TOKEN | 靜態 token | token 僅發送到 GRAFANA_URL 的主機(然後是 GRAFANA_SERVICE_ACCOUNT_TOKEN、GTOK) |
GCX_CONTEXT | gcx | 強制使用的 gcx 上下文,與 --gcx-context 相同 |
JIRA_API_TOKEN JIRA_EMAIL JIRA_BASE | 僅 --attach-jira | 全部三個,無預設值 |
解析順序,在所有 Grafana 技能中一致:--token;--gcx-context / $GCX_CONTEXT;--grafana-url($GRAFANA_URL 主機的環境 token,否則為提供該主機的 gcx 上下文,否則退出並顯示要執行的 gcx login);gcx 的當前上下文;當 gcx 缺失時的環境 token。透過 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 - node memory used % · 3.2 vs 2.7 (dc1, last 6h)" \
--ylabel "Memory used %" --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 "reload: old+new worker coexist → node mem ~2x" \
--grafana-url https://grafana.example.com \
--out ./mem-3.2-vs-2.7.png \
--attach-jira ABC-123
常見錯誤
- 圖表來自未經檢查的查詢 → 請參閱上述 PromQL 提示;看似合理的錯誤數字是失敗模式,而非錯誤訊息。
- 代理返回 401 → 使用靜態 token 時,該 token 不屬於該主機;透過 gcx 時,重新整理 token 已過期(約每月一次),執行
gcx login <context>。 - 使用系統
python3→ModuleNotFoundError: matplotlib。請使用 venv python。 - 期望多條線但出現空白/一條水平線 →
--expr正則表達式只匹配到一個序列;請放寬標籤匹配器。 - 序列未命名 / 全部顯示 "series" →
--legend-key指向了一個指標沒有的標籤;請選取一個確實存在的標籤(檢查原始查詢結果)。 - 圖例名稱中有
:9100(或任何:port) → 會自動從衍生序列名稱中移除,因此--rename應針對清理後的主機名稱(例如lb-edge-dc1-1,而非lb-edge-dc1-1:9100)。無需列出兩種形式。 - 相對時間只接受一個數字和一個單位,s/m/h/d(
now-90m、now-6h、now-2d)。不支援複合時間(now-1h30m)、週(now-1w)和捨入(now/d):請轉換它們(now-90m、now-7d)。