Skip to content

refactor(dashboards-v2): declare per-kind query capabilities instead of inferring them from panel types - #12559

Open
ahrefabhi wants to merge 5 commits into
mainfrom
refactor/v2-panel-query-capabilities
Open

refactor(dashboards-v2): declare per-kind query capabilities instead of inferring them from panel types#12559
ahrefabhi wants to merge 5 commits into
mainfrom
refactor/v2-panel-query-capabilities

Conversation

@ahrefabhi

Copy link
Copy Markdown
Contributor

Description

V2 panels answered "how does this panel's query behave?" by comparing against the legacy PANEL_TYPES enum. Each kind now declares it, so adding a kind means stating its behaviour once instead of finding every switch that should have mentioned it.

  • Kinds declare their query behaviour — request type, table formatting, step-interval and order treatment, paging, list-view authoring, trace operator. buildQueryRangeRequest takes that block, so the PANEL_TYPES.BAR / .LIST / .TABLE branches are gone. An exhaustive Record<PanelKind, …> test means a new kind can't ship without declaring its request shape.
  • The capabilities are passed in, not looked up. The panel registry carries every renderer with it, so importing it into the data path drags the app's API client into anything that touches the request builder. The call sites already resolve the definition.
  • The chart layer no longer infers a time axis from a panel type. UPlotAxisBuilder decided X-axis date formatting from a hardcoded [TIME_SERIES, BAR] list, so a chart that plots time but isn't one of those two silently lost its formatted ticks — no type error, no failing test. Callers now declare isTimeAxis.
  • getPanelDefinition always resolves. It was typed to return a definition for any PanelKind, but the registry only holds registered kinds, and a spec from a newer SigNoz names one this build has never heard of. Callers coped by truthiness-checking a value the type said couldn't be falsy — a lint autofix had already deleted one such guard in PublicPanel. Unknown kinds now resolve to UNSUPPORTED_PANEL, which declares nothing and renders as unsupported; isPanelKindSupported is the separate question the lazy fetch and editor session actually needed.
  • Analytics gained panelKind on all seven panel events, alongside the existing panelType so current reports keep resolving. panelType can't distinguish two kinds that map onto it.
  • Removed ViewPanelQueryBuilder — no importers; the View modal renders PanelEditorQueryBuilder. It referenced a stylesheet class that no longer exists.

Behaviour is unchanged for every registered kind. The one visible difference: a panel whose kind this build can't render now says so, instead of rendering a header above an empty body.

Additional Information

  • Read it commit by commit — each is one theme (declare / request path / axis / builder mode / analytics / registry), and the diff is mostly deletions once the declarations are in place.
  • The legacy enum still appears in ~28 V2 files, all of it translation at a boundary rather than a decision: the V1 Query pivot (mapCompositeQueryFromQuery writes panelType into ICompositeMetricQuery), URL params (graphType / panelTypes are a serialised contract), the shared QueryBuilderV2 provider (where panelType is provider state read by its subcomponents), and analytics. A follow-up will quarantine those into a single boundary module with a lint rule keeping them there.
  • The last commit deletes resolveQueryCapabilities, added earlier in this branch: it existed only to absorb a missing definition, which the registry no longer produces.

@ahrefabhi
ahrefabhi requested a review from a team as a code owner August 14, 2026 08:57
The View modal renders PanelEditorQueryBuilder; this component had no
importers and referenced a stylesheet class that no longer exists.

Assisted-by: Claude Opus 5
…a panel type

The uPlotV2 axis builder decided X-axis date formatting by testing the
panel type against a hardcoded [TIME_SERIES, BAR] list. A chart that plots
time but is not one of those two silently lost its time-formatted ticks —
no type error, no failing test, just wrong-looking ticks.

Axis props now take isTimeAxis and each caller states it: the three V2
kinds through the shared base config (histogram passes false — its X axis
is buckets), and the Meter Explorer, K8s metrics and V1 shared config
builders directly.

Assisted-by: Claude Opus 5
Each panel kind now states how its query behaves — request type, result
formatting, step-interval and order treatment, paging, whether it is
authored as a list view, and whether it offers a trace operator.

These are the questions V2 answered by comparing against the legacy
PANEL_TYPES enum. Declaring them per kind means the compiler asks for an
answer when a kind is added, instead of the kind silently falling through
someone else's switch. The expectations are an exhaustive Record over
PanelKind, so a new kind cannot ship without stating its request shape.

getPanelDefinition also stops lying. It was typed to return a definition
for any PanelKind, but the registry only holds the kinds this build
registers — a dashboard spec written by a newer SigNoz names one it has
never heard of, and callers coped by truthiness-checking a value the type
said could not be falsy. An unregistered kind now resolves to
UNSUPPORTED_PANEL, which declares nothing and renders as unsupported, so
callers read a definition's fields directly and such a panel says why it is
blank instead of leaving a hole in the layout. Whether a kind can be
rendered at all becomes its own question: isPanelKindSupported.

Assisted-by: Claude Opus 5
…e declarations

buildQueryRangeRequest now takes the kind's declared query capabilities
instead of a legacy panel type, so the request type, table formatting, bar
step interval and list order tiebreaker all come from the kind itself. The
editor asks the same declarations whether the query builder runs in
list-view mode, offers a trace operator, shows the plot-mode chip, or seeds
a default query, rather than testing "is this the List panel?" in four
places.

The capabilities are passed in rather than looked up by kind: the panel
registry carries every renderer with it, which has no business in the data
path — importing it there pulls the app's API client into any test that
touches the request builder. The call sites already resolve the definition,
so threading it costs nothing. PlotTag takes isListView instead of a panel
type, so a presentational component no longer needs the enum at all.

panelTypeToRequestType moves to persesQueryAdapters, the V1 Query pivot
that is now its only caller — the legacy switch belongs on the V1 side of
the boundary rather than in the middle of the V5 request builder. The
shared QueryBuilderV2 provider keeps its legacy panelType prop: that is
state inside the shared provider, read by its subcomponents, and out of
scope here.

Assisted-by: Claude Opus 5
Panel events identified the panel only by its legacy panel type, which
cannot tell apart two kinds that map onto the same one — so a newly added
kind is indistinguishable from the kind it shares a type with.

Adds panelKind alongside the existing panelType on all seven events (no
data, clone, delete, move, CSV export, drilldown opened, create alert).
Additive on purpose: existing reports keep resolving.

Assisted-by: Claude Opus 5
@ahrefabhi
ahrefabhi force-pushed the refactor/v2-panel-query-capabilities branch from 7ae53e5 to 98d2da9 Compare August 14, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant