Context
The true matrix cross-tab shipped in objectui#1649: a type: 'matrix' report renders rows (down) × columns (across) with measures in the cells, pivoted client-side from a single queryDataset over all dimensions.
It intentionally renders no totals row/column. Re-aggregating bucketed values on the client would drift from the semantic layer — e.g. an avg measure can't be averaged-of-averages, and a count_distinct can't be summed across buckets. ADR-0021's governance line is "one place to reason about a metric," so the renderer refuses to invent subtotals it can't compute correctly.
Proposal
Compute totals server-side, where the measure's true aggregate is known:
- per-row subtotals (aggregate across the row's across-buckets),
- per-column subtotals (aggregate down),
- grand total.
Likely a queryDataset option (e.g. { totals: true } or withGrandTotal) that returns the marginal aggregates as extra rows/fields, so each total is computed with the measure's real aggregate function rather than re-derived. The matrix renderer then renders the supplied totals (it already has the slot for them — DatasetMatrixTable).
Affected
- framework:
packages/services/service-analytics — marginal/total aggregation in the dataset query - objectui (consumer):
packages/plugin-report/src/DatasetReportRenderer.tsxDatasetMatrixTable — render server-supplied totals row/column
Found during the ADR-0021 report epic; the no-totals tradeoff is documented in the DatasetReportRenderer header comment.
Context
The true matrix cross-tab shipped in objectui#1649: a
type: 'matrix'report rendersrows(down) ×columns(across) with measures in the cells, pivoted client-side from a singlequeryDatasetover all dimensions.It intentionally renders no totals row/column. Re-aggregating bucketed values on the client would drift from the semantic layer — e.g. an
avgmeasure can't be averaged-of-averages, and acount_distinctcan't be summed across buckets. ADR-0021's governance line is "one place to reason about a metric," so the renderer refuses to invent subtotals it can't compute correctly.Proposal
Compute totals server-side, where the measure's true aggregate is known:
Likely a
queryDatasetoption (e.g.{ totals: true }orwithGrandTotal) that returns the marginal aggregates as extra rows/fields, so each total is computed with the measure's real aggregate function rather than re-derived. The matrix renderer then renders the supplied totals (it already has the slot for them —DatasetMatrixTable).Affected
packages/services/service-analytics— marginal/total aggregation in the dataset querypackages/plugin-report/src/DatasetReportRenderer.tsxDatasetMatrixTable— render server-supplied totals row/columnFound during the ADR-0021 report epic; the no-totals tradeoff is documented in the DatasetReportRenderer header comment.