Replace Grafana iframe panel with server-side chart widget
The iframe-based 'panel' widget didn't work: the browser couldn't
authenticate against the OIDC-protected Grafana (Authentik), and
iframes can't carry Bearer tokens or share cross-origin session
cookies. Result: blank iframe or login redirect.
Replace it with a 'chart' widget that queries Grafana's datasource
API server-side:
Backend (GrafanaWidgetSource): POSTs to /api/ds/query with the stored
api_key (which bypasses OIDC), using the widget's configured PromQL
query, datasource_uid, time range, and resolution. Normalizes Grafana's
frame-based response into a simple {series: [{label, points: [{t, v}]}]}
shape. The api_key is never exposed to the browser.
Frontend (GrafanaChartWidget): renders the series data as a recharts
LineChart with dark-mode-aware colors (Tailwind --chart-* tokens),
responsive container, custom tooltip, and per-series lines. Loading
skeleton, error Alert, and empty state. recharts ^3.9.2 added.
The 'link' widget kind (deep-link URL) is unchanged. The 'panel' kind
and GrafanaPanelWidget are fully removed.
Backend: 279 tests pass (+1 net: -2 panel + 3 chart). Frontend: 127
tests pass (net 0: -3 panel + 3 chart). Lint/build green both sides.
This commit is contained in:
@@ -26,13 +26,15 @@ class GrafanaLinkWidgetConfig(WidgetConfigBase):
|
||||
panel_id: int | None = None
|
||||
|
||||
|
||||
class GrafanaPanelWidgetConfig(WidgetConfigBase):
|
||||
"""Embed a single Grafana panel via iframe."""
|
||||
class GrafanaChartWidgetConfig(WidgetConfigBase):
|
||||
"""Render a time-series chart from a Grafana datasource query."""
|
||||
|
||||
dashboard_uid: str
|
||||
panel_id: int
|
||||
datasource_uid: str = "prometheus"
|
||||
query: str = ""
|
||||
from_ts: str = "now-1h"
|
||||
to_ts: str = "now"
|
||||
interval_ms: int = 30_000
|
||||
max_data_points: int = 100
|
||||
|
||||
|
||||
DEFINITION = ServiceDefinition(
|
||||
@@ -53,12 +55,19 @@ DEFINITION = ServiceDefinition(
|
||||
refresh_interval_ms=0,
|
||||
),
|
||||
widget_kind(
|
||||
kind="panel",
|
||||
name="Panel embed",
|
||||
description="Embed a Grafana panel directly.",
|
||||
model_cls=GrafanaPanelWidgetConfig,
|
||||
default_config={"dashboard_uid": "", "panel_id": 1, "from_ts": "now-1h", "to_ts": "now"},
|
||||
refresh_interval_ms=0,
|
||||
kind="chart",
|
||||
name="Chart",
|
||||
description="Live time-series chart from a Grafana datasource query.",
|
||||
model_cls=GrafanaChartWidgetConfig,
|
||||
default_config={
|
||||
"datasource_uid": "prometheus",
|
||||
"query": "",
|
||||
"from_ts": "now-1h",
|
||||
"to_ts": "now",
|
||||
"interval_ms": 30_000,
|
||||
"max_data_points": 100,
|
||||
},
|
||||
refresh_interval_ms=60_000,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user