Skip to content

Commit 8e1a0d3

Browse files
authored
feat(aci): Hide issue stream detectors from the UI (#102806)
Automatically applies `!type:issue_stream` when using `useDetetectorsQuery()` so that users won't see this detector type in the list views or when connecting monitors.
1 parent 4cb7c09 commit 8e1a0d3

File tree

8 files changed

+65
-10
lines changed

8 files changed

+65
-10
lines changed

static/app/types/workflowEngine/detectors.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ export type DetectorType =
7777
| 'error'
7878
| 'metric_issue'
7979
| 'monitor_check_in_failure'
80-
| 'uptime_domain_failure';
80+
| 'uptime_domain_failure'
81+
| 'issue_stream';
8182

8283
interface BaseMetricDetectorConfig {
8384
thresholdPeriod: number;

static/app/views/detectors/components/forms/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function PlaceholderForm() {
2525
<Layout.Page>
2626
<Layout.Body>
2727
<Layout.Main width="full">
28-
<LoadingError message={t('This monitor type is not yet implemented')} />
28+
<LoadingError message={t('This monitor type can not be created')} />
2929
</Layout.Main>
3030
</Layout.Body>
3131
</Layout.Page>
@@ -42,6 +42,8 @@ export function NewDetectorForm({detectorType}: {detectorType: DetectorType}) {
4242
return <NewErrorDetectorForm />;
4343
case 'monitor_check_in_failure':
4444
return <NewCronDetectorForm />;
45+
case 'issue_stream':
46+
return <PlaceholderForm />;
4547
default:
4648
unreachable(detectorType);
4749
return <PlaceholderForm />;

static/app/views/detectors/hooks/index.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,29 @@ import useOrganization from 'sentry/utils/useOrganization';
1212
interface UseDetectorsQueryKeyOptions {
1313
cursor?: string;
1414
ids?: string[];
15+
/**
16+
* By default, issue stream detectors are excluded from the query,
17+
* because they are opaque to the user in the UI and only used to
18+
* make connections to alerts.
19+
*/
20+
includeIssueStreamDetectors?: boolean;
1521
limit?: number;
1622
projects?: number[];
1723
query?: string;
1824
sortBy?: string;
1925
}
2026

27+
const createDetectorQuery = (
28+
query: string | undefined,
29+
options: {includeIssueStreamDetectors: boolean}
30+
) => {
31+
if (options.includeIssueStreamDetectors) {
32+
return query;
33+
}
34+
35+
return `!type:issue_stream ${query ?? ''}`.trim();
36+
};
37+
2138
export const makeDetectorListQueryKey = ({
2239
orgSlug,
2340
query,
@@ -26,21 +43,40 @@ export const makeDetectorListQueryKey = ({
2643
limit,
2744
cursor,
2845
ids,
46+
includeIssueStreamDetectors = false,
2947
}: {
3048
orgSlug: string;
3149
cursor?: string;
3250
ids?: string[];
51+
includeIssueStreamDetectors?: boolean;
3352
limit?: number;
3453
projects?: number[];
3554
query?: string;
3655
sortBy?: string;
3756
}): ApiQueryKey => [
3857
`/organizations/${orgSlug}/detectors/`,
39-
{query: {query, sortBy, project: projects, per_page: limit, cursor, id: ids}},
58+
{
59+
query: {
60+
query: createDetectorQuery(query, {includeIssueStreamDetectors}),
61+
sortBy,
62+
project: projects,
63+
per_page: limit,
64+
cursor,
65+
id: ids,
66+
},
67+
},
4068
];
4169

4270
export function useDetectorsQuery<T extends Detector = Detector>(
43-
{ids, query, sortBy, projects, limit, cursor}: UseDetectorsQueryKeyOptions = {},
71+
{
72+
ids,
73+
query,
74+
sortBy,
75+
projects,
76+
limit,
77+
cursor,
78+
includeIssueStreamDetectors,
79+
}: UseDetectorsQueryKeyOptions = {},
4480
queryOptions: Partial<UseApiQueryOptions<T[]>> = {}
4581
) {
4682
const org = useOrganization();
@@ -54,6 +90,7 @@ export function useDetectorsQuery<T extends Detector = Detector>(
5490
limit,
5591
cursor,
5692
ids,
93+
includeIssueStreamDetectors,
5794
}),
5895
{
5996
staleTime: 0,

static/app/views/detectors/list.spec.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ describe('DetectorsList', () => {
159159
const mockDetectorsRequestErrorType = MockApiClient.addMockResponse({
160160
url: '/organizations/org-slug/detectors/',
161161
body: [ErrorDetectorFixture({name: 'Error Detector'})],
162-
match: [MockApiClient.matchQuery({query: 'type:error'})],
162+
match: [MockApiClient.matchQuery({query: '!type:issue_stream type:error'})],
163163
});
164164

165165
render(<DetectorsList />, {organization});
@@ -191,7 +191,11 @@ describe('DetectorsList', () => {
191191
owner: ActorFixture({id: testUser.id, name: testUser.email, type: 'user'}),
192192
}),
193193
],
194-
match: [MockApiClient.matchQuery({query: 'assignee:test@example.com'})],
194+
match: [
195+
MockApiClient.matchQuery({
196+
query: '!type:issue_stream assignee:test@example.com',
197+
}),
198+
],
195199
});
196200

197201
render(<DetectorsList />, {organization});
@@ -484,7 +488,11 @@ describe('DetectorsList', () => {
484488
headers: {
485489
'X-Hits': '50',
486490
},
487-
match: [MockApiClient.matchQuery({query: 'assignee:test@example.com'})],
491+
match: [
492+
MockApiClient.matchQuery({
493+
query: '!type:issue_stream assignee:test@example.com',
494+
}),
495+
],
488496
});
489497

490498
// Click through menus to select assignee

static/app/views/detectors/list.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ interface DetectorHeadingInfo {
3636
title: string;
3737
}
3838

39-
const DETECTOR_TYPE_HEADING_MAPPING: Record<DetectorType, DetectorHeadingInfo> = {
39+
const DETECTOR_TYPE_HEADING_MAPPING: Record<
40+
Exclude<DetectorType, 'issue_stream'>,
41+
DetectorHeadingInfo
42+
> = {
4043
error: {
4144
title: t('Error Monitors'),
4245
description: t(

static/app/views/detectors/monitorViewContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface MonitorViewContextValue {
2222
*/
2323
additionalColumns?: MonitorListAdditionalColumn[];
2424
assigneeFilter?: string;
25-
detectorFilter?: DetectorType;
25+
detectorFilter?: Exclude<DetectorType, 'issue_stream'>;
2626
emptyState?: React.ReactNode;
2727
renderVisualization?: (params: RenderVisualizationParams) => React.ReactNode;
2828
showTimeRangeSelector?: boolean;

static/app/views/detectors/utils/detectorTypeConfig.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const DETECTOR_TYPE_CONFIG: Record<DetectorType, DetectorTypeConfig> = {
2323
userCreateable: true,
2424
label: t('Uptime'),
2525
},
26+
issue_stream: {
27+
userCreateable: false,
28+
label: t('Issue Stream'),
29+
},
2630
};
2731

2832
export function isValidDetectorType(detectorType: DetectorType) {

static/gsApp/hooks/useMetricDetectorLimit.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe('useMetricDetectorLimit', () => {
115115
'/organizations/org-slug/detectors/',
116116
expect.objectContaining({
117117
query: expect.objectContaining({
118-
query: 'type:metric',
118+
query: '!type:issue_stream type:metric',
119119
per_page: 1,
120120
}),
121121
})

0 commit comments

Comments
 (0)