Skip to content

support legendFormat and show "No data" on empty results - #123

Merged
JackieTien97 merged 1 commit into
apache:masterfrom
CoollZzz:feat/support-legend-format-and-no-data
Aug 14, 2026
Merged

support legendFormat and show "No data" on empty results#123
JackieTien97 merged 1 commit into
apache:masterfrom
CoollZzz:feat/support-legend-format-and-no-data

Conversation

@CoollZzz

@CoollZzz CoollZzz commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Description

This PR improves Grafana table-model queries by supporting custom legend formats and returning Grafana's native No data state when a time-series result contains no plottable values.

Support Grafana legendFormat

  • Adds legendFormat to the frontend query model, backend query parameters, and the Table Model query editor (the other two SQL query types are unchanged).
  • Supports static legends and templates such as {{instance}} and {{nodeType}} - {{nodeId}}.
  • Resolves legend templates after converting long-form query results to wide time-series frames, when the per-series labels are available.
  • Maps common Prometheus label names to their IoTDB column aliases, such as nodeType to node_type and name to label_name.
  • Leaves the legend unchanged when legendFormat is empty or set to Grafana's __auto sentinel.
  • Applies the resolved value through DisplayNameFromDS without overwriting other field configuration.

Resolving legends in the backend keeps imported Prometheus dashboards compatible and avoids requiring panel-specific field overrides.

Show No data for empty time-series results

Some IoTDB HOP and rate queries return timestamped rows whose numeric values are all NULL, instead of returning zero rows. Grafana previously received a non-empty frame for these results and rendered empty axes rather than its No data state.

This PR treats a result as having no plottable data when:

  • the result contains zero rows;
  • every numeric value column contains only NULL values; or
  • the result has no numeric value column at all (only timestamps and string tags).

In these cases, the backend returns no frame, allowing Grafana to display No data.

The behavior applies to any non-Table format — the empty or legacy format defaults to the time-series treatment, so queries saved before FORMAT existed are covered too. The Table format still returns a frame so that column headers and NULL rows remain available to table panels. This logic is implemented in the plugin instead of adding query-specific SQL filters, so it also applies to future sparse aggregation queries.

Testability and coverage

The table query execution path is separated from response construction through executeTableQuery. Tests can replace the query runner with an in-memory result, allowing response semantics to be tested without a live IoTDB RPC service.

Added coverage includes:

  • static and templated legend formats;
  • multiple placeholders and whitespace handling;
  • Prometheus-to-IoTDB label aliases;
  • missing and empty labels;
  • the empty and __auto no-op formats;
  • preservation of existing field configuration;
  • legend application after long-to-wide conversion;
  • zero-row time-series and table results;
  • all-NULL numeric time-series results;
  • partially populated numeric results; and
  • legendFormat query deserialization and backward compatibility.

Key changed/added classes (or packages if there are too many classes) in this PR

  • connectors/grafana-plugin/pkg/plugin/table_query.go
  • connectors/grafana-plugin/pkg/plugin/table_query_test.go
  • connectors/grafana-plugin/pkg/plugin/plugin.go
  • connectors/grafana-plugin/src/QueryEditor.tsx
  • connectors/grafana-plugin/src/types.ts

@JackieTien97
JackieTien97 merged commit 608ec36 into apache:master Aug 14, 2026
13 of 14 checks passed
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.

2 participants