Skip to content

Commit 7d2afd7

Browse files
authored
feat(tracemetrics): Show applicable group by options (#101277)
Connect the group by options by making a request to `trace-items` for attributes under the specific metric name. Also adds in some quick UI cleanup by removing dummy metric options and debug info I had to update the `useTraceItemAttributeKeys` to take a query prop and pass it along to the request.
1 parent 16bb8d8 commit 7d2afd7

File tree

6 files changed

+101
-26
lines changed

6 files changed

+101
-26
lines changed

static/app/views/explore/components/attributeDetails.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export function AttributeDetails({
3131
);
3232
}
3333

34-
function traceItemTypeToType(traceItemType: TraceItemDataset): 'span' | 'log' {
34+
function traceItemTypeToType(
35+
traceItemType: TraceItemDataset
36+
): 'span' | 'log' | 'tracemetric' {
3537
if (traceItemType === TraceItemDataset.SPANS) {
3638
return 'span' as const;
3739
}
@@ -40,6 +42,10 @@ function traceItemTypeToType(traceItemType: TraceItemDataset): 'span' | 'log' {
4042
return 'log' as const;
4143
}
4244

45+
if (traceItemType === TraceItemDataset.TRACEMETRICS) {
46+
return 'tracemetric' as const;
47+
}
48+
4349
throw new Error('Cannot convert unknown trace item type to type');
4450
}
4551

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414

1515
interface UseGetTraceItemAttributeKeysProps extends UseTraceItemAttributeBaseProps {
1616
projectIds?: Array<string | number>;
17+
query?: string;
1718
}
1819

1920
type TraceItemAttributeKeyOptions = Pick<
@@ -23,6 +24,7 @@ type TraceItemAttributeKeyOptions = Pick<
2324
attributeType: 'string' | 'number';
2425
itemType: TraceItemDataset;
2526
project?: string[];
27+
query?: string;
2628
substringMatch?: string;
2729
};
2830

@@ -32,17 +34,20 @@ export function makeTraceItemAttributeKeysQueryOptions({
3234
datetime,
3335
projectIds,
3436
search,
37+
query,
3538
}: {
3639
datetime: PageFilters['datetime'];
3740
traceItemType: TraceItemDataset;
3841
type: 'string' | 'number';
3942
projectIds?: Array<string | number>;
43+
query?: string;
4044
search?: string;
4145
}): TraceItemAttributeKeyOptions {
4246
const options: TraceItemAttributeKeyOptions = {
4347
itemType: traceItemType,
4448
attributeType: type,
4549
project: projectIds?.map(String),
50+
query,
4651
substringMatch: search,
4752
...normalizeDateTimeParams(datetime),
4853
};
@@ -56,6 +61,7 @@ export function useGetTraceItemAttributeKeys({
5661
traceItemType,
5762
projectIds,
5863
type,
64+
query,
5965
}: UseGetTraceItemAttributeKeysProps) {
6066
const api = useApi();
6167
const organization = useOrganization();
@@ -69,6 +75,7 @@ export function useGetTraceItemAttributeKeys({
6975
datetime: selection.datetime,
7076
projectIds: projectIds ?? selection.projects,
7177
search: queryString,
78+
query,
7279
});
7380

7481
let result: Tag[];
@@ -87,7 +94,7 @@ export function useGetTraceItemAttributeKeys({
8794

8895
return getTraceItemTagCollection(result, type);
8996
},
90-
[api, organization, selection, traceItemType, projectIds, type]
97+
[api, organization, selection, traceItemType, projectIds, type, query]
9198
);
9299

93100
return getTraceItemAttributeKeys;

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import type {UseTraceItemAttributeBaseProps} from 'sentry/views/explore/types';
1313

1414
interface UseTraceItemAttributeKeysProps extends UseTraceItemAttributeBaseProps {
1515
enabled?: boolean;
16+
query?: string;
1617
}
1718

1819
export function useTraceItemAttributeKeys({
1920
enabled,
2021
type,
2122
traceItemType,
2223
projects,
24+
query,
2325
}: UseTraceItemAttributeKeysProps) {
2426
const {selection} = usePageFilters();
2527

@@ -33,8 +35,9 @@ export function useTraceItemAttributeKeys({
3335
type,
3436
datetime: selection.datetime,
3537
projectIds,
38+
query,
3639
});
37-
}, [selection, traceItemType, type, projectIds]);
40+
}, [selection, traceItemType, type, projectIds, query]);
3841

