Skip to content

Commit 074cd4c

Browse files
authored
feat(insights): Refactor chart widgets to pass down prop overrides (#89455)
Inside of the Releases Drawers, we are only viewing a smaller slice of time than the main PageFilters. The chart widgets and their hooks need to support a pageFilters override. I think env/projects should be the same, but I think it will be more consistent to pass around the full pageFilters object. `showReleaseAs` is also needed since we currently show lines inside of the drawer, and bubbles outside of it. Need as part of #88560
1 parent dc8cdfc commit 074cd4c

10 files changed

+87
-29
lines changed

static/app/views/dashboards/widgets/timeSeriesWidget/timeSeriesWidgetVisualization.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import type {
4242
LegendSelection,
4343
Release,
4444
} from 'sentry/views/dashboards/widgets/common/types';
45+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
4546
import {useReleaseBubbles} from 'sentry/views/releases/releaseBubbles/useReleaseBubbles';
4647
import {makeReleasesPathname} from 'sentry/views/releases/utils/pathnames';
4748

@@ -55,7 +56,8 @@ import {TimeSeriesWidgetYAxis} from './timeSeriesWidgetYAxis';
5556

5657
const {error, warn, info} = Sentry.logger;
5758

58-
export interface TimeSeriesWidgetVisualizationProps {
59+
export interface TimeSeriesWidgetVisualizationProps
60+
extends Partial<LoadableChartWidgetProps> {
5961
/**
6062
* An array of `Plottable` objects. This can be any object that implements the `Plottable` interface.
6163
*/
@@ -95,10 +97,6 @@ export interface TimeSeriesWidgetVisualizationProps {
9597
* Default: `auto`
9698
*/
9799
showLegend?: 'auto' | 'never';
98-
/**
99-
* Show releases as either lines per release or a bubble for a group of releases.
100-
*/
101-
showReleaseAs?: 'bubble' | 'line';
102100
}
103101

104102
export function TimeSeriesWidgetVisualization(props: TimeSeriesWidgetVisualizationProps) {
@@ -114,7 +112,8 @@ export function TimeSeriesWidgetVisualization(props: TimeSeriesWidgetVisualizati
114112
const {register: registerWithWidgetSyncContext} = useWidgetSyncContext();
115113

116114
const pageFilters = usePageFilters();
117-
const {start, end, period, utc} = pageFilters.selection.datetime;
115+
const {start, end, period, utc} =
116+
props.pageFilters?.datetime || pageFilters.selection.datetime;
118117

119118
const theme = useTheme();
120119
const organization = useOrganization();

static/app/views/insights/common/components/insightsTimeSeriesWidget.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,21 @@ import {
2828
HTTP_RESPONSE_5XX_COLOR,
2929
THROUGHPUT_COLOR,
3030
} from 'sentry/views/insights/colors';
31+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
3132
import type {DiscoverSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
3233
import {convertSeriesToTimeseries} from 'sentry/views/insights/common/utils/convertSeriesToTimeseries';
3334
import {INGESTION_DELAY} from 'sentry/views/insights/settings';
3435

35-
export interface InsightsTimeSeriesWidgetProps extends WidgetTitleProps {
36+
export interface InsightsTimeSeriesWidgetProps
37+
extends WidgetTitleProps,
38+
LoadableChartWidgetProps {
3639
error: Error | null;
3740
isLoading: boolean;
3841
series: DiscoverSeries[];
3942
visualizationType: 'line' | 'area' | 'bar';
4043
aliases?: Record<string, string>;
4144
description?: React.ReactNode;
4245
height?: string | number;
43-
id?: string;
4446
interactiveTitle?: () => React.ReactNode;
4547
legendSelection?: LegendSelection | undefined;
4648
onLegendSelectionChange?: ((selection: LegendSelection) => void) | undefined;
@@ -52,7 +54,8 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) {
5254
const theme = useTheme();
5355
const organization = useOrganization();
5456
const pageFilters = usePageFilters();
55-
const {releases: releasesWithDate} = useReleaseStats(pageFilters.selection);
57+
const pageFiltersSelection = props.pageFilters || pageFilters.selection;
58+
const {releases: releasesWithDate} = useReleaseStats(pageFiltersSelection);
5659
const releases =
5760
releasesWithDate?.map(({date, version}) => ({
5861
timestamp: date,
@@ -120,7 +123,7 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) {
120123
}
121124

122125
const enableReleaseBubblesProps = organization.features.includes('release-bubbles-ui')
123-
? ({releases, showReleaseAs: 'bubble'} as const)
126+
? ({releases, showReleaseAs: props.showReleaseAs || 'bubble'} as const)
124127
: {};
125128

126129
return (
@@ -129,6 +132,8 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) {
129132
Title={Title}
130133
Visualization={
131134
<TimeSeriesWidgetVisualization
135+
id={props.id}
136+
pageFilters={props.pageFilters}
132137
{...enableReleaseBubblesProps}
133138
legendSelection={props.legendSelection}
134139
onLegendSelectionChange={props.onLegendSelectionChange}
@@ -151,6 +156,7 @@ export function InsightsTimeSeriesWidget(props: InsightsTimeSeriesWidgetProps) {
151156
children: (
152157
<ModalChartContainer>
153158
<TimeSeriesWidgetVisualization
159+
id={props.id}
154160
{...visualizationProps}
155161
{...enableReleaseBubblesProps}
156162
onZoom={() => {}}

static/app/views/insights/common/components/widgets/httpDomainSummaryDurationChartWidget.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpDomainSummaryChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpDomainSummaryChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {getDurationChartTitle} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78
import {SpanMetricsField} from 'sentry/views/insights/types';
89

9-
export default function HttpDomainSummaryDurationChartWidget() {
10+
export default function HttpDomainSummaryDurationChartWidget(
11+
props: LoadableChartWidgetProps
12+
) {
1013
const chartFilters = useHttpDomainSummaryChartFilter();
1114
const {
1215
isPending: isDurationDataLoading,
@@ -18,11 +21,13 @@ export default function HttpDomainSummaryDurationChartWidget() {
1821
yAxis: [`avg(${SpanMetricsField.SPAN_SELF_TIME})`],
1922
transformAliasToInputFormat: true,
2023
},
21-
Referrer.DOMAIN_SUMMARY_DURATION_CHART
24+
Referrer.DOMAIN_SUMMARY_DURATION_CHART,
25+
props.pageFilters
2226
);
2327

2428
return (
2529
<InsightsLineChartWidget
30+
{...props}
2631
id="httpDomainSummaryDurationChartWidget"
2732
title={getDurationChartTitle('http')}
2833
series={[durationData[`avg(${SpanMetricsField.SPAN_SELF_TIME})`]]}

static/app/views/insights/common/components/widgets/httpDomainSummaryResponseCodesChartWidget.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpDomainSummaryChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpDomainSummaryChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {DataTitles} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78
import {FIELD_ALIASES} from 'sentry/views/insights/http/settings';
89

9-
export default function HttpDomainSummaryResponseCodesWidget() {
10+
export default function HttpDomainSummaryResponseCodesChartWidget(
11+
props: LoadableChartWidgetProps
12+
) {
1013
const chartFilters = useHttpDomainSummaryChartFilter();
1114
const {
1215
isPending: isResponseCodeDataLoading,
@@ -18,12 +21,14 @@ export default function HttpDomainSummaryResponseCodesWidget() {
1821
yAxis: ['http_response_rate(3)', 'http_response_rate(4)', 'http_response_rate(5)'],
1922
transformAliasToInputFormat: true,
2023
},
21-
Referrer.DOMAIN_SUMMARY_RESPONSE_CODE_CHART
24+
Referrer.DOMAIN_SUMMARY_RESPONSE_CODE_CHART,
25+
props.pageFilters
2226
);
2327

2428
return (
2529
<InsightsLineChartWidget
26-
id="httpDomainSummaryResponseCodesWidget"
30+
{...props}
31+
id="httpDomainSummaryResponseCodesChartWidget"
2732
title={DataTitles.unsuccessfulHTTPCodes}
2833
series={[
2934
responseCodeData[`http_response_rate(3)`],

static/app/views/insights/common/components/widgets/httpDomainSummaryThroughputChartWidget.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpDomainSummaryChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpDomainSummaryChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {getThroughputChartTitle} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78

8-
export default function HttpDomainSummaryThroughputChartWidget() {
9+
export default function HttpDomainSummaryThroughputChartWidget(
10+
props: LoadableChartWidgetProps
11+
) {
912
const chartFilters = useHttpDomainSummaryChartFilter();
1013
const {
1114
isPending: isThroughputDataLoading,
@@ -17,11 +20,13 @@ export default function HttpDomainSummaryThroughputChartWidget() {
1720
yAxis: ['epm()'],
1821
transformAliasToInputFormat: true,
1922
},
20-
Referrer.DOMAIN_SUMMARY_THROUGHPUT_CHART
23+
Referrer.DOMAIN_SUMMARY_THROUGHPUT_CHART,
24+
props.pageFilters
2125
);
2226

2327
return (
2428
<InsightsLineChartWidget
29+
{...props}
2530
id="httpDomainSummaryThroughputChartWidget"
2631
title={getThroughputChartTitle('http')}
2732
series={[throughputData['epm()']]}

static/app/views/insights/common/components/widgets/httpDurationChartWidget.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpLandingChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpLandingChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {getDurationChartTitle} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78

8-
export default function HttpDurationChartWidget() {
9+
export default function HttpDurationChartWidget(props: LoadableChartWidgetProps) {
910
const chartFilters = useHttpLandingChartFilter();
1011
const {
1112
isPending: isDurationDataLoading,
@@ -17,11 +18,13 @@ export default function HttpDurationChartWidget() {
1718
yAxis: ['avg(span.self_time)'],
1819
transformAliasToInputFormat: true,
1920
},
20-
Referrer.LANDING_DURATION_CHART
21+
Referrer.LANDING_DURATION_CHART,
22+
props.pageFilters
2123
);
2224

2325
return (
2426
<InsightsLineChartWidget
27+
{...props}
2528
id="httpDurationChartWidget"
2629
title={getDurationChartTitle('http')}
2730
series={[durationData['avg(span.self_time)']]}

static/app/views/insights/common/components/widgets/httpResponseCodesChartWidget.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpLandingChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpLandingChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {DataTitles} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78
import {FIELD_ALIASES} from 'sentry/views/insights/http/settings';
89

9-
export default function HttpResponseCodesChartWidget() {
10+
export default function HttpResponseCodesChartWidget(props: LoadableChartWidgetProps) {
1011
const chartFilters = useHttpLandingChartFilter();
1112
const {
1213
isPending: isResponseCodeDataLoading,
@@ -18,11 +19,13 @@ export default function HttpResponseCodesChartWidget() {
1819
yAxis: ['http_response_rate(3)', 'http_response_rate(4)', 'http_response_rate(5)'],
1920
transformAliasToInputFormat: true,
2021
},
21-
Referrer.LANDING_RESPONSE_CODE_CHART
22+
Referrer.LANDING_RESPONSE_CODE_CHART,
23+
props.pageFilters
2224
);
2325

2426
return (
2527
<InsightsLineChartWidget
28+
{...props}
2629
id="httpResponseCodesChartWidget"
2730
title={DataTitles.unsuccessfulHTTPCodes}
2831
series={[

static/app/views/insights/common/components/widgets/httpThroughputChartWidget.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
22
import {InsightsLineChartWidget} from 'sentry/views/insights/common/components/insightsLineChartWidget';
33
import {useHttpLandingChartFilter} from 'sentry/views/insights/common/components/widgets/hooks/useHttpLandingChartFilter';
4+
import type {LoadableChartWidgetProps} from 'sentry/views/insights/common/components/widgets/types';
45
import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
56
import {getThroughputChartTitle} from 'sentry/views/insights/common/views/spans/types';
67
import {Referrer} from 'sentry/views/insights/http/referrers';
78

8-
export default function HttpThroughputChartWidget() {
9+
export default function HttpThroughputChartWidget(props: LoadableChartWidgetProps) {
910
const chartFilters = useHttpLandingChartFilter();
1011
const {
1112
isPending: isThroughputDataLoading,
@@ -17,11 +18,13 @@ export default function HttpThroughputChartWidget() {
1718
yAxis: ['epm()'],
1819
transformAliasToInputFormat: true,
1920
},
20-
Referrer.LANDING_THROUGHPUT_CHART
21+
Referrer.LANDING_THROUGHPUT_CHART,
22+
props.pageFilters
2123
);
2224

2325
return (
2426
<InsightsLineChartWidget
27+
{...props}
2528
id="httpThroughputChartWidget"
2629
title={getThroughputChartTitle('http')}
2730
series={[throughputData['epm()']]}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type {PageFilters} from 'sentry/types/core';
2+
3+
/**
4+
* These props are common across components that are required to dynamically
5+
* render an Insight Chart Widget
6+
*/
7+
export interface LoadableChartWidgetProps {
8+
// TODO(billy): This should be required when all chart widgets are converted
9+
/**
10+
* Unique ID for the widget
11+
*/
12+
id?: string;
13+
14+
/**
15+
* PageFilters-like object that will override the main PageFilters e.g. in
16+
* Releases Drawer, we have a smaller timeframe to show a smaller amount of
17+
* releases.
18+
*/
19+
pageFilters?: PageFilters;
20+
21+
/**
22+
* Show releases as either lines per release or a bubble for a group of releases.
23+
*/
24+
showReleaseAs?: 'bubble' | 'line';
25+
}

static/app/views/insights/common/queries/useDiscoverSeries.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import moment from 'moment-timezone';
22

3+
import type {PageFilters} from 'sentry/types/core';
34
import type {Series} from 'sentry/types/echarts';
45
import {encodeSort, type EventsMetaType} from 'sentry/utils/discover/eventView';
56
import {
@@ -51,13 +52,15 @@ interface UseMetricsSeriesOptions<Fields> {
5152

5253
export const useSpanMetricsSeries = <Fields extends SpanMetricsProperty[]>(
5354
options: UseMetricsSeriesOptions<Fields> = {},
54-
referrer: string
55+
referrer: string,
56+
pageFilters?: PageFilters
5557
) => {
5658
const useEap = useInsightsEap();
5759
return useDiscoverSeries<Fields>(
5860
options,
5961
useEap ? DiscoverDatasets.SPANS_EAP_RPC : DiscoverDatasets.SPANS_METRICS,
60-
referrer
62+
referrer,
63+
pageFilters
6164
);
6265
};
6366

@@ -108,7 +111,8 @@ export const useSpanIndexedSeries = <
108111
const useDiscoverSeries = <T extends string[]>(
109112
options: UseMetricsSeriesOptions<T> = {},
110113
dataset: DiscoverDatasets,
111-
referrer: string
114+
referrer: string,
115+
pageFilters?: PageFilters
112116
) => {
113117
const {
114118
search = undefined,
@@ -117,7 +121,7 @@ const useDiscoverSeries = <T extends string[]>(
117121
samplingMode = DEFAULT_SAMPLING_MODE,
118122
} = options;
119123

120-
const pageFilters = usePageFilters();
124+
const defaultPageFilters = usePageFilters();
121125
const location = useLocation();
122126
const organization = useOrganization();
123127

@@ -127,7 +131,7 @@ const useDiscoverSeries = <T extends string[]>(
127131
const eventView = getSeriesEventView(
128132
search,
129133
undefined,
130-
pageFilters.selection,
134+
pageFilters || defaultPageFilters.selection,
131135
yAxis,
132136
undefined,
133137
dataset
@@ -161,7 +165,7 @@ const useDiscoverSeries = <T extends string[]>(
161165
samplingMode === 'NONE' || !shouldSetSamplingMode ? undefined : samplingMode,
162166
}),
163167
options: {
164-
enabled: options.enabled && pageFilters.isReady,
168+
enabled: options.enabled && defaultPageFilters.isReady,
165169
refetchOnWindowFocus: false,
166170
retry: shouldRetryHandler,
167171
retryDelay: getRetryDelay,

0 commit comments

Comments
 (0)