From 6100284f1c238fd32f1672a1b033383e6775dab0 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Wed, 4 Sep 2024 10:25:44 +0200 Subject: [PATCH 1/4] Add customSentry lib in Frontend --- frontend/src/libs/customSentry.ts | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 frontend/src/libs/customSentry.ts diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts new file mode 100644 index 0000000000..8a257aa439 --- /dev/null +++ b/frontend/src/libs/customSentry.ts @@ -0,0 +1,51 @@ +/* eslint-disable no-empty */ + +import { metrics, setMeasurement } from '@sentry/react' + +type CustomSentryMeasurementValue = { + id: string + value: number +} + +export enum CustomSentryMeasurementName { + LOGBOOK_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON', + LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER', + MANUAL_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON = 'MANUAL_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON', + MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER = 'MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER' +} + +class CustomSentry { + mesurements: Map = new Map() + + 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() From 67631ed6ecdf2f16475dbfd439af1efef73b0265 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Wed, 4 Sep 2024 10:26:37 +0200 Subject: [PATCH 2/4] Track manual prior notification form spinner time --- .../components/ManualPriorNotificationForm/index.tsx | 8 ++++++++ .../useCases/openManualPriorNotificationForm.ts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx index a6286f19cb..416983f828 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx @@ -3,6 +3,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' import { Formik } from 'formik' @@ -86,6 +87,13 @@ export function ManualPriorNotificationForm() { ) } + if (openedPriorNotificationDetail?.reportId) { + customSentry.endMeasurement( + CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, + openedPriorNotificationDetail.reportId + ) + } + return ( > => 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)) From 119c10f8bd53b06188b465b37623040213a05644 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Wed, 4 Sep 2024 10:31:20 +0200 Subject: [PATCH 3/4] Track logbook prior notification form spinner time --- .../components/LogbookPriorNotificationForm/index.tsx | 6 ++++++ .../useCases/openLogbookPriorNotificationForm.ts | 6 ++++++ 2 files changed, 12 insertions(+) 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 ( > => 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)) From 8912d59d725ac6ffa810aa300112cfaf028b0c39 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Wed, 4 Sep 2024 10:38:20 +0200 Subject: [PATCH 4/4] Track prior notification card download button enabling time --- .../shared/DownloadButton/index.tsx | 19 +++++++++++++++++-- frontend/src/libs/customSentry.ts | 16 +++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx index 62c6cabb9b..56cf8875e0 100644 --- a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx +++ b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx @@ -6,10 +6,11 @@ import { StatusBodyEnum, useGetPriorNotificationPdfExistenceQuery } from '@features/PriorNotification/priorNotificationApi' -import { Accent, Button, customDayjs, Dropdown, Icon } from '@mtes-mct/monitor-ui' +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' +import { Accent, Button, customDayjs, Dropdown, Icon, usePrevious } from '@mtes-mct/monitor-ui' import { downloadAsPdf } from '@utils/downloadAsPdf' import printJS from 'print-js' -import { useMemo } from 'react' +import { useEffect, useMemo } from 'react' import { HTML_STYLE } from './template' import { getHasAuthorizedLandingDownload, getHtmlContent } from './utils' @@ -33,6 +34,8 @@ export function DownloadButton({ const getGearsApiQuery = useGetGearsQuery() const { data } = useGetPriorNotificationPdfExistenceQuery(reportId, RTK_ONE_MINUTE_POLLING_QUERY_OPTIONS) + const wasDisabled = usePrevious(isDisabled) + const isPriorNotificationDocumentAvailable = useMemo(() => 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/libs/customSentry.ts b/frontend/src/libs/customSentry.ts index 8a257aa439..93a42196b6 100644 --- a/frontend/src/libs/customSentry.ts +++ b/frontend/src/libs/customSentry.ts @@ -8,15 +8,25 @@ type CustomSentryMeasurementValue = { } export enum CustomSentryMeasurementName { - LOGBOOK_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON', LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER', - MANUAL_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON = 'MANUAL_PRIOR_NOTIFICATION_FORM_DOWNLOAD_BUTTON', - MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER = 'MANUAL_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}`