3942
const queryKey = useMemo(
4043
() => ['use-trace-item-attribute-keys', queryOptions],
@@ -45,6 +48,7 @@ export function useTraceItemAttributeKeys({
4548
traceItemType,
4649
type,
4750
projectIds,
51+
query,
4852
});
4953

5054
const {data, isFetching, error} = useQuery<TagCollection>({

static/app/views/explore/metrics/metricPanel.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import {DiscoverDatasets} from 'sentry/utils/discover/types';
88
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
99
import {useDimensions} from 'sentry/utils/useDimensions';
1010
import {useChartInterval} from 'sentry/views/explore/hooks/useChartInterval';
11+
import {useTopEvents} from 'sentry/views/explore/hooks/useTopEvents';
1112
import {MetricsGraph} from 'sentry/views/explore/metrics/metricGraph';
1213
import MetricInfoTabs from 'sentry/views/explore/metrics/metricInfoTabs';
1314
import {type TraceMetric} from 'sentry/views/explore/metrics/metricQuery';
1415
import {MetricRow} from 'sentry/views/explore/metrics/metricRow';
1516
import {useMetricVisualize} from 'sentry/views/explore/metrics/metricsQueryParams';
17+
import {useQueryParamsGroupBys} from 'sentry/views/explore/queryParams/context';
1618
import {useSortedTimeSeries} from 'sentry/views/insights/common/queries/useSortedTimeSeries';
1719

1820
interface MetricPanelProps {
@@ -24,17 +26,20 @@ const MIN_RIGHT_WIDTH = 400;
2426

2527
export function MetricPanel({traceMetric}: MetricPanelProps) {
2628
const visualize = useMetricVisualize();
29+
const groupBys = useQueryParamsGroupBys();
2730
const measureRef = useRef<HTMLDivElement>(null);
2831
const {width} = useDimensions({elementRef: measureRef});
2932
const [interval] = useChartInterval();
33+
const topEvents = useTopEvents();
3034

3135
const timeseriesResult = useSortedTimeSeries(
3236
{
3337
search: new MutableSearch(`metric.name:${traceMetric.name}`),
3438
yAxis: [visualize.yAxis],
3539
interval,
36-
fields: [],
40+
fields: [...groupBys],
3741
enabled: Boolean(traceMetric.name),
42+
topEvents,
3843
},
3944
'api.explore.metrics-stats',
4045
DiscoverDatasets.TRACEMETRICS
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import {CompactSelect} from 'sentry/components/core/compactSelect';
2+
import type {SelectOption} from 'sentry/components/core/compactSelect/types';
3+
import LoadingIndicator from 'sentry/components/loadingIndicator';
4+
import {MutableSearch} from 'sentry/components/searchSyntax/mutableSearch';
5+
import {useGroupByFields} from 'sentry/views/explore/hooks/useGroupByFields';
6+
import {useTraceItemAttributeKeys} from 'sentry/views/explore/hooks/useTraceItemAttributeKeys';
7+
import {
8+
useQueryParamsGroupBys,
9+
useSetQueryParamsGroupBys,
10+
} from 'sentry/views/explore/queryParams/context';
11+
import {TraceItemDataset} from 'sentry/views/explore/types';
12+
13+
interface GroupBySelectorProps {
14+
/**
15+
* The metric name to filter attributes by
16+
*/
17+
metricName: string;
18+
}
19+
20+
/**
21+
* A selector component for choosing metric group by attributes.
22+
* Fetches available attribute keys from the trace-items API endpoint
23+
* and displays them as options in a compact select dropdown.
24+
*/
25+
export function GroupBySelector({metricName}: GroupBySelectorProps) {
26+
const groupBys = useQueryParamsGroupBys();
27+
const setGroupBys = useSetQueryParamsGroupBys();
28+
29+
const metricNameFilter = metricName
30+
? MutableSearch.fromQueryObject({['metric.name']: [metricName]}).formatString()
31+
: undefined;
32+
33+
const {attributes: numberTags, isLoading: numberTagsLoading} =
34+
useTraceItemAttributeKeys({
35+
traceItemType: TraceItemDataset.TRACEMETRICS,
36+
type: 'number',
37+
enabled: Boolean(metricNameFilter),
38+
query: metricNameFilter,
39+
});
40+
const {attributes: stringTags, isLoading: stringTagsLoading} =
41+
useTraceItemAttributeKeys({
42+
traceItemType: TraceItemDataset.TRACEMETRICS,
43+
type: 'string',
44+
enabled: Boolean(metricNameFilter),
45+
query: metricNameFilter,
46+
});
47+
48+
const enabledOptions: Array<SelectOption<string>> = useGroupByFields({
49+
groupBys: [],
50+
numberTags: numberTags ?? {},
51+
stringTags: stringTags ?? {},
52+
traceItemType: TraceItemDataset.TRACEMETRICS,
53+
hideEmptyOption: true,
54+
});
55+
56+
const isLoading = numberTagsLoading || stringTagsLoading;
57+
const triggerLabel = isLoading ? <LoadingIndicator size={16} /> : undefined;
58+
59+
return (
60+
<CompactSelect<string>
61+
multiple
62+
searchable
63+
options={enabledOptions}
64+
value={[...groupBys]}
65+
disabled={isLoading || enabledOptions.length === 0}
66+
triggerProps={triggerLabel ? {children: triggerLabel} : undefined}
67+
onChange={selectedOptions => {
68+
setGroupBys(selectedOptions.map(option => option.value));
69+
}}
70+
/>
71+
);
72+
}

static/app/views/explore/metrics/metricRow/index.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@ import {
1212
import {useMetricOptions} from 'sentry/views/explore/hooks/useMetricOptions';
1313
import {type TraceMetric} from 'sentry/views/explore/metrics/metricQuery';
1414
import {AggregateDropdown} from 'sentry/views/explore/metrics/metricRow/aggregateDropdown';
15+
import {GroupBySelector} from 'sentry/views/explore/metrics/metricRow/groupBySelector';
16+
import {useSetMetricName} from 'sentry/views/explore/metrics/metricsQueryParams';
1517
import {
16-
useMetricVisualize,
17-
useSetMetricName,
18-
} from 'sentry/views/explore/metrics/metricsQueryParams';
19-
import {
20-
useQueryParamsGroupBys,
2118
useQueryParamsQuery,
2219
useSetQueryParamsQuery,
2320
} from 'sentry/views/explore/queryParams/context';
@@ -67,9 +64,6 @@ function MetricToolbar({
6764
tracesItemSearchQueryBuilderProps,
6865
traceMetric,
6966
}: MetricToolbarProps) {
70-
const visualize = useMetricVisualize();
71-
const groupBys = useQueryParamsGroupBys();
72-
const query = useQueryParamsQuery();
7367
const {data: metricOptionsData} = useMetricOptions();
7468
const setMetricName = useSetMetricName();
7569

@@ -80,18 +74,6 @@ function MetricToolbar({
8074
value: option['metric.name'],
8175
type: option['metric.type'],
8276
})) ?? []),
83-
// TODO(nar): Remove these when we actually have metrics served
84-
// This is only used for providing an option to test current selection behavior
85-
{
86-
label: 'test-distribution',
87-
value: 'test-distribution',
88-
type: 'distribution' as const,
89-
},
90-
{
91-
label: 'test-gauge',
92-
value: 'test-gauge',
93-
type: 'gauge' as const,
94-
},
9577
];
9678
}, [metricOptionsData]);
9779

@@ -103,7 +85,6 @@ function MetricToolbar({
10385

10486
return (
10587
<div style={{width: '100%'}}>
106-
{traceMetric.name}/{visualize.yAxis}/ by {groupBys.join(',')}/ where {query}
10788
<Flex direction="row" gap="md" align="center">
10889
{t('Query')}
10990
<CompactSelect
@@ -115,7 +96,7 @@ function MetricToolbar({
11596
/>
11697
<AggregateDropdown type={currentMetricType} />
11798
{t('by')}
118-
<CompactSelect options={[]} value={groupBys[0] ?? ''} />
99+
<GroupBySelector metricName={traceMetric.name} />
119100
{t('where')}
120101
<TraceItemSearchQueryBuilder {...tracesItemSearchQueryBuilderProps} />
121102
</Flex>

0 commit comments

Comments
 (0)