Skip to content

Commit 6bd1582

Browse files
DominikB2014claude
andauthored
fix(explore): Pass sort param for group-by explore Slack unfurls (#112704)
When an Explore link with `groupBy` is unfurled in Slack, the unfurl sets `topEvents=5` but omits the `sort` parameter. Without it, the timeseries endpoint returns whichever groups it defaults to rather than the actual top groups matching what Explore shows (e.g., "mark" and "paint" appearing instead of the real top groups). Two changes: - `map_explore_query_args` now copies the `aggregateSort` URL param (Explore's name) as `sort` (the API param name) - `_unfurl_explore` defaults to `-{yAxis}` (descending by the charted aggregate) when no explicit sort is present, matching the frontend's `defaultAggregateSortBys` behavior Fixes DAIN-1490 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b4bb9a8 commit 6bd1582

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/sentry/integrations/slack/unfurl/explore.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ def _unfurl_explore(
129129
style = ChartType.SLACK_EXPLORE_LINE
130130
if group_bys:
131131
params.setlist("topEvents", [str(TOP_N)])
132+
if not params.getlist("sort"):
133+
# Default to descending by the first yAxis, matching Explore's
134+
# defaultAggregateSortBys behavior
135+
params.setlist("sort", [f"-{y_axes[0]}"])
132136

133137
if not params.get("statsPeriod") and not params.get("start"):
134138
params["statsPeriod"] = DEFAULT_PERIOD
@@ -231,6 +235,12 @@ def map_explore_query_args(url: str, args: Mapping[str, str | None]) -> Mapping[
231235
if values:
232236
query.setlist(param, values)
233237

238+
# Explore stores the aggregate sort as "aggregateSort" in the URL;
239+
# the events-timeseries endpoint expects it as "sort".
240+
aggregate_sort = raw_query.getlist("aggregateSort")
241+
if aggregate_sort:
242+
query.setlist("sort", aggregate_sort)
243+
234244
return dict(**args, query=query, chart_type=chart_type, dataset=explore_dataset)
235245

236246

tests/sentry/integrations/slack/test_unfurl.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,37 @@ def test_unfurl_explore_with_groupby(
15781578
assert len(mock_generate_chart.mock_calls) == 1
15791579
assert mock_generate_chart.call_args[0][0] == ChartType.SLACK_EXPLORE_LINE
15801580

1581+
# Verify sort is passed to the timeseries API for correct top events
1582+
api_params = mock_client_get.call_args[1]["params"]
1583+
assert api_params.getlist("sort") == ["-avg(span.duration)"]
1584+
1585+
@patch(
1586+
"sentry.integrations.slack.unfurl.explore.client.get",
1587+
)
1588+
@patch("sentry.charts.backend.generate_chart", return_value="chart-url")
1589+
def test_unfurl_explore_with_groupby_explicit_sort(
1590+
self, mock_generate_chart: MagicMock, mock_client_get: MagicMock
1591+
) -> None:
1592+
mock_client_get.return_value = MagicMock(data=self._build_mock_timeseries_response())
1593+
url = f"https://sentry.io/organizations/{self.organization.slug}/explore/traces/?aggregateField=%7B%22groupBy%22%3A%22span.op%22%7D&aggregateField=%7B%22yAxes%22%3A%5B%22avg(span.duration)%22%5D%7D&aggregateSort=span.op&project={self.project.id}&statsPeriod=24h"
1594+
link_type, args = match_link(url)
1595+
1596+
if not args or not link_type:
1597+
raise AssertionError("Missing link_type/args")
1598+
1599+
links = [
1600+
UnfurlableUrl(url=url, args=args),
1601+
]
1602+
1603+
with self.feature(["organizations:data-browsing-widget-unfurl"]):
1604+
unfurls = link_handlers[link_type].fn(self.integration, links, self.user)
1605+
1606+
assert len(unfurls) == 1
1607+
1608+
# Verify explicit aggregateSort from the URL is used instead of the default
1609+
api_params = mock_client_get.call_args[1]["params"]
1610+
assert api_params.getlist("sort") == ["span.op"]
1611+
15811612
@patch(
15821613
"sentry.integrations.slack.unfurl.explore.client.get",
15831614
)

0 commit comments

Comments
 (0)