Skip to content

Commit 6f2f1c9

Browse files
authored
feat(alerts): Add migration warnings on list view (#58426)
- relates to #58139
1 parent aa36338 commit 6f2f1c9

File tree

5 files changed

+87
-4
lines changed

5 files changed

+87
-4
lines changed

static/app/views/alerts/filterBar.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {CompactSelect} from 'sentry/components/compactSelect';
66
import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
77
import SearchBar from 'sentry/components/searchBar';
88
import {SegmentedControl} from 'sentry/components/segmentedControl';
9+
import {IconWarning} from 'sentry/icons';
910
import {t} from 'sentry/locale';
1011
import {space} from 'sentry/styles/space';
1112

@@ -19,6 +20,7 @@ interface Props {
1920
hasStatusFilters?: boolean;
2021
onChangeDataset?: (dataset: DatasetOption) => void;
2122
onChangeStatus?: (status: string) => void;
23+
showMigrationWarning?: boolean;
2224
}
2325

2426
function FilterBar({
@@ -28,6 +30,7 @@ function FilterBar({
2830
onChangeStatus,
2931
onChangeDataset,
3032
hasStatusFilters,
33+
showMigrationWarning,
3134
}: Props) {
3235
const selectedTeams = getTeamParams(location.query.team);
3336
const selectedStatus = getQueryStatus(location.query.status);
@@ -77,8 +80,12 @@ function FilterBar({
7780
<SegmentedControl.Item key={DatasetOption.SESSIONS}>
7881
{t('Sessions')}
7982
</SegmentedControl.Item>
80-
<SegmentedControl.Item key={DatasetOption.PERFORMANCE}>
83+
<SegmentedControl.Item
84+
textValue={t('Performance')}
85+
key={DatasetOption.PERFORMANCE}
86+
>
8187
{t('Performance')}
88+
{showMigrationWarning ? <StyledIconWarning /> : null}
8289
</SegmentedControl.Item>
8390
</SegmentedControl>
8491
</SegmentedControlWrapper>
@@ -121,3 +128,10 @@ const FilterButtons = styled(ButtonBar)`
121128
const SegmentedControlWrapper = styled('div')`
122129
width: max-content;
123130
`;
131+
132+
const StyledIconWarning = styled(IconWarning)`
133+
vertical-align: middle;
134+
margin-top: -${space(0.5)};
135+
margin-left: ${space(0.5)};
136+
color: ${p => p.theme.yellow400};
137+
`;

static/app/views/alerts/list/rules/alertRulesList.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ describe('AlertRulesList', () => {
254254
'ascending'
255255
);
256256

257-
expect(rulesMock).toHaveBeenCalledTimes(1);
257+
expect(rulesMock).toHaveBeenCalledTimes(2);
258258
expect(rulesMock).toHaveBeenCalledWith(
259259
'/organizations/org-slug/combined-rules/',
260260
expect.objectContaining({

static/app/views/alerts/list/rules/alertRulesList.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ import {
99
addMessage,
1010
addSuccessMessage,
1111
} from 'sentry/actionCreators/indicator';
12+
import Alert from 'sentry/components/alert';
1213
import * as Layout from 'sentry/components/layouts/thirds';
1314
import Link from 'sentry/components/links/link';
1415
import LoadingError from 'sentry/components/loadingError';
1516
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
1617
import Pagination from 'sentry/components/pagination';
1718
import PanelTable from 'sentry/components/panels/panelTable';
1819
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
19-
import {IconArrow} from 'sentry/icons';
20-
import {t} from 'sentry/locale';
20+
import {IconArrow, IconWarning} from 'sentry/icons';
21+
import {t, tct} from 'sentry/locale';
2122
import {space} from 'sentry/styles/space';
2223
import {Project} from 'sentry/types';
2324
import {defined} from 'sentry/utils';
@@ -35,6 +36,11 @@ import useApi from 'sentry/utils/useApi';
3536
import {useLocation} from 'sentry/utils/useLocation';
3637
import useOrganization from 'sentry/utils/useOrganization';
3738
import useRouter from 'sentry/utils/useRouter';
39+
import {
40+
hasMigrationFeatureFlag,
41+
ruleNeedsMigration,
42+
useOrgNeedsMigration,
43+
} from 'sentry/views/alerts/utils/migrationUi';
3844

3945
import FilterBar from '../../filterBar';
4046
import {AlertRuleType, CombinedMetricIssueAlerts} from '../../types';
@@ -91,6 +97,8 @@ function AlertRulesList() {
9197
staleTime: 0,
9298
}
9399
);
100+
const hasMigrationUIFeatureFlag = hasMigrationFeatureFlag(organization);
101+
const showMigrationUI = useOrgNeedsMigration();
94102

95103
const handleChangeFilter = (activeFilters: string[]) => {
96104
const {cursor: _cursor, page: _page, ...currentQuery} = location.query;
@@ -195,8 +203,17 @@ function AlertRulesList() {
195203
<AlertHeader router={router} activeTab="rules" />
196204
<Layout.Body>
197205
<Layout.Main fullWidth>
206+
{showMigrationUI ? (
207+
<Alert showIcon type="warning">
208+
{tct(
209+
'Our performance alerts just got a lot more accurate, which is why we recommend you review the thresholds of all rules marked with a “[warningIcon]“',
210+
{warningIcon: <StyledIconWarning />}
211+
)}
212+
</Alert>
213+
) : null}
198214
<FilterBar
199215
location={location}
216+
showMigrationWarning={showMigrationUI}
200217
onChangeDataset={handleChangeDataset}
201218
onChangeFilter={handleChangeFilter}
202219
onChangeSearch={handleChangeSearch}
@@ -261,6 +278,9 @@ function AlertRulesList() {
261278
key={`${
262279
isIssueAlert(rule) ? AlertRuleType.METRIC : AlertRuleType.ISSUE
263280
}-${rule.id}`}
281+
showMigrationWarning={
282+
hasMigrationUIFeatureFlag && ruleNeedsMigration(rule)
283+
}
264284
projectsLoaded={initiallyLoaded}
265285
projects={projects as Project[]}
266286
rule={rule}
@@ -325,3 +345,8 @@ const StyledPanelTable = styled(PanelTable)`
325345
white-space: nowrap;
326346
font-size: ${p => p.theme.fontSizeMedium};
327347
`;
348+
349+
const StyledIconWarning = styled(IconWarning)`
350+
vertical-align: middle;
351+
color: ${p => p.theme.yellow400};
352+
`;

static/app/views/alerts/list/rules/row.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
IconMute,
2525
IconNot,
2626
IconUser,
27+
IconWarning,
2728
} from 'sentry/icons';
2829
import {t, tct} from 'sentry/locale';
2930
import {space} from 'sentry/styles/space';
@@ -52,6 +53,7 @@ type Props = {
5253
projects: Project[];
5354
projectsLoaded: boolean;
5455
rule: CombinedMetricIssueAlerts;
56+
showMigrationWarning: boolean;
5557
};
5658

5759
function RuleListRow({
@@ -62,6 +64,7 @@ function RuleListRow({
6264
onDelete,
6365
onOwnerChange,
6466
hasEditAccess,
67+
showMigrationWarning,
6568
}: Props) {
6669
const {teams: userTeams} = useUserTeams();
6770
const [assignee, setAssignee] = useState<string>('');
@@ -316,6 +319,13 @@ function RuleListRow({
316319
<ErrorBoundary>
317320
<AlertNameWrapper isIssueAlert={isIssueAlert(rule)}>
318321
<FlexCenter>
322+
{showMigrationWarning && (
323+
<Tooltip
324+
title={t('The current thresholds for this alert could use some review')}
325+
>
326+
<StyledIconWarning />
327+
</Tooltip>
328+
)}
319329
<Tooltip
320330
title={
321331
isIssueAlert(rule)
@@ -519,4 +529,9 @@ const Label = styled(TextOverflow)`
519529
margin-left: 6px;
520530
`;
521531

532+
const StyledIconWarning = styled(IconWarning)`
533+
margin-right: ${space(1)};
534+
color: ${p => p.theme.yellow400};
535+
`;
536+
522537
export default RuleListRow;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {Organization} from 'sentry/types';
2+
import {useApiQuery} from 'sentry/utils/queryClient';
3+
import useOrganization from 'sentry/utils/useOrganization';
4+
import {Dataset} from 'sentry/views/alerts/rules/metric/types';
5+
import {CombinedMetricIssueAlerts} from 'sentry/views/alerts/types';
6+
7+
// TODO(telemetry-experience): remove when the migration is complete
8+
export const hasMigrationFeatureFlag = (organization: Organization): boolean =>
9+
organization.features.includes('alert-migration-ui');
10+
11+
// TODO(telemetry-experience): remove when the migration is complete
12+
export const ruleNeedsMigration = (rule: CombinedMetricIssueAlerts): boolean => {
13+
return 'dataset' in rule && rule.dataset === Dataset.TRANSACTIONS;
14+
};
15+
// TODO(telemetry-experience): remove when the migration is complete
16+
export function useOrgNeedsMigration(): boolean {
17+
const organization = useOrganization();
18+
const {data = []} = useApiQuery<CombinedMetricIssueAlerts[]>(
19+
[
20+
`/organizations/${organization.slug}/combined-rules/`,
21+
{query: {dataset: Dataset.TRANSACTIONS}},
22+
],
23+
{staleTime: 0}
24+
);
25+
26+
const hasTransactionAlerts = data.length > 0;
27+
const hasFeatureFlag = hasMigrationFeatureFlag(organization);
28+
return hasTransactionAlerts && hasFeatureFlag;
29+
}

0 commit comments

Comments
 (0)