Skip to content

Commit a290948

Browse files
authored
feat(monitors): Add onboarding modal for the new alerts/monitors pages (#112694)
1 parent 9dbd2c0 commit a290948

File tree

10 files changed

+782
-7
lines changed

10 files changed

+782
-7
lines changed

knip.config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ const productionEntryPoints = [
2525
'static/app/components/pipeline/**/*.{js,ts,tsx}',
2626
// TODO: Remove when used
2727
'static/app/views/seerExplorer/contexts/**/*.{js,ts,tsx}',
28-
// TODO: Remove when used
29-
'static/app/components/featureShowcase.tsx',
3028
];
3129

3230
const testingEntryPoints = [

static/app/components/featureShowcase.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010

1111
import {Button} from '@sentry/scraps/button';
1212
import {Image, type ImageProps} from '@sentry/scraps/image';
13-
import {Container, Flex, Stack} from '@sentry/scraps/layout';
13+
import {Flex, Stack} from '@sentry/scraps/layout';
1414
import {Heading, Text} from '@sentry/scraps/text';
1515

1616
import type {ModalRenderProps} from 'sentry/actionCreators/modal';
@@ -62,7 +62,7 @@ function StepTitle({children}: {children: ReactNode}) {
6262
}
6363

6464
function StepContent({children}: {children: ReactNode}) {
65-
return <Text as="p">{children}</Text>;
65+
return <Stack gap="xl">{children}</Stack>;
6666
}
6767

6868
/**
@@ -162,16 +162,21 @@ function FeatureShowcase({closeModal, children, onStepChange}: FeatureShowcasePr
162162
};
163163

164164
return (
165-
<Container data-test-id="feature-showcase">
165+
<Stack data-test-id="feature-showcase" gap="md">
166166
<Flex justify="end">
167-
<Button priority="transparent" onClick={closeModal} aria-label={t('Close tour')}>
167+
<Button
168+
priority="transparent"
169+
size="sm"
170+
onClick={closeModal}
171+
aria-label={t('Close tour')}
172+
>
168173
<IconClose size="xs" />
169174
</Button>
170175
</Flex>
171176
<ShowcaseContext.Provider value={contextValue}>
172177
{activeStep}
173178
</ShowcaseContext.Provider>
174-
</Container>
179+
</Stack>
175180
);
176181
}
177182

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import {useCallback} from 'react';
2+
import {css, type Theme} from '@emotion/react';
3+
4+
import monitorsTourAlertsImage from 'sentry-images/spot/monitors-tour-alerts.svg';
5+
import monitorsTourConnectingImage from 'sentry-images/spot/monitors-tour-connecting.svg';
6+
import monitorsTourIntroImage from 'sentry-images/spot/monitors-tour-intro.svg';
7+
import monitorsTourMonitorsImage from 'sentry-images/spot/monitors-tour-monitors.svg';
8+
9+
import {Button} from '@sentry/scraps/button';
10+
import {Stack} from '@sentry/scraps/layout';
11+
import {ExternalLink} from '@sentry/scraps/link';
12+
import {Text} from '@sentry/scraps/text';
13+
14+
import {openModal} from 'sentry/actionCreators/modal';
15+
import {FeatureShowcase} from 'sentry/components/featureShowcase';
16+
import {IconInfo} from 'sentry/icons';
17+
import {t, tct} from 'sentry/locale';
18+
import {trackAnalytics} from 'sentry/utils/analytics';
19+
import {useOrganization} from 'sentry/utils/useOrganization';
20+
21+
const DOCS_URL = 'https://docs.sentry.io/product/new-monitors-and-alerts/';
22+
23+
export function AlertsMonitorsShowcaseButton() {
24+
const organization = useOrganization();
25+
26+
const handleClick = useCallback(() => {
27+
trackAnalytics('monitors.onboarding_modal_viewed', {organization, step: 0});
28+
openModal(
29+
deps => (
30+
<FeatureShowcase
31+
{...deps}
32+
onStepChange={step => {
33+
trackAnalytics('monitors.onboarding_modal_viewed', {
34+
organization,
35+
step,
36+
});
37+
}}
38+
>
39+
<FeatureShowcase.Step>
40+
<FeatureShowcase.Image
41+
src={monitorsTourIntroImage}
42+
alt={t('Introducing Monitors and Alerts')}
43+
/>
44+
<FeatureShowcase.StepTitle>
45+
{t('Introducing Monitors & Alerts')}
46+
</FeatureShowcase.StepTitle>
47+
<FeatureShowcase.StepContent>
48+
{t(
49+
'Monitors detect problems and create issues. These issues trigger Alerts to notify your team.'
50+
)}
51+
</FeatureShowcase.StepContent>
52+
<FeatureShowcase.StepActions />
53+
</FeatureShowcase.Step>
54+
<FeatureShowcase.Step>
55+
<FeatureShowcase.Image
56+
src={monitorsTourMonitorsImage}
57+
alt={t('Monitors detect problems and create issues')}
58+
/>
59+
<FeatureShowcase.StepTitle>
60+
{t('Monitors detect problems and create issues')}
61+
</FeatureShowcase.StepTitle>
62+
<FeatureShowcase.StepContent>
63+
<Text>
64+
{t(
65+
'Set conditions across your data and when a threshold is breached, Sentry creates an issue.'
66+
)}
67+
</Text>
68+
<Stack gap="sm">
69+
<Text bold>{t('Types of Monitors:')}</Text>
70+
<ul>
71+
<li>
72+
<Text>
73+
<Text bold as="span">
74+
{t('Metric')}
75+
</Text>
76+
{' — '}
77+
{t('span attributes, logs, custom metrics, and more')}
78+
</Text>
79+
</li>
80+
<li>
81+
<Text>
82+
<Text bold as="span">
83+
{t('Cron')}
84+
</Text>
85+
{' — '}
86+
{t('scheduled, recurring job health')}
87+
</Text>
88+
</li>
89+
<li>
90+
<Text>
91+
<Text bold as="span">
92+
{t('Uptime')}
93+
</Text>
94+
{' — '}
95+
{t('service availability and reliability')}
96+
</Text>
97+
</li>
98+
<li>
99+
<Text>
100+
<Text bold as="span">
101+
{t('Mobile Builds')}
102+
</Text>
103+
{' — '}
104+
{t('build size and regressions')}
105+
</Text>
106+
</li>
107+
<li>
108+
<Text>
109+
<Text bold as="span">
110+
{t('Error')}
111+
</Text>{' '}
112+
{t('(managed by Sentry)')}
113+
{' — '}
114+
{t(
115+
'groups incoming errors into issues based on your project settings'
116+
)}
117+
</Text>
118+
</li>
119+
</ul>
120+
</Stack>
121+
</FeatureShowcase.StepContent>
122+
<FeatureShowcase.StepActions />
123+
</FeatureShowcase.Step>
124+
<FeatureShowcase.Step>
125+
<FeatureShowcase.Image
126+
src={monitorsTourAlertsImage}
127+
alt={t('Alerts notify your team')}
128+
/>
129+
<FeatureShowcase.StepTitle>
130+
{t('Alerts notify your team')}
131+
</FeatureShowcase.StepTitle>
132+
<FeatureShowcase.StepContent>
133+
<Text>
134+
{t(
135+
'Alerts notify your team. Define who gets paged, when, and how — via Slack, email, PagerDuty, and more.'
136+
)}
137+
</Text>
138+
<Text>
139+
{t(
140+
'Scale and connect to many monitors, projects, and issue types. Configure your routing so the right people get notified when it matters.'
141+
)}
142+
</Text>
143+
</FeatureShowcase.StepContent>
144+
<FeatureShowcase.StepActions />
145+
</FeatureShowcase.Step>
146+
<FeatureShowcase.Step>
147+
<FeatureShowcase.Image
148+
src={monitorsTourConnectingImage}
149+
alt={t('Connecting Alerts and Monitors')}
150+
/>
151+
<FeatureShowcase.StepTitle>
152+
{t('Connecting Alerts & Monitors')}
153+
</FeatureShowcase.StepTitle>
154+
<FeatureShowcase.StepContent>
155+
<Text>
156+
{t(
157+
'When creating a Monitor you have the option of setting up a new Alert or connecting to an existing Alert at the same time.'
158+
)}
159+
</Text>
160+
<Text>
161+
{t(
162+
'When creating or editing Alerts you can connect to existing routing without ever touching your Monitor logic.'
163+
)}
164+
</Text>
165+
<Text>
166+
{tct('For more information, [link:read the docs].', {
167+
link: <ExternalLink href={DOCS_URL} />,
168+
})}
169+
</Text>
170+
</FeatureShowcase.StepContent>
171+
<FeatureShowcase.StepActions />
172+
</FeatureShowcase.Step>
173+
</FeatureShowcase>
174+
),
175+
{
176+
modalCss: (theme: Theme) => css`
177+
width: 490px;
178+
179+
[role='document'] {
180+
padding: ${theme.space['2xl']};
181+
padding-top: ${theme.space.lg};
182+
}
183+
`,
184+
}
185+
);
186+
}, [organization]);
187+
188+
return (
189+
<Button
190+
size="sm"
191+
icon={<IconInfo />}
192+
onClick={handleClick}
193+
aria-label={t('Feature tour')}
194+
/>
195+
);
196+
}

static/app/utils/analytics/monitorsAnalyticsEvents.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type MonitorsEventParameters = {
2828
};
2929
'monitor.created': DetectorCreateAnalyticsEventPayload;
3030
'monitor.updated': DetectorAnalyticsEventPayload;
31+
'monitors.onboarding_modal_viewed': {step: number};
3132
};
3233

3334
type MonitorsAnalyticsKey = keyof MonitorsEventParameters;
@@ -38,4 +39,5 @@ export const monitorsEventMap: Record<MonitorsAnalyticsKey, string> = {
3839
'monitor.updated': 'Detectors: Updated',
3940
'automation.created': 'Automations: Created',
4041
'automation.updated': 'Automations: Updated',
42+
'monitors.onboarding_modal_viewed': 'Monitors: Onboarding Modal Viewed',
4143
};

static/app/views/automations/list.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {ProjectPageFilter} from 'sentry/components/pageFilters/project/projectPa
88
import {usePageFilters} from 'sentry/components/pageFilters/usePageFilters';
99
import {Pagination} from 'sentry/components/pagination';
1010
import {SentryDocumentTitle} from 'sentry/components/sentryDocumentTitle';
11+
import {AlertsMonitorsShowcaseButton} from 'sentry/components/workflowEngine/alertsMonitorsShowcaseButton';
1112
import {WorkflowEngineListLayout as ListLayout} from 'sentry/components/workflowEngine/layout/list';
1213
import {IconAdd} from 'sentry/icons';
1314
import {t} from 'sentry/locale';
@@ -147,6 +148,7 @@ function Actions() {
147148
const organization = useOrganization();
148149
return (
149150
<Flex gap="sm">
151+
<AlertsMonitorsShowcaseButton />
150152
<AutomationFeedbackButton />
151153
<LinkButton
152154
to={makeAutomationCreatePathname(organization.slug)}

static/app/views/detectors/list/common/detectorListActions.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Flex} from '@sentry/scraps/layout';
33

44
import {ALL_ACCESS_PROJECTS} from 'sentry/components/pageFilters/constants';
55
import {usePageFilters} from 'sentry/components/pageFilters/usePageFilters';
6+
import {AlertsMonitorsShowcaseButton} from 'sentry/components/workflowEngine/alertsMonitorsShowcaseButton';
67
import {IconAdd} from 'sentry/icons';
78
import {t} from 'sentry/locale';
89
import type {DetectorType} from 'sentry/types/workflowEngine/detectors';
@@ -26,6 +27,7 @@ export function DetectorListActions({children, detectorType}: DetectorListAction
2627

2728
return (
2829
<Flex gap="sm">
30+
<AlertsMonitorsShowcaseButton />
2931
{children}
3032
<MonitorFeedbackButton />
3133
<LinkButton

0 commit comments

Comments
 (0)