diff --git a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx index f37214d585..02d976c8e7 100644 --- a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx @@ -2,6 +2,7 @@ import { verifyAndSendPriorNotification } from '@features/PriorNotification/useC import { getPriorNotificationIdentifier } from '@features/PriorNotification/utils' import { useMainAppDispatch } from '@hooks/useMainAppDispatch' import { useMainAppSelector } from '@hooks/useMainAppSelector' +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { DisplayedErrorKey } from '@libs/DisplayedError/constants' import { assertNotNullish } from '@utils/assertNotNullish' @@ -41,6 +42,11 @@ export function LogbookPriorNotificationForm() { return } + customSentry.endMeasurement( + CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, + openedPriorNotificationDetail.reportId + ) + return ( data?.status === StatusBodyEnum.FOUND, [data]) const hasAuthorizedLandingDownload = @@ -76,6 +79,18 @@ export function DownloadButton({ downloadAsPdf(fileName, blob) } + useEffect(() => { + if (isDisabled === wasDisabled) { + return + } + + if (isDisabled) { + customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON, reportId) + } else { + customSentry.endMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON, reportId) + } + }, [isDisabled, reportId, wasDisabled]) + return ( <> {hasAuthorizedLandingDownload && ( diff --git a/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts b/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts index 8f43670397..8e36de8eef 100644 --- a/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts +++ b/frontend/src/features/PriorNotification/useCases/openLogbookPriorNotificationForm.ts @@ -1,5 +1,6 @@ import { RtkCacheTagType } from '@api/constants' import { addMainWindowBanner } from '@features/SideWindow/useCases/addMainWindowBanner' +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { DisplayedErrorKey } from '@libs/DisplayedError/constants' import { FrontendApiError } from '@libs/FrontendApiError' import { FrontendError } from '@libs/FrontendError' @@ -19,6 +20,11 @@ export const openLogbookPriorNotificationForm = (identifier: PriorNotification.Identifier, fingerprint?: string): MainAppThunk> => async dispatch => { try { + customSentry.startMeasurement( + CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, + identifier.reportId + ) + dispatch(displayedErrorActions.unset(DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_FORM_ERROR)) dispatch(priorNotificationActions.closePriorNotificationCardAndForm()) dispatch(priorNotificationActions.openPriorNotification(OpenedPriorNotificationType.LogbookForm)) diff --git a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts index 53145c6715..69d812fff5 100644 --- a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts +++ b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts @@ -1,4 +1,5 @@ import { RtkCacheTagType } from '@api/constants' +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { DisplayedErrorKey } from '@libs/DisplayedError/constants' import { FrontendApiError } from '@libs/FrontendApiError' import { FrontendError } from '@libs/FrontendError' @@ -24,6 +25,13 @@ export const openManualPriorNotificationForm = ): MainAppThunk> => async dispatch => { try { + if (identifier) { + customSentry.startMeasurement( + CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, + identifier.reportId + ) + } + dispatch(displayedErrorActions.unset(DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_FORM_ERROR)) dispatch(priorNotificationActions.closePriorNotificationCardAndForm()) dispatch(priorNotificationActions.openPriorNotification(OpenedPriorNotificationType.ManualForm)) diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts new file mode 100644 index 0000000000..93a42196b6 --- /dev/null +++ b/frontend/src/libs/customSentry.ts @@ -0,0 +1,61 @@ +/* eslint-disable no-empty */ + +import { metrics, setMeasurement } from '@sentry/react' + +type CustomSentryMeasurementValue = { + id: string + value: number +} + +export enum CustomSentryMeasurementName { + LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER', + MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER = 'MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER', + PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON = 'PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON' +} + +class CustomSentry { + mesurements: Map = new Map() + + clearMeasurement(name: CustomSentryMeasurementName, id: string) { + try { + const key = `${name}-${id}` + if (!this.mesurements.has(key)) { + return + } + + this.mesurements.delete(key) + } catch (_) {} + } + + startMeasurement(name: CustomSentryMeasurementName, id: string) { + try { + const key = `${name}-${id}` + const value = Date.now() + if (this.mesurements.has(key)) { + return + } + + this.mesurements.set(key, { id, value }) + } catch (_) {} + } + + endMeasurement(name: CustomSentryMeasurementName, id: string) { + try { + const key = `${name}-${id}` + const measurement = this.mesurements.get(key) + if (!measurement) { + return + } + + setMeasurement(name, Date.now() - measurement.value, 'millisecond') + metrics.distribution(name, measurement.value, { + tags: { type: 'important' }, + unit: 'millisecond' + }) + + this.mesurements.delete(key) + } catch (_) {} + } +} + +export const customSentry = new CustomSentry()