gkhnelbstn opened a new issue, #42701:
URL: https://github.com/apache/superset/issues/42701
## Summary
On a stacked Timeseries Bar chart (`echarts_timeseries_bar`) with "Show
Total"/"Only Total" enabled, the displayed stacked total is silently inflated
when the chart also uses 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. The
sort metric's value gets summed into the total even though it's correctly
excluded from the actual rendered series/legend.
## Reproduction
1. Create an `echarts_timeseries_bar` chart with 2+ metrics (e.g. custom SQL
metrics `A`, `B`), Stacked, "Only Total" enabled.
2. Set **Sort Series By / Series limit sort by** (`timeseries_limit_metric`)
to a metric that is *not* among the displayed metrics — e.g.
`MIN(some_sequence_column)` labeled `Sort`, used purely so `X-Axis Sort By` can
order categories by their natural sequence instead of alphabetically. The
generated query becomes roughly:
```sql
SELECT category, A, B, MIN(some_sequence_column) AS "Sort"
FROM ...
GROUP BY category
ORDER BY "Sort"
```
3. A real returned row looks like: `{"category": "1-3g", "A": 32, "B": 0,
"Sort": 2}`.
4. The chart correctly shows only 2 series in the legend (`A`, `B`) — `Sort`
is excluded from the rendered series.
5. **Bug**: the "Only Total" stacked label for this category shows `34` (`32
+ 0 + 2`) instead of the correct `32` (`32 + 0`). The sort metric's value
silently leaks into the total.
## Root cause
`plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts`:
```ts
const { totalStackedValues, thresholdValues } = extractDataTotalValues(
rebasedData,
{ stack, percentageThreshold, xAxisCol: xAxisLabel, legendState },
);
const extraMetricLabels =
extractExtraMetrics(chartProps.rawFormData).map(getMetricLabel);
```
`extraMetricLabels` — which correctly excludes series-limit/sort-only
metrics when building the actual chart series via `extractSeries` — is computed
*after* `extractDataTotalValues` runs, and is never passed into it.
`plugins/plugin-chart-echarts/src/utils/series.ts`, `extractDataTotalValues`:
```ts
export function extractDataTotalValues(
data: DataRecord[],
opts: { stack: StackType; percentageThreshold: number; xAxisCol: string;
legendState?: LegendState },
): { totalStackedValues: number[]; thresholdValues: number[] } {
...
data.forEach(datum => {
const values = Object.keys(datum).reduce((prev, curr) => {
if (curr === xAxisCol) return prev;
if (legendState && !legendState[curr]) return prev;
const value = datum[curr] || 0;
return prev + (value as number);
}, 0);
...
});
```
It sums every remaining numeric key in each row. The only exclusions are the
x-axis column and legend-toggled-off series — there's no way to exclude a
metric that was added to the query purely for sorting/limiting (via
`extractExtraMetrics` in `buildQuery.ts`, comment: `// only add series limit
metric if it's explicitly needed e.g. for sorting`). Since that column is never
a visible legend entry, `legendState` can never exclude it either.
## Suggested fix
Thread `extraMetricLabels` into `extractDataTotalValues` and exclude them
the same way `xAxisCol` is excluded:
```ts
export function extractDataTotalValues(
data: DataRecord[],
opts: {
stack: StackType;
percentageThreshold: number;
xAxisCol: string;
legendState?: LegendState;
extraMetricLabels?: string[]; // NEW
},
): { totalStackedValues: number[]; thresholdValues: number[] } {
const { stack, percentageThreshold, xAxisCol, legendState,
extraMetricLabels } = opts;
const excludedKeys = new Set([xAxisCol, ...(extraMetricLabels ?? [])]);
...
data.forEach(datum => {
const values = Object.keys(datum).reduce((prev, curr) => {
if (excludedKeys.has(curr)) return prev;
if (legendState && !legendState[curr]) return prev;
...
```
And in `transformProps.ts`, move the `extraMetricLabels` computation above
the `extractDataTotalValues` call and pass it through via `opts`.
## Impact
Any stacked Timeseries Bar/Area chart combining "Only Total"/"Show Total"
with a `timeseries_limit_metric` that differs from the displayed metrics will
show an inflated, incorrect stacked total. 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`, `7-9d`, `10-12d`, ...), which is precisely the situation
where the sort metric is likely to differ from the displayed metrics.
## Workaround
Avoid combining a `timeseries_limit_metric` that isn't a displayed metric
with "Only Total"/"Show Total" on a stacked chart. If category ordering is the
only reason for the extra metric, consider instead encoding the sort order
directly into the x-axis column's values (e.g. zero-padded numeric prefixes) so
`X-Axis Sort By` can use simple name/alphabetical ordering without needing a
separate sort metric at all.
## Environment
- Superset version: 6.1.0 (confirmed present at `refs/tags/6.1.0`)
- Chart type: `echarts_timeseries_bar` (Time-series Bar Chart), stacked,
"Only Total" enabled
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]