From bcb177efd458e4cd752ea8ebaf380ca34ebbc64b Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Thu, 12 Sep 2024 10:20:14 +0200 Subject: [PATCH 1/8] Fix measurement name in openManualPriorNotificationForm() hook --- .../useCases/openManualPriorNotificationForm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts index 69d812fff5..8784a469e0 100644 --- a/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts +++ b/frontend/src/features/PriorNotification/useCases/openManualPriorNotificationForm.ts @@ -27,7 +27,7 @@ export const openManualPriorNotificationForm = try { if (identifier) { customSentry.startMeasurement( - CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, + CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, identifier.reportId ) } From ed74b3975e12308948becb70642ee3fcb486c0a8 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Thu, 12 Sep 2024 10:22:17 +0200 Subject: [PATCH 2/8] Use span rather than obsolete & non-working metrics in customSentry lib --- frontend/src/libs/customSentry.ts | 59 +++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts index 93a42196b6..2ffef93909 100644 --- a/frontend/src/libs/customSentry.ts +++ b/frontend/src/libs/customSentry.ts @@ -1,10 +1,12 @@ /* eslint-disable no-empty */ -import { metrics, setMeasurement } from '@sentry/react' +import { ONE_MINUTE } from '@constants/index' +import { captureMessage, Scope, startInactiveSpan, type Span } from '@sentry/react' type CustomSentryMeasurementValue = { - id: string - value: number + span: Span + /** Epoch in ms */ + startDate: number } export enum CustomSentryMeasurementName { @@ -17,6 +19,8 @@ class CustomSentry { mesurements: Map = new Map() clearMeasurement(name: CustomSentryMeasurementName, id: string) { + console.info('startMeasurement') + try { const key = `${name}-${id}` if (!this.mesurements.has(key)) { @@ -28,18 +32,37 @@ class CustomSentry { } startMeasurement(name: CustomSentryMeasurementName, id: string) { + console.info('startMeasurement') + try { + const startDate = Date.now() const key = `${name}-${id}` - const value = Date.now() if (this.mesurements.has(key)) { return } - this.mesurements.set(key, { id, value }) + const newScope = new Scope() + newScope.setTags({ + side: 'frontend', + type: 'performance' + }) + const newSpan = startInactiveSpan({ name: key, scope: newScope }) + if (!newSpan) { + return + } + + this.mesurements.set(key, { span: newSpan, startDate }) + + // Delete the key after 1m in case `endMeasurement()` is never called + setTimeout(() => { + this.clearMeasurement(name, id) + }, ONE_MINUTE) } catch (_) {} } - endMeasurement(name: CustomSentryMeasurementName, id: string) { + endMeasurement(name: CustomSentryMeasurementName, id: string, maxExpectedDurationInMs?: number) { + console.info('endMeasurement') + try { const key = `${name}-${id}` const measurement = this.mesurements.get(key) @@ -47,11 +70,25 @@ class CustomSentry { return } - setMeasurement(name, Date.now() - measurement.value, 'millisecond') - metrics.distribution(name, measurement.value, { - tags: { type: 'important' }, - unit: 'millisecond' - }) + measurement.span.end() + + const durationInMs = Date.now() - measurement.startDate + if (maxExpectedDurationInMs && durationInMs > maxExpectedDurationInMs) { + const messageScope = new Scope() + messageScope.setTags({ + side: 'frontend', + type: 'performance' + }) + + const message = captureMessage(`${name} took more than ${maxExpectedDurationInMs / 1000}s.`, { + level: 'warning', + tags: { + side: 'frontend', + type: 'performance' + } + }) + console.warn('[MonitorFish]', message) + } this.mesurements.delete(key) } catch (_) {} From 4b5cf4d92d27ad1e05bdb5564bb6c6dbb9fa39b5 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Thu, 12 Sep 2024 10:42:28 +0200 Subject: [PATCH 3/8] Add some missing styled component prop prefixes --- .../Mission/components/MissionOverlay/MissionDetails.tsx | 6 +++--- .../components/PriorNotificationCard/index.tsx | 6 +++--- .../SideWindow/Alert/AlertListAndReportingList/index.tsx | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/src/features/Mission/components/MissionOverlay/MissionDetails.tsx b/frontend/src/features/Mission/components/MissionOverlay/MissionDetails.tsx index edb3c4ad87..b15a1d4357 100644 --- a/frontend/src/features/Mission/components/MissionOverlay/MissionDetails.tsx +++ b/frontend/src/features/Mission/components/MissionOverlay/MissionDetails.tsx @@ -68,7 +68,7 @@ export function MissionDetails({ isSelected, mission, overlayPosition }: Mission /> )} - + <Title $isSelected={isSelected}> {mission.controlUnits.length === 1 && mission.controlUnits.map((controlUnit: LegacyControlUnit.LegacyControlUnit) => ( <Fragment key={controlUnit.id}> @@ -176,12 +176,12 @@ const Details = styled.div` ` const Title = styled.div<{ - isSelected: boolean + $isSelected: boolean }>` height: 40px; font: normal normal bold 13px/18px Marianne; color: ${p => p.theme.color.gunMetal}; - width: ${p => (p.isSelected ? 90 : 100)}%; + width: ${p => (p.$isSelected ? 90 : 100)}%; ` const Wrapper = styled.div` diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx index b81b4e40d4..2ecbc6a09e 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx @@ -101,7 +101,7 @@ export function PriorNotificationCard({ /> {isPendingVerification && <Intro>Le préavis doit être vérifié par le CNSP avant sa diffusion.</Intro>} - <Intro hasNoTopMargin={isPendingVerification}> + <Intro $hasNoTopMargin={isPendingVerification}> Le navire doit respecter un délai d’envoi{hasDesignatedPorts && ' et débarquer dans un port désigné'}. </Intro> @@ -155,9 +155,9 @@ const Body = styled.div` ` const Intro = styled.p<{ - hasNoTopMargin?: boolean + $hasNoTopMargin?: boolean }>` - ${p => p.hasNoTopMargin && 'margin-top: 2px;'} + ${p => p.$hasNoTopMargin && 'margin-top: 2px;'} color: ${p => p.theme.color.slateGray}; font-style: italic; ` diff --git a/frontend/src/features/SideWindow/Alert/AlertListAndReportingList/index.tsx b/frontend/src/features/SideWindow/Alert/AlertListAndReportingList/index.tsx index b9d3f51286..155f1f4d81 100644 --- a/frontend/src/features/SideWindow/Alert/AlertListAndReportingList/index.tsx +++ b/frontend/src/features/SideWindow/Alert/AlertListAndReportingList/index.tsx @@ -39,14 +39,14 @@ export function AlertListAndReportingList({ return ( <Wrapper> <Title - isSelected={selectedTab === AlertAndReportingTab.ALERT} + $isSelected={selectedTab === AlertAndReportingTab.ALERT} onClick={() => setSelectedTab(AlertAndReportingTab.ALERT)} > Alertes setSelectedTab(AlertAndReportingTab.REPORTING)} > Signalements @@ -75,9 +75,9 @@ const Wrapper = styled.div` // TODO This should be a `<a />` or a `<button />`. const Title = styled.h2<{ - isSelected: boolean + $isSelected: boolean }>` - border-bottom: 5px solid ${p => (p.isSelected ? p.theme.color.charcoal : p.theme.color.white)}; + border-bottom: 5px solid ${p => (p.$isSelected ? p.theme.color.charcoal : p.theme.color.white)}; color: ${p => p.theme.color.gunMetal}; cursor: pointer; display: inline-block; From b51ece5e7d69b35ab77bd00e16227deafbafa7fd Mon Sep 17 00:00:00 2001 From: Ivan Gabriele <ivan.gabriele@protonmail.com> Date: Thu, 12 Sep 2024 10:43:37 +0200 Subject: [PATCH 4/8] Remove console infos in customSentry lib --- frontend/src/libs/customSentry.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts index 2ffef93909..5ab7ea3f38 100644 --- a/frontend/src/libs/customSentry.ts +++ b/frontend/src/libs/customSentry.ts @@ -19,8 +19,6 @@ class CustomSentry { mesurements: Map<string, CustomSentryMeasurementValue> = new Map() clearMeasurement(name: CustomSentryMeasurementName, id: string) { - console.info('startMeasurement') - try { const key = `${name}-${id}` if (!this.mesurements.has(key)) { @@ -32,8 +30,6 @@ class CustomSentry { } startMeasurement(name: CustomSentryMeasurementName, id: string) { - console.info('startMeasurement') - try { const startDate = Date.now() const key = `${name}-${id}` @@ -61,8 +57,6 @@ class CustomSentry { } endMeasurement(name: CustomSentryMeasurementName, id: string, maxExpectedDurationInMs?: number) { - console.info('endMeasurement') - try { const key = `${name}-${id}` const measurement = this.mesurements.get(key) @@ -73,20 +67,22 @@ class CustomSentry { measurement.span.end() const durationInMs = Date.now() - measurement.startDate - if (maxExpectedDurationInMs && durationInMs > maxExpectedDurationInMs) { + if (maxExpectedDurationInMs !== undefined && durationInMs > maxExpectedDurationInMs) { const messageScope = new Scope() messageScope.setTags({ side: 'frontend', type: 'performance' }) - const message = captureMessage(`${name} took more than ${maxExpectedDurationInMs / 1000}s.`, { + const message = `${name} took more than ${maxExpectedDurationInMs / 1000}s.` + captureMessage(message, { level: 'warning', tags: { side: 'frontend', type: 'performance' } }) + console.warn('[MonitorFish]', message) } From 21ac8d26b195462517503d10fa40d94c43599fdf Mon Sep 17 00:00:00 2001 From: Ivan Gabriele <ivan.gabriele@protonmail.com> Date: Thu, 12 Sep 2024 10:45:33 +0200 Subject: [PATCH 5/8] Add 2s loading spinner perf measurement threshold in pno forms --- .../components/LogbookPriorNotificationForm/index.tsx | 3 ++- .../components/ManualPriorNotificationForm/index.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx index 02d976c8e7..31a22e608e 100644 --- a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/index.tsx @@ -44,7 +44,8 @@ export function LogbookPriorNotificationForm() { customSentry.endMeasurement( CustomSentryMeasurementName.LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER, - openedPriorNotificationDetail.reportId + openedPriorNotificationDetail.reportId, + 2000 ) return ( diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx index 416983f828..9c7868cd01 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/index.tsx @@ -90,7 +90,8 @@ export function ManualPriorNotificationForm() { if (openedPriorNotificationDetail?.reportId) { customSentry.endMeasurement( CustomSentryMeasurementName.MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER, - openedPriorNotificationDetail.reportId + openedPriorNotificationDetail.reportId, + 2000 ) } From 12841e7639bf5e6c96fdfdbd43af8655c982f3e3 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele <ivan.gabriele@protonmail.com> Date: Thu, 12 Sep 2024 10:52:17 +0200 Subject: [PATCH 6/8] Track pno list loading spinner display with a 2s thereshold alert --- .../components/PriorNotificationList/index.tsx | 7 +++++++ frontend/src/libs/customSentry.ts | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx index 60032d2c73..3fd47b75de 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx @@ -14,6 +14,7 @@ import { useListSorting } from '@hooks/useListSorting' import { useLoadingState } from '@hooks/useLoadingState' import { useMainAppDispatch } from '@hooks/useMainAppDispatch' import { useMainAppSelector } from '@hooks/useMainAppSelector' +import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { DisplayedErrorKey } from '@libs/DisplayedError/constants' import { Accent, Button, Icon, Size, TableWithSelectableRows, usePrevious } from '@mtes-mct/monitor-ui' import { skipToken } from '@reduxjs/toolkit/query' @@ -144,6 +145,12 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps) } }, [previousListFilter, listFilter, table]) + if (isBodyLoaderVisible) { + customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0') + } else { + customSentry.endMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0', 2000) + } + return ( <> <SubMenu diff --git a/frontend/src/libs/customSentry.ts b/frontend/src/libs/customSentry.ts index 5ab7ea3f38..9a63f466e8 100644 --- a/frontend/src/libs/customSentry.ts +++ b/frontend/src/libs/customSentry.ts @@ -12,7 +12,8 @@ type CustomSentryMeasurementValue = { 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' + PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON = 'PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON', + PRIOR_NOTIFICATION_LIST_BODY_SPINNER = 'PRIOR_NOTIFICATION_LIST_BODY_SPINNER' } class CustomSentry { From 8ea26c23edaec39a8fda2e8c308205a323fc8964 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele <ivan.gabriele@protonmail.com> Date: Thu, 12 Sep 2024 10:55:13 +0200 Subject: [PATCH 7/8] Add 2s download button enabling perf measurement threshold in pno forms --- .../shared/DownloadButton/index.tsx | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx index 87284b9b83..46d9607e97 100644 --- a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx +++ b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx @@ -10,7 +10,7 @@ import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' import { Accent, Button, customDayjs, Dropdown, Icon, usePrevious } from '@mtes-mct/monitor-ui' import { downloadFile } from '@utils/downloadFile' import printJS from 'print-js' -import { useEffect, useMemo } from 'react' +import { useMemo } from 'react' import { HTML_STYLE } from './template' import { getHasAuthorizedLandingDownload, getHtmlContent } from './utils' @@ -34,8 +34,6 @@ 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 = @@ -79,17 +77,11 @@ export function DownloadButton({ downloadFile(fileName, 'application/pdf', 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]) + if (isDisabled) { + customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON, reportId) + } else { + customSentry.endMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON, reportId, 1000) + } return ( <> From 82dd985425fb7abf4967980b819f30e235b1d2db Mon Sep 17 00:00:00 2001 From: Ivan Gabriele <ivan.gabriele@protonmail.com> Date: Thu, 12 Sep 2024 11:09:51 +0200 Subject: [PATCH 8/8] Fix lint error in DowloadButton --- .../components/shared/DownloadButton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx index 46d9607e97..b79e68a968 100644 --- a/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx +++ b/frontend/src/features/PriorNotification/components/shared/DownloadButton/index.tsx @@ -7,7 +7,7 @@ import { useGetPriorNotificationPdfExistenceQuery } from '@features/PriorNotification/priorNotificationApi' import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry' -import { Accent, Button, customDayjs, Dropdown, Icon, usePrevious } from '@mtes-mct/monitor-ui' +import { Accent, Button, customDayjs, Dropdown, Icon } from '@mtes-mct/monitor-ui' import { downloadFile } from '@utils/downloadFile' import printJS from 'print-js' import { useMemo } from 'react'