diff --git a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx index 31a22e608e..35300e07c1 100644 --- a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx @@ -43,7 +43,7 @@ export function LogbookPriorNotificationForm() { } customSentry.endMeasurement( - CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, + CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_LOADING, openedPriorNotificationDetail.reportId, 2000 ) diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx index 9c7868cd01..49cc01fd35 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx @@ -28,6 +28,7 @@ export function ManualPriorNotificationForm() { const editedManualPriorNotificationFormValues = useMainAppSelector( state => state.priorNotification.editedManualPriorNotificationFormValues ) + const editedPriorNotificationId = useMainAppSelector(state => state.priorNotification.editedPriorNotificationId) const openedPriorNotificationDetail = useMainAppSelector( state => state.priorNotification.openedPriorNotificationDetail ) @@ -80,16 +81,24 @@ export function ManualPriorNotificationForm() { } if (!editedManualPriorNotificationFormValues || isLoading) { + const customSentryProps = editedPriorNotificationId + ? { + id: editedPriorNotificationId, + maxExpectedDurationInMs: 2000, + name: CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER + } + : undefined + return ( - + ) } if (openedPriorNotificationDetail?.reportId) { customSentry.endMeasurement( - CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, + CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_LOADING, openedPriorNotificationDetail.reportId, 2000 ) diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx index 2ecbc6a09e..7447d6cb41 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx @@ -9,6 +9,7 @@ import { } from '@features/PriorNotification/utils' import { useMainAppDispatch } from '@hooks/useMainAppDispatch' import { useMainAppSelector } from '@hooks/useMainAppSelector' +import { CustomSentryMeasurementName } from '@libs/customSentry' import { DisplayedErrorKey } from '@libs/DisplayedError/constants' import { Accent, Button, Level } from '@mtes-mct/monitor-ui' import { useIsSuperUser } from 'auth/hooks/useIsSuperUser' @@ -40,6 +41,7 @@ export function PriorNotificationCard({ const displayedError = useMainAppSelector( state => state.displayedError[DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_CARD_ERROR] ) + const editedPriorNotificationId = useMainAppSelector(state => state.priorNotification.editedPriorNotificationId) const isSuperUser = useIsSuperUser() const controlledDisplayedErrorKey = displayedError @@ -62,9 +64,17 @@ export function PriorNotificationCard({ } if (!detail || isLoading) { + const customSentryProps = editedPriorNotificationId + ? { + id: editedPriorNotificationId, + maxExpectedDurationInMs: 2000, + name: CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER + } + : undefined + return ( - + ) } diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/TableBodyLoader.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/TableBodyLoader.tsx index 0156b7dc5a..89c198b7ca 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/TableBodyLoader.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/TableBodyLoader.tsx @@ -1,4 +1,6 @@ +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { TableWithSelectableRows } from '@mtes-mct/monitor-ui' +import { useEffect } from 'react' import styled from 'styled-components' import { getTableColumns } from './columns' @@ -11,6 +13,10 @@ export function TableBodyLoader({ isFromUrl }: TableBodyLoaderProps) { const emptyRows = new Array(DEFAULT_PAGE_SIZE).fill(undefined) const tableColumns = getTableColumns(isFromUrl) + useEffect(() => () => { + customSentry.endMeasurement(CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, '0', 2000) + }) + return ( {emptyRows.map((_, index) => ( diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx index 3fd47b75de..bc68a1bd1b 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx @@ -146,6 +146,7 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps) }, [previousListFilter, listFilter, table]) if (isBodyLoaderVisible) { + customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_LOADING, '0') customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0') } else { customSentry.endMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0', 2000) diff --git a/frontend/src/features/PriorNotification/slice.ts b/frontend/src/features/PriorNotification/slice.ts index 2268b1d280..0a23ddf362 100644 --- a/frontend/src/features/PriorNotification/slice.ts +++ b/frontend/src/features/PriorNotification/slice.ts @@ -12,6 +12,8 @@ export interface PriorNotificationState { editedLogbookPriorNotificationFormValues: PriorNotification.LogbookForm | undefined editedManualPriorNotificationComputedValues: Undefine | undefined editedManualPriorNotificationFormValues: ManualPriorNotificationFormValues | undefined + // TODO Remove this prop once loading / spinner perfs tests are removed. + editedPriorNotificationId: string | undefined isPriorNotificationFormDirty: boolean listFilterValues: ListFilter openedPriorNotificationComponentType: OpenedPriorNotificationType | undefined @@ -22,6 +24,8 @@ const INITIAL_STATE: PriorNotificationState = { editedLogbookPriorNotificationFormValues: undefined, editedManualPriorNotificationComputedValues: undefined, editedManualPriorNotificationFormValues: undefined, + // TODO Remove this prop once loading / spinner perfs tests are removed. + editedPriorNotificationId: undefined, isPriorNotificationFormDirty: false, listFilterValues: DEFAULT_LIST_FILTER_VALUES, openedPriorNotificationComponentType: undefined, @@ -34,6 +38,7 @@ const priorNotificationSlice = createSlice({ reducers: { closePriorNotificationCardAndForm(state) { state.editedLogbookPriorNotificationFormValues = undefined + state.editedPriorNotificationId = undefined state.editedManualPriorNotificationComputedValues = undefined state.editedManualPriorNotificationFormValues = undefined state.isPriorNotificationFormDirty = false @@ -60,6 +65,11 @@ const priorNotificationSlice = createSlice({ state.editedManualPriorNotificationFormValues = action.payload }, + // TODO Remove this function once loading / spinner perfs tests are removed. + setEditedPriorNotificationId(state, action: PayloadAction) { + state.editedPriorNotificationId = action.payload + }, + setIsPriorNotificationFormDirty(state, action: PayloadAction) { state.isPriorNotificationFormDirty = action.payload }, diff --git a/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts b/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts index 8e36de8eef..556f78cae8 100644 --- a/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts +++ b/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts @@ -20,6 +20,10 @@ export const openLogbookPriorNotificationForm = (identifier: PriorNotification.Identifier, fingerprint?: string): MainAppThunk> => async dispatch => { try { + customSentry.startMeasurement( + CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_LOADING, + identifier.reportId + ) customSentry.startMeasurement( CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, identifier.reportId @@ -27,6 +31,8 @@ export const openLogbookPriorNotificationForm = dispatch(displayedErrorActions.unset(DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_FORM_ERROR)) dispatch(priorNotificationActions.closePriorNotificationCardAndForm()) + // TODO Remove this function once loading / spinner perfs tests are removed. + dispatch(priorNotificationActions.setEditedPriorNotificationId(identifier.reportId)) dispatch(priorNotificationActions.openPriorNotification(OpenedPriorNotificationType.LogbookForm)) const logbookPriorNotification = await dispatch( diff --git a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts index 8784a469e0..7227c28cc8 100644 --- a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts +++ b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts @@ -26,6 +26,10 @@ export const openManualPriorNotificationForm = async dispatch => { try { if (identifier) { + customSentry.startMeasurement( + CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_LOADING, + identifier.reportId + ) customSentry.startMeasurement( CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, identifier.reportId @@ -34,6 +38,10 @@ export const openManualPriorNotificationForm = dispatch(displayedErrorActions.unset(DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_FORM_ERROR)) dispatch(priorNotificationActions.closePriorNotificationCardAndForm()) + // TODO Remove this function once loading / spinner perfs tests are removed. + if (identifier) { + dispatch(priorNotificationActions.setEditedPriorNotificationId(identifier.reportId)) + } dispatch(priorNotificationActions.openPriorNotification(OpenedPriorNotificationType.ManualForm)) if (!identifier) { diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts index 9a63f466e8..e133b2b136 100644 --- a/frontend/src/libs/customSentry.ts +++ b/frontend/src/libs/customSentry.ts @@ -10,9 +10,12 @@ type CustomSentryMeasurementValue = { } export enum CustomSentryMeasurementName { + LOGBOOK_PRIOR_NOTIFICATION_FORM_LOADING = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_LOADING', LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER', + MANUAL_PRIOR_NOTIFICATION_FORM_LOADING = 'MANUAL_PRIOR_NOTIFICATION_FORM_LOADING', MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER = 'MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER', PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON = 'PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON', + PRIOR_NOTIFICATION_LIST_BODY_LOADING = 'PRIOR_NOTIFICATION_LIST_BODY_LOADING', PRIOR_NOTIFICATION_LIST_BODY_SPINNER = 'PRIOR_NOTIFICATION_LIST_BODY_SPINNER' } diff --git a/frontend/src/ui/LoadingSpinnerWall.tsx b/frontend/src/ui/LoadingSpinnerWall.tsx index 7a773738db..c49c03ee77 100644 --- a/frontend/src/ui/LoadingSpinnerWall.tsx +++ b/frontend/src/ui/LoadingSpinnerWall.tsx @@ -1,14 +1,42 @@ import { FulfillingBouncingCircleSpinner } from '@components/FulfillingBouncingCircleSpinner' +import { customSentry, type CustomSentryMeasurementName } from '@libs/customSentry' import { THEME } from '@mtes-mct/monitor-ui' +import { useEffect } from 'react' import styled from 'styled-components' import VesselSVG from '../features/icons/Icone_navire.svg?react' export type LoadingSpinnerWallProps = { + customSentryProps?: + | { + id: string + maxExpectedDurationInMs?: number + name: CustomSentryMeasurementName + } + | undefined isVesselShowed?: boolean message?: string } -export function LoadingSpinnerWall({ isVesselShowed = false, message = 'Chargement...' }: LoadingSpinnerWallProps) { +export function LoadingSpinnerWall({ + customSentryProps, + isVesselShowed = false, + message = 'Chargement...' +}: LoadingSpinnerWallProps) { + useEffect( + () => () => { + if (!customSentryProps) { + return + } + + customSentry.endMeasurement( + customSentryProps.name, + customSentryProps.id, + customSentryProps.maxExpectedDurationInMs + ) + }, + [customSentryProps] + ) + return (