From 5b1ecda5a2a864468e79518340e64b9858b485c9 Mon Sep 17 00:00:00 2001 From: Dominik Buszowiecki Date: Fri, 6 Jun 2025 14:55:44 -0400 Subject: [PATCH 1/2] open http response rate in comparison view --- .../explore/multiQueryMode/locationUtils.tsx | 31 ++++----- .../views/explore/toolbar/toolbarSaveAs.tsx | 16 +++-- .../common/components/chartActionDropdown.tsx | 4 +- .../widgets/httpResponseCodesChartWidget.tsx | 66 ++++++++++++++++++- 4 files changed, 90 insertions(+), 27 deletions(-) diff --git a/static/app/views/explore/multiQueryMode/locationUtils.tsx b/static/app/views/explore/multiQueryMode/locationUtils.tsx index 14448c99dd79e8..34735fc4e52192 100644 --- a/static/app/views/explore/multiQueryMode/locationUtils.tsx +++ b/static/app/views/explore/multiQueryMode/locationUtils.tsx @@ -278,35 +278,28 @@ type CompareRouteProps = { location: Location; mode: Mode; organization: Organization; - chartType?: ChartType; - fields?: string[]; - groupBys?: string[]; - query?: string; - sortBys?: Sort[]; - yAxes?: string[]; + queries: WritableExploreQueryParts[]; }; export function generateExploreCompareRoute({ organization, location, mode, - chartType, - groupBys, - query, - sortBys, - yAxes, + queries, }: CompareRouteProps): LocationDescriptorObject { const url = getCompareBaseUrl(organization); - const compareQuery: WritableExploreQueryParts = { - chartType, + const compareQueries = queries.map(query => ({ + ...query, // Filter out empty strings which are used to indicate no grouping // in Trace Explorer. The same assumption does not exist for the // comparison view. - groupBys: mode === Mode.AGGREGATE ? groupBys?.filter(Boolean) : [], - query, - sortBys, - yAxes, - }; + groupBys: mode === Mode.AGGREGATE ? query.groupBys?.filter(Boolean) : [], + })); + + if (compareQueries.length < 2) { + compareQueries.push(DEFAULT_QUERY); + } + return { pathname: url, query: { @@ -316,7 +309,7 @@ export function generateExploreCompareRoute({ [URL_PARAM.PERIOD]: location.query.statsPeriod, [URL_PARAM.PROJECT]: location.query.project, [URL_PARAM.ENVIRONMENT]: location.query.environment, - queries: getQueriesAsUrlParam([compareQuery, DEFAULT_QUERY]), + queries: getQueriesAsUrlParam(compareQueries), }, }; } diff --git a/static/app/views/explore/toolbar/toolbarSaveAs.tsx b/static/app/views/explore/toolbar/toolbarSaveAs.tsx index 296afaccf73615..bd0330555b853d 100644 --- a/static/app/views/explore/toolbar/toolbarSaveAs.tsx +++ b/static/app/views/explore/toolbar/toolbarSaveAs.tsx @@ -289,12 +289,16 @@ export function ToolbarSaveAs() { organization, mode, location, - query, - yAxes: [visualizeYAxes[0]!], - groupBys, - fields, - sortBys, - chartType: visualizes[0]!.chartType, + queries: [ + { + query, + groupBys, + fields, + sortBys, + yAxes: [visualizeYAxes[0]!], + chartType: visualizes[0]!.chartType, + }, + ], })} > {`${t('Compare Queries')}`} diff --git a/static/app/views/insights/common/components/chartActionDropdown.tsx b/static/app/views/insights/common/components/chartActionDropdown.tsx index 505c2928ed97a0..8eabf8ba1a8dae 100644 --- a/static/app/views/insights/common/components/chartActionDropdown.tsx +++ b/static/app/views/insights/common/components/chartActionDropdown.tsx @@ -1,3 +1,5 @@ +import type {LocationDescriptor} from 'history'; + import type {MenuItemProps} from 'sentry/components/dropdownMenu'; import {DropdownMenu} from 'sentry/components/dropdownMenu'; import {IconEllipsis} from 'sentry/icons'; @@ -73,7 +75,7 @@ export function ChartActionDropdown({ type BaseProps = { alertMenuOptions: MenuItemProps[]; - exploreUrl: string; + exploreUrl: LocationDescriptor; }; export function BaseChartActionDropdown({alertMenuOptions, exploreUrl}: BaseProps) { diff --git a/static/app/views/insights/common/components/widgets/httpResponseCodesChartWidget.tsx b/static/app/views/insights/common/components/widgets/httpResponseCodesChartWidget.tsx index ca5c0dfaf451db..03f085a3bd7ee5 100644 --- a/static/app/views/insights/common/components/widgets/httpResponseCodesChartWidget.tsx +++ b/static/app/views/insights/common/components/widgets/httpResponseCodesChartWidget.tsx @@ -1,14 +1,29 @@ import {MutableSearch} from 'sentry/utils/tokenizeSearch'; +import {useLocation} from 'sentry/utils/useLocation'; +import useOrganization from 'sentry/utils/useOrganization'; +import usePageFilters from 'sentry/utils/usePageFilters'; +import {Dataset} from 'sentry/views/alerts/rules/metric/types'; +import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode'; +import {generateExploreCompareRoute} from 'sentry/views/explore/multiQueryMode/locationUtils'; +import {ChartType} from 'sentry/views/insights/common/components/chart'; +import {BaseChartActionDropdown} from 'sentry/views/insights/common/components/chartActionDropdown'; import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget'; import {useHttpLandingChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpLandingChartFilter'; import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types'; import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; +import {getAlertsUrl} from 'sentry/views/insights/common/utils/getAlertsUrl'; +import {useAlertsProject} from 'sentry/views/insights/common/utils/useAlertsProject'; import {DataTitles} from 'sentry/views/insights/common/views/spans/types'; import {Referrer} from 'sentry/views/insights/http/referrers'; import {FIELD_ALIASES} from 'sentry/views/insights/http/settings'; export default function HttpResponseCodesChartWidget(props: LoadableChartWidgetProps) { const chartFilters = useHttpLandingChartFilter(); + const organization = useOrganization(); + const location = useLocation(); + const project = useAlertsProject(); + const {selection} = usePageFilters(); + const search = MutableSearch.fromQueryObject(chartFilters); const { isPending: isResponseCodeDataLoading, @@ -24,11 +39,60 @@ export default function HttpResponseCodesChartWidget(props: LoadableChartWidgetP props.pageFilters ); + const responseRateField = 'tags[http.response.status_code,number]'; + + const queries = [ + { + yAxes: ['count()'], + label: '3xx', + query: `${responseRateField}:>300 ${responseRateField}:<=399`, + }, + { + yAxes: ['count()'], + label: '4xx', + query: `${responseRateField}:>400 ${responseRateField}:<=499`, + }, + { + yAxes: ['count()'], + label: '5xx', + query: `${responseRateField}:>500 ${responseRateField}:<=599`, + }, + ]; + + const exploreUrl = generateExploreCompareRoute({ + organization, + mode: Mode.AGGREGATE, + location, + queries: queries.map(query => ({ + ...query, + chartType: ChartType.LINE, + })), + }); + + const extraActions = [ + ({ + key: query.label, + label: query.label, + to: getAlertsUrl({ + project, + aggregate: query.yAxes[0]!, + organization, + pageFilters: selection, + dataset: Dataset.EVENTS_ANALYTICS_PLATFORM, + query: query.query, + }), + }))} + />, + ]; + return ( Date: Mon, 9 Jun 2025 10:19:12 -0400 Subject: [PATCH 2/2] fix tests --- static/app/views/explore/toolbar/toolbarSaveAs.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/static/app/views/explore/toolbar/toolbarSaveAs.tsx b/static/app/views/explore/toolbar/toolbarSaveAs.tsx index bd0330555b853d..ced6c765ab9b5c 100644 --- a/static/app/views/explore/toolbar/toolbarSaveAs.tsx +++ b/static/app/views/explore/toolbar/toolbarSaveAs.tsx @@ -293,7 +293,6 @@ export function ToolbarSaveAs() { { query, groupBys, - fields, sortBys, yAxes: [visualizeYAxes[0]!], chartType: visualizes[0]!.chartType,