Skip to content

fix(explore): stacked Timeseries Bar total excludes the sort-only metric - #42881

Merged
rusackas merged 4 commits into
apache:masterfrom
vjymisal0:fix/stacked-total-excludes-sort-metric
Aug 10, 2026
Merged

rusackas merged 4 commits into
apache:masterfrom
vjymisal0:fix/stacked-total-excludes-sort-metric

Conversation

@vjymisal0

Copy link
Copy Markdown
Contributor

SUMMARY

On a stacked Timeseries Bar chart (echarts_timeseries_bar) with "Show Total"/"Only Total" enabled, the displayed stacked total was silently inflated when the chart also used a timeseries_limit_metric (the "Sort by" metric used to order/limit the x-axis) that isn't one of the chart's displayed metrics.

extraMetricLabels — which correctly excludes series-limit/sort-only metrics when building the actual rendered series via extractSeries — was computed in Timeseries/transformProps.ts after extractDataTotalValues ran, and was never passed into it. extractDataTotalValues summed every remaining numeric key in each row except the x-axis column, so the sort-only metric's value leaked into the total even though it never appeared in the legend.

Fix:

  • extractDataTotalValues (utils/series.ts) now accepts an optional extraMetricLabels list and excludes those columns the same way it already excludes the x-axis column.
  • transformProps.ts now computes extraMetricLabels once, above both call sites that need it (it was already being computed below, for extractSeries), instead of after extractDataTotalValues had already run without it.

This is easy to hit in practice: timeseries_limit_metric is the standard way to control x-axis category ordering when the natural order isn't alphabetical (e.g. binned/bucketed labels like 1-3d, 4-6d), which is precisely the situation where the sort metric is likely to differ from the displayed metrics.

Closes #42701

TESTING INSTRUCTIONS

