Skip to content

Commit a5c52b9

Browse files
authored
chore(comp workflows): Hint for Distributions (#102761)
- Include hint for distributions which explains how the cohorts are selected For non-percentile/avg functions, we compare the time segments directly <img width="1044" height="198" alt="image" src="https://github.com/user-attachments/assets/70c1f230-b960-43e7-aad8-8e74a4384cf2" /> For percentile/avg functions, we also segment by the numerical attr <img width="1052" height="210" alt="image" src="https://github.com/user-attachments/assets/b16a2a2f-722f-412c-89fd-684524380caf" />
1 parent c3166f9 commit a5c52b9

File tree

1 file changed

+74
-0
lines changed
  • static/app/views/explore/components/attributeBreakdowns

1 file changed

+74
-0
lines changed

static/app/views/explore/components/attributeBreakdowns/content.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Fragment, useEffect, useMemo, useState} from 'react';
22
import {useTheme} from '@emotion/react';
33
import styled from '@emotion/styled';
4+
import moment from 'moment-timezone';
45

56
import emptyTraceImg from 'sentry-images/spot/performance-empty-trace.svg';
67

@@ -17,18 +18,21 @@ import {IconChevron} from 'sentry/icons/iconChevron';
1718
import {IconMegaphone} from 'sentry/icons/iconMegaphone';
1819
import {t} from 'sentry/locale';
1920
import {space} from 'sentry/styles/space';
21+
import {getUserTimezone} from 'sentry/utils/dates';
2022
import {useDebouncedValue} from 'sentry/utils/useDebouncedValue';
2123
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
2224
import type {ChartInfo} from 'sentry/views/explore/components/chart/types';
2325
import useAttributeBreakdowns from 'sentry/views/explore/hooks/useAttributeBreakdowns';
2426
import type {BoxSelectOptions} from 'sentry/views/explore/hooks/useChartBoxSelect';
27+
import {prettifyAggregation} from 'sentry/views/explore/utils';
2528

2629
import {Chart} from './chart';
2730
import {useChartSelection} from './chartSelectionContext';
2831
import {SortingToggle, type SortingMethod} from './sortingToggle';
2932

3033
const CHARTS_COLUMN_COUNT = 3;
3134
const CHARTS_PER_PAGE = CHARTS_COLUMN_COUNT * 4;
35+
const PERCENTILE_FUNCTION_PREFIXES = ['p50', 'p75', 'p90', 'p95', 'p99', 'avg'];
3236

3337
function FeedbackButton() {
3438
const openForm = useFeedbackForm();
@@ -133,6 +137,44 @@ function ContentImpl({
133137
setPage(0);
134138
}, [filteredRankedAttributes]);
135139

140+
const selectionHint = useMemo(() => {
141+
if (!boxSelectOptions.xRange) {
142+
return null;
143+
}
144+
145+
const [x1, x2] = boxSelectOptions.xRange;
146+
147+
let startTimestamp = Math.floor(x1 / 60_000) * 60_000;
148+
const endTimestamp = Math.ceil(x2 / 60_000) * 60_000;
149+
startTimestamp = Math.min(startTimestamp, endTimestamp - 60_000);
150+
151+
const userTimezone = getUserTimezone() || moment.tz.guess();
152+
const startDate = moment
153+
.tz(startTimestamp, userTimezone)
154+
.format('MMM D YYYY h:mm A z');
155+
const endDate = moment.tz(endTimestamp, userTimezone).format('MMM D YYYY h:mm A z');
156+
157+
// Check if yAxis is a percentile function (only these functions should include "and is greater than or equal to")
158+
const yAxisLower = chartInfo.yAxis.toLowerCase();
159+
const isPercentileFunction = PERCENTILE_FUNCTION_PREFIXES.some(prefix =>
160+
yAxisLower.startsWith(prefix)
161+
);
162+
163+
const formattedFunction = prettifyAggregation(chartInfo.yAxis) ?? chartInfo.yAxis;
164+
165+
return {
166+
selection: isPercentileFunction
167+
? t(
168+
`Selection is data between %s - %s and is greater than or equal to %s`,
169+
startDate,
170+
endDate,
171+
formattedFunction
172+
)
173+
: t(`Selection is data between %s - %s`, startDate, endDate),
174+
baseline: t('Baseline is all other spans from your query'),
175+
};
176+
}, [boxSelectOptions.xRange, chartInfo.yAxis]);
177+
136178
return (
137179
<Flex direction="column" gap="xl" padding="xl">
138180
{isLoading ? (
@@ -152,6 +194,14 @@ function ContentImpl({
152194
/>
153195
<SortingToggle value={sortingMethod} onChange={setSortingMethod} />
154196
</ControlsContainer>
197+
{selectionHint && (
198+
<SelectionHintContainer>
199+
<SelectionHint color={theme.chart.getColorPalette(0)?.[0]}>
200+
{selectionHint.selection}
201+
</SelectionHint>
202+
<SelectionHint color="#A29FAA">{selectionHint.baseline}</SelectionHint>
203+
</SelectionHintContainer>
204+
)}
155205
{filteredRankedAttributes.length > 0 ? (
156206
<Fragment>
157207
<ChartsGrid>
@@ -269,3 +319,27 @@ const PaginationContainer = styled('div')`
269319
justify-content: end;
270320
align-items: center;
271321
`;
322+
323+
const SelectionHintContainer = styled('div')`
324+
display: flex;
325+
flex-direction: column;
326+
gap: ${space(0.5)};
327+
margin-bottom: ${space(1)};
328+
`;
329+
330+
const SelectionHint = styled(Text)<{color?: string}>`
331+
display: flex;
332+
align-items: center;
333+
color: ${p => p.theme.subText};
334+
font-size: ${p => p.theme.fontSize.sm};
335+
336+
&::before {
337+
content: '';
338+
width: 8px;
339+
height: 8px;
340+
border-radius: 50%;
341+
background-color: ${p => p.color || p.theme.gray400};
342+
margin-right: ${space(0.5)};
343+
flex-shrink: 0;
344+
}
345+
`;

0 commit comments

Comments
 (0)