Conversation
Categorical bar charts did not properly handle equations (e.g., `count(span.duration) / 5`). Equations were filtered out of the Visualize section, sort used the wrong format (`equation|...` instead of `equation[0]`), and changing the X-axis dropped equations from state causing server errors. - Include FieldValueKind.EQUATION in the Visualize section filter - Use equation[0] alias format for sort (matching getTableSortOptions) - Preserve equations in SET_CATEGORICAL_X_AXIS aggregate filter - Validate equation alias sorts when X-axis changes Refs DAIN-1201 Co-Authored-By: Claude <noreply@anthropic.com>
…ical bar charts Categorical bar charts previously limited users to a single aggregate, which made equations impossible on the Errors dataset (where equations require their underlying aggregate to coexist). This adopts the Big Number pattern: users can add multiple aggregates/equations and select which one to plot via radio buttons. The chart, sort, and display type switching all respect the selection. Fixes DAIN-1201
static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx
Outdated
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/utils/convertBuilderStateToWidget.ts
Outdated
Show resolved
Hide resolved
… aggregates When deleting an aggregate before the selected one, the index now decrements to keep pointing at the same aggregate. When deleting the selected item itself, the index resets to undefined (defaults to last). Previously only the last-item deletion was handled, leaving a stale index that could go out of bounds.
static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx
Outdated
Show resolved
Hide resolved
…elete index check Two fixes from automated review: 1. convertBuilderStateToWidget: The defaultSort fallback for categorical bar used the raw equation|... string format. The API expects the equation[N] alias format. Now computes the correct alias index. 2. visualize/index: The delete handler used >= which also caught deletions after the selected aggregate, incorrectly resetting the radio. Changed to === so only deleting the selected item resets it.
static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx
Outdated
Show resolved
Hide resolved
…ional SET_CATEGORICAL_AGGREGATE previously recomputed sort unconditionally using selectedAggregate from the closure, which could be stale during deletions (dispatch order: SET_CATEGORICAL_AGGREGATE runs before SET_SELECTED_AGGREGATE updates the index). Now only recomputes sort when the current sort field is no longer present in the new aggregates, matching how SET_FIELDS works for tables. This avoids the stale-index problem entirely.
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
…ata lookup Two fixes: 1. Sort validation now checks the specific equation[N] index against the equation count, not just whether any equation exists. Prevents stale equation[1] sort when only equation[0] remains after deletion. Applies to both SET_CATEGORICAL_AGGREGATE and SET_CATEGORICAL_X_AXIS. 2. Chart rendering now converts raw equation|... aggregates to their equation[N] alias before passing to transformTableToCategoricalSeries, since the events API returns data under alias keys.
…ge cases Document the equation alias index computation pattern, stale closure avoidance in SET_CATEGORICAL_AGGREGATE, equation index bounds validation, and the three-way delete handler logic.
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx
Outdated
Show resolved
Hide resolved
…ton visibility When switching the categorical bar radio selection, update the sort to match so bars are ordered by the displayed metric. Also remove the enableEquations gate from the delete button for categorical bar, since multiple aggregates can come from display type switching even when equations are disabled for the dataset.
If the selectedAggregate URL param is stale (e.g. from a bookmark after aggregates were removed), clamp it to the valid range so the chart renders the last aggregate instead of falling back to showing all.
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Show resolved
Hide resolved
…GATE The time series branch of DELETE_AGGREGATE was missing sort-fixup logic that SET_Y_AXIS applies: clearing sort when no grouping fields exist, and resetting stale TraceMetrics sort targets.
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Show resolved
Hide resolved
…ort-in-categorical-bar-charts
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
narsaynorath
left a comment
There was a problem hiding this comment.
Just pointed out two things I think we should consider changing (the stuff around valid sorts and resetting), and some clarification things around text copy (low priority) and possibly moving off equation[X] in the future. Otherwise the code looks good, thanks for naming some of the operations like fixing the sort for tables and categorical charts
We also talked about the behaviour when adding an equation causes the chart to not show data. Likely caused by some of the filtering that we do by filtering out an empty equation from our query, so the selected aggregate look up returns nothing for the chart to plot, throwing the error
static/app/views/dashboards/widgetBuilder/utils/convertBuilderStateToWidget.ts
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/components/visualize/index.tsx
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
- Move categorical bar sort sync from radio onChange into SET_SELECTED_AGGREGATE reducer (eliminates two-dispatch pattern) - Refactor fixupCategoricalBarSort and fixupTableSortOnRemoval to return Sort[] | null instead of calling setSort internally - Accept xAxisFields in fixupCategoricalBarSort so sorting by the X-axis column is treated as valid - Pass old sort index as fallbackIndex in SET_CATEGORICAL_AGGREGATE so sort follows in-place aggregate edits - Filter empty equations from aggregates in convertBuilderStateToWidget to prevent "no plottable values" error when adding a new equation
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
static/app/views/dashboards/widgetBuilder/utils/convertBuilderStateToWidget.ts
Show resolved
Hide resolved
…egate index - Include DisplayType.TOP_N in DELETE_AGGREGATE time-series branch so it correctly deletes from yAxis instead of falling through to the table branch - Clamp getSelectedAggregateIndex to aggregateCount-1 to prevent out-of-bounds access when empty equations are filtered from aggregates
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
static/app/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState.tsx
Outdated
Show resolved
Hide resolved
…branch Clamp fallbackIndex once at the top of fixupCategoricalBarSort so both the invalid-sort and no-sort branches use a safe index. Previously the no-sort branch passed fallbackIndex directly to generateSortField, which could crash on out-of-bounds access with a stale selectedAggregate.
|
@narsaynorath thanks for taking a look! I ended up asking Claude to make a detailed test plan, and went through it. I think we should be good to go! |
…display The raw `equation|` prefix was showing in chart tooltips and legends for categorical bar widgets using equations. Strip it in formatCategoricalSeriesLabel, the latest display-only formatting point.
|
@narsaynorath right on thanks! I fixed the |
…ort-in-categorical-bar-charts

Categorical bar charts previously limited users to a single aggregate, which made equations impossible on the Errors dataset (where equations require their underlying aggregate to be selected and the equation). Also, switching to a categorical bar from a time series chart would silently drop all but the first aggregate, which is annoying.
This PR adopts the Big Number pattern: users can add multiple aggregates and equations, then select which one to plot via radio buttons. When only one aggregate exists, no radio buttons appear. This way, when users change back/forth between datasets and widget types, we don't drop any data.
There is added complexity now though, because the different actions might invalidate state (e.g., changing the selected aggregate might have to force change the sort). There were some stale closure issues in the reduces, so I ended up adding a new action dispatch for deleting an aggregate, which will now fall back to the correct aggregate where needed.
Fixes DAIN-1201