Added two unit tests to test/utils/series.test.ts:

  • extractDataTotalValues excludes extraMetricLabels from the stacked total (#42701) — reproduces the bug on the unfixed path (verifies the pre-fix behavior with a comment) and asserts the fixed behavior with extraMetricLabels passed.
  • extractDataTotalValues still respects legendState alongside extraMetricLabels — confirms the existing legend-toggle exclusion still works together with the new one.

Ran locally:

npx jest plugins/plugin-chart-echarts/test/utils/series.test.ts
npx jest plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts plugins/plugin-chart-echarts/test/Timeseries/Bar/transformProps.test.ts plugins/plugin-chart-echarts/test/MixedTimeseries/transformProps.test.ts
npx oxlint --config oxlint.json --quiet <changed files>

All pass (102 + 112 tests, oxlint clean). tsc --noEmit on the package reports pre-existing errors from unbuilt monorepo package type declarations and other unrelated files/lines (confirmed identical patterns exist elsewhere in the same untouched file); none are on the lines this PR changes.

Manual repro steps are in the linked issue (stacked bar chart, 2+ metrics, timeseries_limit_metric set to a non-displayed metric, "Only Total" enabled).

ADDITIONAL INFORMATION

On a stacked Timeseries Bar chart with "Only Total"/"Show Total"
enabled, the displayed stacked total silently included the
timeseries_limit_metric value when that sort/limit metric differed
from the chart's displayed metrics. The metric is correctly excluded
from the rendered series/legend by extractSeries via
extraMetricLabels, but extractDataTotalValues summed every remaining
numeric column except the x-axis column, so the sort metric's value
still leaked into the total.

extractDataTotalValues now accepts an optional extraMetricLabels list
and excludes those columns the same way it already excludes the
x-axis column. transformProps.ts computes extraMetricLabels once,
above both call sites that need it, instead of after
extractDataTotalValues had already run without it.

Closes #42701
Copilot AI lite review requested due to automatic review settings August 7, 2026 06:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@dosubot dosubot Bot added viz:charts:echarts Related to Echarts viz:charts:timeseries Related to Timeseries labels Aug 7, 2026
@bito-code-review

bito-code-review Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #83afb7

Actionable Suggestions - 0
Review Details
  • Files reviewed - 3 · Commit Range: bbb8384..bbb8384
    • superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
    • superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
    • superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue is correct. The extraMetricLabels are currently derived from raw metric labels, but rebasedData has already been processed through rebaseForecastDatum, which applies verboseMap to rename keys. Consequently, the exclusion set in extractDataTotalValues fails to match the verbose keys present in the data, causing sort-only metrics to be incorrectly included in the stacked totals.

To resolve this, you should map the extraMetricLabels using the same verboseMap before passing them to extractDataTotalValues. In transformProps.ts, update the extraction logic as follows:

  const extraMetricLabels = extractExtraMetrics(chartProps.rawFormData).map(
    (metric) => verboseMap[getMetricLabel(metric)] || getMetricLabel(metric),
  );

This ensures the exclusion set uses the same labels as the rebased data rows.

superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts

const extraMetricLabels = extractExtraMetrics(chartProps.rawFormData).map(
    (metric) => verboseMap[getMetricLabel(metric)] || getMetricLabel(metric),
  );

…luding

rebasedData's keys have already been through rebaseForecastDatum,
which renames a key to its verboseMap entry when one is configured
for that metric. extraMetricLabels was still the raw metric label, so
a sort-only metric with a verbose_name set would silently fail to
match the exclusion set in extractDataTotalValues (and in
extractSeries, which has the same requirement and was already using
this variable). Added a regression test in transformProps.test.ts
covering a verbose-named sort-only metric end to end.

Thanks to the Bito AI review on this PR for catching this.
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Aug 7, 2026
@vjymisal0

Copy link
Copy Markdown
Contributor Author

Good catch — pushed a fix. extraMetricLabels is now resolved through verboseMap the same way rebaseForecastDatum renames the data keys, using the same verboseMap[label] ?? label fallback pattern already used elsewhere in this file. Added a regression test in transformProps.test.ts covering a verbose-named sort-only metric end to end (fails without the fix: total comes out to 34 instead of 32; passes with it).

@codecov

codecov Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.36%. Comparing base (38ba4a6) to head (3d2b7bc).
⚠️ Report is 32 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42881      +/-   ##
==========================================
+ Coverage   57.10%   66.36%   +9.26%     
==========================================
  Files        2857     2857              
  Lines      161125   161047      -78     
  Branches    37060    37048      -12     
==========================================
+ Hits        92014   106883   +14869     
+ Misses      68259    52148   -16111     
- Partials      852     2016    +1164     
Flag Coverage Δ
javascript 73.19% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bito-code-review

bito-code-review Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #5a5350

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: bbb8384..516121d
    • superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
    • superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sadpandajoe

Copy link
Copy Markdown
Member

@vjymisal0 thanks for the PR! Since there is a visual component to your change, can you add before and after screenshots of your fix into the PR description?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts:758

  • The test name references issue #42881, but this PR (and the new unit test in series.test.ts) is about #42701. Updating the reference avoids confusion when triaging failures or searching history.
  test('should exclude a verbose-named sort-only metric from the stacked total (#42881)', () => {

Fixes the oxfmt-frontend pre-commit CI failure (destructuring
assignment exceeded the configured printWidth).
@vjymisal0

Copy link
Copy Markdown
Contributor Author

Pushed 3d2b7bc — ran oxfmt on series.ts to fix the oxfmt-frontend pre-commit CI failure (a destructuring assignment exceeded the configured printWidth). No logic change.

@netlify

netlify Bot commented Aug 8, 2026

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 3d2b7bc
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a76be0806f0770008543dbf
😎 Deploy Preview https://deploy-preview-42881--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@bito-code-review

bito-code-review Bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #f4bdf3

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 516121d..3d2b7bc
    • superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@rusackas rusackas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for chasing down the verboseMap edge case too, that's exactly the kind of thing that would've bitten someone later. Tests look solid (both the unit-level exclusion logic and a real end-to-end verboseMap repro) and CI's green. LGTM, merging!

@rusackas rusackas added the merge-if-green If approved and tests are green, please go ahead and merge it for me label Aug 10, 2026
@rusackas
rusackas merged commit 178d9c4 into apache:master Aug 10, 2026
79 checks passed
rusackas pushed a commit to SaadAhmed7/superset that referenced this pull request Sep 9, 2026
apache#42881 excluded sort-only metrics from the "Only Total" label by exact
name match. Time comparison post-processing emits a derived column per
query metric named `<label>__<offset>`, and sort-only metrics are part
of the query, so `Sort__1 year ago` still slipped into the total on
time-comparison charts. The same inflated total feeds thresholdValues,
so the percentage-threshold cutoff was off by the same amount.

Match keys beginning with `<label>` + TIME_COMPARISON_SEPARATOR as well
as the exact label. Keying on the separator keeps a distinct metric that
merely shares a prefix (`SortTotal` vs `Sort`) counted in the total.

Fixes apache#43068

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rusackas pushed a commit to SaadAhmed7/superset that referenced this pull request Sep 16, 2026
apache#42881 excluded sort-only metrics from the "Only Total" label by exact
name match. Time comparison post-processing emits a derived column per
query metric named `<label>__<offset>`, and sort-only metrics are part
of the query, so `Sort__1 year ago` still slipped into the total on
time-comparison charts. The same inflated total feeds thresholdValues,
so the percentage-threshold cutoff was off by the same amount.

Match keys beginning with `<label>` + TIME_COMPARISON_SEPARATOR as well
as the exact label. Keying on the separator keeps a distinct metric that
merely shares a prefix (`SortTotal` vs `Sort`) counted in the total.

Fixes apache#43068

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-if-green If approved and tests are green, please go ahead and merge it for me plugins size/L viz:charts:echarts Related to Echarts viz:charts:timeseries Related to Timeseries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Timeseries Bar: stacked 'Only Total' sum includes the series-limit/sort metric's value, not just the displayed metrics

4 participants