fix(observability): every Grafana query-variable dropdown was silently empty in production#5349
Conversation
…y empty in production Every "query"-type template variable across every dashboard ($repo, $scope, $provider/$feature/$model) resolved to zero options in the live Grafana instance -- confirmed empirically against a running frser-sqlite-datasource via POST /api/ds/query -- because the variable's `query` object only carried `rawQueryText` (a display/round-trip field the plugin's variable-query path never actually executes), never `queryText` (the field the plugin's query builder requires). Panel targets were never affected -- they already set both fields at the top level -- which is exactly why every table/timeseries panel rendered real data while every $variable dropdown showed a red error icon in the UI, cascading into "No data"/zeroed panels wherever a panel's own WHERE clause referenced one of the broken variables. Adds a cross-dashboard regression test scanning every file in grafana/dashboards/ for this exact shape, so a future dashboard can't reintroduce it by copying the variable pattern without the fix.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5349 +/- ##
==========================================
- Coverage 94.40% 94.36% -0.04%
==========================================
Files 550 550
Lines 44119 44119
Branches 14632 14632
==========================================
- Hits 41652 41635 -17
- Misses 1792 1809 +17
Partials 675 675
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-12 14:45:52 UTC
⏸️ Suggested Action - Manual Review
Review summary Blockers
Nits — 5 non-blocking
Concerns raised — review before merging
Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
…eryText The model template variable's queryText/rawQueryText fallback (target?.rawQueryText ?? target?.queryText) meant an unescaped queryText would never be caught once both fields existed. Assert both explicitly, and extend the TemplateVar.query type to declare queryText (missing since #5349 added the field to the JSON).
* fix(grafana): escape AI usage SQL variables * test(grafana): assert sqlstring escaping on queryText, not just rawQueryText The model template variable's queryText/rawQueryText fallback (target?.rawQueryText ?? target?.queryText) meant an unescaped queryText would never be caught once both fields existed. Assert both explicitly, and extend the TemplateVar.query type to declare queryText (missing since #5349 added the field to the JSON).
Summary
User-reported live bug: the AI-usage dashboard's Provider/Feature/Model filters showed red error
icons and couldn't actually filter anything, and several panels (tokens-by-feature, cost-share-by-
feature) showed no data despite the dashboard's own summary panels clearly showing real, non-zero
totals.
Root cause, confirmed empirically against the live
frser-sqlite-datasourceplugin viaPOST /api/ds/query: every "query"-type template variable across every dashboard(
$repo,$scope,$provider/$feature/$model, added across #5234/#5267/#5302) had itsqueryobject carry onlyrawQueryText— a display/round-trip field the plugin's variable-querypath never actually executes — never
queryText, the field its query builder actually requires.Every one of these dropdowns silently resolved to zero options in production; the identical raw SQL
run directly via the
sqlite3CLI, or via the API withqueryTextadded, returns real dataimmediately. Panel targets were never affected — they already set both fields at the top level —
which is exactly why every table/timeseries panel kept rendering real data while every variable
dropdown was broken, cascading into "No data"/zeroed panels wherever a panel's own
WHEREclausereferenced one of the broken variables.
Since these are file-provisioned dashboards (
editable: false), the fix couldn't be hotfixed via thedashboard-save API — I updated the files directly on
edge-nl-01and restarted Grafana to confirm thefix live before opening this PR (see test plan).
Adds a cross-dashboard regression test scanning every file in
grafana/dashboards/for this exactshape, so a future dashboard can't reintroduce it by copying the variable pattern without the fix.
Test plan
npm run typecheck— cleannpm run test:ci— full local gate greenselfhost-grafana-variable-query-text.test.ts: scans every dashboard file for this exactmissing-
queryTextshape; verified it fails when the bug is reintroduced (temporarily revertedone file, confirmed the test catches it) and passes with the fix
POST /api/ds/queryagainst the runningfrser-sqlite-datasource: the$providervariable's query returned zero rows before the fix,real provider names after; the previously-empty "cost share by feature" panel query also
confirmed to return real, non-zero data with the fix in place