Skip to content

Commit bf759d4

Browse files
authored
feat(compare): Add analytics for query metadata (#85909)
Add analytics for queries in compare. Lift data fetch one component so we can pass the data to the analytics hook
1 parent 2f42fdb commit bf759d4

File tree

8 files changed

+186
-53
lines changed

8 files changed

+186
-53
lines changed

static/app/utils/analytics/tracingEventMap.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type TracingEventParameters = {
1616
confidences: string[];
1717
dataset: string;
1818
has_exceeded_performance_usage_limit: boolean | null;
19+
page_source: 'explore' | 'compare';
1920
query_status: 'success' | 'error' | 'pending';
2021
result_length: number;
2122
result_missing_root: number;

static/app/views/explore/hooks/useAnalytics.tsx

+104-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {useEffect} from 'react';
33
import {defined} from 'sentry/utils';
44
import {trackAnalytics} from 'sentry/utils/analytics';
55
import {dedupeArray} from 'sentry/utils/dedupeArray';
6+
import {DiscoverDatasets} from 'sentry/utils/discover/types';
67
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
78
import useOrganization from 'sentry/utils/useOrganization';
89
import {
@@ -16,29 +17,37 @@ import type {Visualize} from 'sentry/views/explore/contexts/pageParamsContext/vi
1617
import type {AggregatesTableResult} from 'sentry/views/explore/hooks/useExploreAggregatesTable';
1718
import type {SpansTableResult} from 'sentry/views/explore/hooks/useExploreSpansTable';
1819
import type {TracesTableResult} from 'sentry/views/explore/hooks/useExploreTracesTable';
20+
import type {ReadableExploreQueryParts} from 'sentry/views/explore/multiQueryMode/locationUtils';
1921
import {combineConfidenceForSeries} from 'sentry/views/explore/utils';
2022
import type {useSortedTimeSeries} from 'sentry/views/insights/common/queries/useSortedTimeSeries';
2123
import {usePerformanceSubscriptionDetails} from 'sentry/views/performance/newTraceDetails/traceTypeWarnings/usePerformanceSubscriptionDetails';
2224

23-
export function useAnalytics({
25+
export function useTrackAnalytics({
2426
queryType,
2527
aggregatesTableResult,
2628
spansTableResult,
2729
tracesTableResult,
2830
timeseriesResult,
31+
dataset,
32+
title,
33+
query,
34+
fields,
35+
visualizes,
36+
page_source,
2937
}: {
3038
aggregatesTableResult: AggregatesTableResult;
39+
dataset: DiscoverDatasets;
40+
fields: string[];
41+
page_source: 'explore' | 'compare';
42+
query: string;
3143
queryType: 'aggregate' | 'samples' | 'traces';
3244
spansTableResult: SpansTableResult;
3345
timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
34-
tracesTableResult: TracesTableResult;
46+
visualizes: Visualize[];
47+
title?: string;
48+
tracesTableResult?: TracesTableResult;
3549
}) {
3650
const organization = useOrganization();
37-
const dataset = useExploreDataset();
38-
const title = useExploreTitle();
39-
const query = useExploreQuery();
40-
const fields = useExploreFields();
41-
const visualizes = useExploreVisualizes();
4251

4352
const {
4453
data: {hasExceededPerformanceUsageLimit},
@@ -49,7 +58,7 @@ export function useAnalytics({
4958
queryType === 'aggregate'
5059
? aggregatesTableResult.result.error?.message ?? ''
5160
: queryType === 'traces'
52-
? tracesTableResult.result.error?.message ?? ''
61+
? tracesTableResult?.result.error?.message ?? ''
5362
: spansTableResult.result.error?.message ?? '';
5463
const chartError = timeseriesResult.error?.message ?? '';
5564
const query_status = tableError || chartError ? 'error' : 'success';
@@ -85,6 +94,7 @@ export function useAnalytics({
8594
title: title || '',
8695
confidences: computeConfidence(visualizes, timeseriesResult.data),
8796
has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
97+
page_source,
8898
});
8999
}, [
90100
organization,
@@ -103,6 +113,7 @@ export function useAnalytics({
103113
hasExceededPerformanceUsageLimit,
104114
isLoadingSubscriptionDetails,
105115
query_status,
116+
page_source,
106117
]);
107118

108119
useEffect(() => {
@@ -132,6 +143,7 @@ export function useAnalytics({
132143
title: title || '',
133144
confidences: computeConfidence(visualizes, timeseriesResult.data),
134145
has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
146+
page_source,
135147
});
136148
}, [
137149
organization,
@@ -149,10 +161,14 @@ export function useAnalytics({
149161
hasExceededPerformanceUsageLimit,
150162
isLoadingSubscriptionDetails,
151163
query_status,
164+
page_source,
152165
]);
153166

167+
const tracesTableResultDefined = defined(tracesTableResult);
168+
154169
useEffect(() => {
155170
if (
171+
!tracesTableResultDefined ||
156172
queryType !== 'traces' ||
157173
tracesTableResult.result.isPending ||
158174
timeseriesResult.isPending ||
@@ -171,7 +187,7 @@ export function useAnalytics({
171187
'timestamp',
172188
];
173189
const resultMissingRoot =
174-
tracesTableResult.result?.data?.data?.filter(trace => !defined(trace.name))
190+
tracesTableResult?.result?.data?.data?.filter(trace => !defined(trace.name))
175191
.length ?? 0;
176192

177193
trackAnalytics('trace.explorer.metadata', {
@@ -190,6 +206,7 @@ export function useAnalytics({
190206
title: title || '',
191207
confidences: computeConfidence(visualizes, timeseriesResult.data),
192208
has_exceeded_performance_usage_limit: hasExceededPerformanceUsageLimit,
209+
page_source,
193210
});
194211
}, [
195212
organization,
@@ -199,17 +216,92 @@ export function useAnalytics({
199216
visualizes,
200217
title,
201218
queryType,
202-
tracesTableResult.result.isPending,
203-
tracesTableResult.result.status,
204-
tracesTableResult.result.data?.data,
219+
tracesTableResult?.result.isPending,
220+
tracesTableResult?.result.status,
221+
tracesTableResult?.result.data?.data,
205222
timeseriesResult.isPending,
206223
timeseriesResult.data,
207224
hasExceededPerformanceUsageLimit,
208225
isLoadingSubscriptionDetails,
209226
query_status,
227+
page_source,
228+
tracesTableResultDefined,
210229
]);
211230
}
212231

232+
export function useAnalytics({
233+
queryType,
234+
aggregatesTableResult,
235+
spansTableResult,
236+
tracesTableResult,
237+
timeseriesResult,
238+
}: {
239+
aggregatesTableResult: AggregatesTableResult;
240+
queryType: 'aggregate' | 'samples' | 'traces';
241+
spansTableResult: SpansTableResult;
242+
timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
243+
tracesTableResult: TracesTableResult;
244+
}) {
245+
const dataset = useExploreDataset();
246+
const title = useExploreTitle();
247+
const query = useExploreQuery();
248+
const fields = useExploreFields();
249+
const visualizes = useExploreVisualizes();
250+
251+
return useTrackAnalytics({
252+
queryType,
253+
aggregatesTableResult,
254+
spansTableResult,
255+
tracesTableResult,
256+
timeseriesResult,
257+
dataset,
258+
title,
259+
query,
260+
fields,
261+
visualizes,
262+
page_source: 'explore',
263+
});
264+
}
265+
266+
export function useCompareAnalytics({
267+
query: queryParts,
268+
index,
269+
queryType,
270+
aggregatesTableResult,
271+
spansTableResult,
272+
timeseriesResult,
273+
}: {
274+
aggregatesTableResult: AggregatesTableResult;
275+
index: number;
276+
query: ReadableExploreQueryParts;
277+
queryType: 'aggregate' | 'samples' | 'traces';
278+
spansTableResult: SpansTableResult;
279+
timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
280+
}) {
281+
const dataset = DiscoverDatasets.SPANS_EAP_RPC;
282+
const query = queryParts.query;
283+
const fields = queryParts.fields;
284+
const visualizes = queryParts.yAxes.map(yAxis => {
285+
return {
286+
chartType: queryParts.chartType,
287+
yAxes: [yAxis],
288+
label: String(index),
289+
} as Visualize;
290+
});
291+
292+
return useTrackAnalytics({
293+
queryType,
294+
aggregatesTableResult,
295+
spansTableResult,
296+
timeseriesResult,
297+
dataset,
298+
query,
299+
fields,
300+
visualizes,
301+
page_source: 'compare',
302+
});
303+
}
304+
213305
function computeConfidence(
214306
visualizes: Visualize[],
215307
data: ReturnType<typeof useSortedTimeSeries>['data']

static/app/views/explore/multiQueryMode/content.spec.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,9 @@ describe('MultiQueryModeContent', function () {
565565
);
566566

567567
const section = screen.getByTestId('section-visualization-0');
568-
expect(await screen.findByTestId('loading-indicator')).not.toBeInTheDocument();
568+
expect(
569+
await within(section).findByRole('button', {name: '1 hour'})
570+
).toBeInTheDocument();
569571
await userEvent.click(within(section).getByRole('button', {name: '1 hour'}));
570572
await userEvent.click(within(section).getByRole('option', {name: '30 minutes'}));
571573
expect(router.push).toHaveBeenCalledWith({

static/app/views/explore/multiQueryMode/hooks/useMultiQueryTable.tsx

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {DiscoverDatasets} from 'sentry/utils/discover/types';
77
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
88
import usePageFilters from 'sentry/utils/usePageFilters';
99
import {formatSort} from 'sentry/views/explore/contexts/pageParamsContext/sortBys';
10+
import type {AggregatesTableResult} from 'sentry/views/explore/hooks/useExploreAggregatesTable';
11+
import type {SpansTableResult} from 'sentry/views/explore/hooks/useExploreSpansTable';
1012
import {getFieldsForConstructedQuery} from 'sentry/views/explore/multiQueryMode/locationUtils';
1113
import {useSpansQuery} from 'sentry/views/insights/common/queries/useSpansQuery';
1214

@@ -24,7 +26,7 @@ export function useMultiQueryTableAggregateMode({
2426
yAxes,
2527
sortBys,
2628
enabled,
27-
}: Props) {
29+
}: Props): AggregatesTableResult {
2830
const {selection} = usePageFilters();
2931

3032
const fields = useMemo(() => {
@@ -73,7 +75,12 @@ export function useMultiQueryTableAggregateMode({
7375
return {eventView, fields, result};
7476
}
7577

76-
export function useMultiQueryTableSampleMode({query, yAxes, sortBys, enabled}: Props) {
78+
export function useMultiQueryTableSampleMode({
79+
query,
80+
yAxes,
81+
sortBys,
82+
enabled,
83+
}: Props): SpansTableResult {
7784
const {selection} = usePageFilters();
7885

7986
const fields = useMemo(() => {
@@ -112,5 +119,5 @@ export function useMultiQueryTableSampleMode({query, yAxes, sortBys, enabled}: P
112119
trackResponseAnalytics: false,
113120
});
114121

115-
return {eventView, fields, result};
122+
return {eventView, result};
116123
}

static/app/views/explore/multiQueryMode/hooks/useMultiQueryTimeseries.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface UseMultiQueryTimeseriesOptions {
1818
index: number;
1919
}
2020

21-
interface UseMultiQueryTimeseriesResults {
21+
export interface UseMultiQueryTimeseriesResults {
2222
canUsePreviousResults: boolean;
2323
timeseriesResult: ReturnType<typeof useSortedTimeSeries>;
2424
}

static/app/views/explore/multiQueryMode/queryRow.tsx

+47-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import {LazyRender} from 'sentry/components/lazyRender';
66
import {IconDelete} from 'sentry/icons/iconDelete';
77
import {t} from 'sentry/locale';
88
import {space} from 'sentry/styles/space';
9+
import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode';
10+
import {useCompareAnalytics} from 'sentry/views/explore/hooks/useAnalytics';
11+
import {
12+
useMultiQueryTableAggregateMode,
13+
useMultiQueryTableSampleMode,
14+
} from 'sentry/views/explore/multiQueryMode/hooks/useMultiQueryTable';
15+
import {useMultiQueryTimeseries} from 'sentry/views/explore/multiQueryMode/hooks/useMultiQueryTimeseries';
916
import {
1017
getQueryMode,
1118
type ReadableExploreQueryParts,
@@ -27,9 +34,39 @@ type Props = {
2734
export function QueryRow({query: queryParts, index, totalQueryRows}: Props) {
2835
const deleteQuery = useDeleteQueryAtIndex();
2936

30-
const {groupBys} = queryParts;
37+
const {groupBys, query, yAxes, sortBys} = queryParts;
3138
const mode = getQueryMode(groupBys);
3239

40+
const aggregatesTableResult = useMultiQueryTableAggregateMode({
41+
groupBys,
42+
query,
43+
yAxes,
44+
sortBys,
45+
enabled: mode === Mode.AGGREGATE,
46+
});
47+
48+
const spansTableResult = useMultiQueryTableSampleMode({
49+
groupBys,
50+
query,
51+
yAxes,
52+
sortBys,
53+
enabled: mode === Mode.SAMPLES,
54+
});
55+
56+
const {timeseriesResult, canUsePreviousResults} = useMultiQueryTimeseries({
57+
index,
58+
enabled: true,
59+
});
60+
61+
useCompareAnalytics({
62+
aggregatesTableResult,
63+
index,
64+
query: queryParts,
65+
spansTableResult,
66+
timeseriesResult,
67+
queryType: mode === Mode.AGGREGATE ? 'aggregate' : 'samples',
68+
});
69+
3370
return (
3471
<Fragment>
3572
<QueryConstructionSection>
@@ -50,12 +87,20 @@ export function QueryRow({query: queryParts, index, totalQueryRows}: Props) {
5087
</QueryConstructionSection>
5188
<QueryVisualizationSection data-test-id={`section-visualization-${index}`}>
5289
<LazyRender containerHeight={260} withoutContainer>
53-
<MultiQueryModeChart index={index} mode={mode} query={queryParts} />
90+
<MultiQueryModeChart
91+
index={index}
92+
mode={mode}
93+
query={queryParts}
94+
timeseriesResult={timeseriesResult}
95+
canUsePreviousResults={canUsePreviousResults}
96+
/>
5497
<MultiQueryTable
5598
confidences={[]}
5699
mode={mode}
57100
query={queryParts}
58101
index={index}
102+
aggregatesTableResult={aggregatesTableResult}
103+
spansTableResult={spansTableResult}
59104
/>
60105
</LazyRender>
61106
</QueryVisualizationSection>

0 commit comments

Comments
 (0)