Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions static/app/views/detectors/list/cron.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ describe('CronDetectorsList', () => {
body: UserFixture(),
});

// Mock processing errors endpoint (no errors by default)
MockApiClient.addMockResponse({
url: '/organizations/org-slug/processing-errors/',
body: [],
});

// Ensure a project is selected for queries
PageFiltersStore.onInitializeUrlState(PageFiltersFixture({projects: [1]}));

Expand Down
6 changes: 6 additions & 0 deletions static/app/views/detectors/list/cron.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {fadeIn} from 'sentry/styles/animations';
import type {CronDetector, Detector} from 'sentry/types/workflowEngine/detectors';
import {useDebouncedValue} from 'sentry/utils/useDebouncedValue';
import {useDimensions} from 'sentry/utils/useDimensions';
import usePageFilters from 'sentry/utils/usePageFilters';
import {HeaderCell} from 'sentry/views/detectors/components/detectorListTable';
import {DetectorListActions} from 'sentry/views/detectors/list/common/detectorListActions';
import {DetectorListContent} from 'sentry/views/detectors/list/common/detectorListContent';
Expand All @@ -27,6 +28,7 @@ import {
} from 'sentry/views/detectors/monitorViewContext';
import {CronsLandingPanel} from 'sentry/views/insights/crons/components/cronsLandingPanel';
import MonitorEnvironmentLabel from 'sentry/views/insights/crons/components/overviewTimeline/monitorEnvironmentLabel';
import {GlobalMonitorProcessingErrors} from 'sentry/views/insights/crons/components/processingErrors/globalMonitorProcessingErrors';
import {
checkInStatusPrecedent,
statusToText,
Expand Down Expand Up @@ -118,10 +120,13 @@ const DESCRIPTION = t(
const DOCS_URL = 'https://docs.sentry.io/product/crons/';

export default function CronDetectorsList() {
const {selection} = usePageFilters();
const detectorListQuery = useDetectorListQuery({
detectorFilter: 'monitor_check_in_failure',
});

const selectedProjects = selection.projects.map(String);

const contextValue = useMemo<MonitorViewContextValue>(() => {
return {
additionalColumns: ADDITIONAL_COLUMNS,
Expand Down Expand Up @@ -156,6 +161,7 @@ export default function CronDetectorsList() {
docsUrl={DOCS_URL}
>
<DetectorListHeader showTimeRangeSelector showTypeFilter={false} />
<GlobalMonitorProcessingErrors project={selectedProjects} />
<DetectorListContent
{...detectorListQuery}
emptyState={<CronsLandingPanel />}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {deleteProjectProcessingErrorByType} from 'sentry/actionCreators/monitors';
import {t} from 'sentry/locale';
import {useApiQuery} from 'sentry/utils/queryClient';
import useApi from 'sentry/utils/useApi';
import useOrganization from 'sentry/utils/useOrganization';
import {MonitorProcessingErrors} from 'sentry/views/insights/crons/components/processingErrors/monitorProcessingErrors';
import {makeMonitorListErrorsQueryKey} from 'sentry/views/insights/crons/components/processingErrors/utils';
import type {
CheckinProcessingError,
ProcessingErrorType,
} from 'sentry/views/insights/crons/types';

interface GlobalMonitorProcessingErrorsProps {
project?: string[];
}

export function GlobalMonitorProcessingErrors({
project,
}: GlobalMonitorProcessingErrorsProps) {
const api = useApi();
const organization = useOrganization();

const processingErrorQueryKey = makeMonitorListErrorsQueryKey(organization, project);
const {data: processingErrors, refetch: refetchErrors} = useApiQuery<
CheckinProcessingError[]
>(processingErrorQueryKey, {
staleTime: 0,
});

async function handleDismissError(errorType: ProcessingErrorType, projectId: string) {
await deleteProjectProcessingErrorByType(
api,
organization.slug,
projectId,
errorType
);
await refetchErrors();
}

if (!processingErrors?.length) {
return null;
}

return (
<MonitorProcessingErrors
checkinErrors={processingErrors}
onDismiss={handleDismissError}
>
{t('Errors were encountered while ingesting check-ins for the selected projects')}
</MonitorProcessingErrors>
);
}
44 changes: 5 additions & 39 deletions static/app/views/insights/crons/views/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import * as qs from 'query-string';
import {Alert} from '@sentry/scraps/alert';

import {openBulkEditMonitorsModal} from 'sentry/actionCreators/modal';
import {deleteProjectProcessingErrorByType} from 'sentry/actionCreators/monitors';
import {Button} from 'sentry/components/core/button';
import {ButtonBar} from 'sentry/components/core/button/buttonBar';
import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidgetButton';
Expand All @@ -30,7 +29,6 @@ import {useApiQuery} from 'sentry/utils/queryClient';
import {decodeList, decodeScalar} from 'sentry/utils/queryString';
import useRouteAnalyticsEventNames from 'sentry/utils/routeAnalytics/useRouteAnalyticsEventNames';
import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
import useApi from 'sentry/utils/useApi';
import {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
import useOrganization from 'sentry/utils/useOrganization';
Expand All @@ -42,22 +40,16 @@ import {
import {NewMonitorButton} from 'sentry/views/insights/crons/components/newMonitorButton';
import {OverviewTimeline} from 'sentry/views/insights/crons/components/overviewTimeline';
import {OwnerFilter} from 'sentry/views/insights/crons/components/ownerFilter';
import {MonitorProcessingErrors} from 'sentry/views/insights/crons/components/processingErrors/monitorProcessingErrors';
import {makeMonitorListErrorsQueryKey} from 'sentry/views/insights/crons/components/processingErrors/utils';
import {GlobalMonitorProcessingErrors} from 'sentry/views/insights/crons/components/processingErrors/globalMonitorProcessingErrors';
import {MODULE_DESCRIPTION, MODULE_DOC_LINK} from 'sentry/views/insights/crons/settings';
import type {
CheckinProcessingError,
Monitor,
ProcessingErrorType,
} from 'sentry/views/insights/crons/types';
import type {Monitor} from 'sentry/views/insights/crons/types';
import {makeMonitorListQueryKey} from 'sentry/views/insights/crons/utils';

const CronsListPageHeader = HookOrDefault({
hookName: 'component:crons-list-page-header',
});

function CronsOverview() {
const api = useApi();
const organization = useOrganization();
const navigate = useNavigate();
const location = useLocation();
Expand All @@ -76,13 +68,6 @@ function CronsOverview() {
staleTime: 0,
});

const processingErrorQueryKey = makeMonitorListErrorsQueryKey(organization, project);
const {data: processingErrors, refetch: refetchErrors} = useApiQuery<
CheckinProcessingError[]
>(processingErrorQueryKey, {
staleTime: 0,
});

useRouteAnalyticsEventNames('monitors.page_viewed', 'Monitors: Page Viewed');
useRouteAnalyticsParams({empty_state: !monitorList || monitorList.length === 0});

Expand All @@ -96,16 +81,6 @@ function CronsOverview() {
});
};

async function handleDismissError(errorType: ProcessingErrorType, projectId: string) {
await deleteProjectProcessingErrorByType(
api,
organization.slug,
projectId,
errorType
);
await refetchErrors();
}

const showAddMonitor = !isValidPlatform(platform) || !isValidGuide(guide);

const page = (
Expand Down Expand Up @@ -171,18 +146,9 @@ function CronsOverview() {
onSearch={handleSearch}
/>
</Filters>
{!!processingErrors?.length && (
<Alert.Container>
<MonitorProcessingErrors
checkinErrors={processingErrors}
onDismiss={handleDismissError}
>
{t(
'Errors were encountered while ingesting check-ins for the selected projects'
)}
</MonitorProcessingErrors>
</Alert.Container>
)}
<Alert.Container>
<GlobalMonitorProcessingErrors project={project} />
</Alert.Container>
{isPending ? (
<LoadingIndicator />
) : monitorList?.length ? (
Expand Down
Loading