Skip to content

Commit bb3e1ba

Browse files
Merge pull request #450 from monkvision/fix/sentry-sdk-for-client
Modify SDK with Sentry code to make Sentry config easy and minimal in client app
2 parents 79bc7d7 + badabb8 commit bb3e1ba

File tree

2 files changed

+98
-85
lines changed

2 files changed

+98
-85
lines changed

packages/camera/src/components/Capture/capture.js

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { utils } from '@monkvision/toolkit';
2+
import { useMonitoring, MonitoringStatus, SentryTransaction, SentryOperation, SentryTag } from '@monkvision/corejs';
23
import PropTypes from 'prop-types';
3-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
4+
import React, { forwardRef, useCallback, useEffect, useRef, useImperativeHandle, useMemo, useState } from 'react';
45

56
import { useTranslation } from 'react-i18next';
67
import { ActivityIndicator, Platform, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
@@ -122,9 +123,6 @@ const Capture = forwardRef(({
122123
onPictureTaken,
123124
onWarningMessage,
124125
onReady,
125-
onRetakeAll,
126-
onRetakeNeeded,
127-
onSkipRetake,
128126
onStartUploadPicture,
129127
onFinishUploadPicture,
130128
orientationBlockerProps,
@@ -156,7 +154,9 @@ const Capture = forwardRef(({
156154
});
157155
const [endTour, setEndTour] = useState(false);
158156
const { height, width } = useWindowDimensions();
157+
const { errorHandler, measurePerformance } = useMonitoring();
159158

159+
const captureTourTransRef = useRef({});
160160
const { camera, ref } = combinedRefs.current;
161161
const { current } = sights.state;
162162
const portraitMediaQuery = useMediaQuery({ query: '(orientation: portrait)' });
@@ -244,14 +244,25 @@ const Capture = forwardRef(({
244244

245245
const checkComplianceParams = { compliance, inspectionId, sightId: current.id };
246246
const checkComplianceAsync = useCheckComplianceAsync(checkComplianceParams);
247+
const handleCaptureTourFinish = useCallback(() => {
248+
/**
249+
* finish 'capture tour' transaction successfully
250+
* this function will be triggered when 'capture tour' ends
251+
*/
252+
if (!enableComplianceCheck) {
253+
utils.log(['[Event] Capture-Tour sentry transaction finishes']);
254+
captureTourTransRef.current.transaction.finish();
255+
}
256+
onCaptureTourFinish();
257+
}, []);
247258
const startUploadAsyncParams = {
248259
inspectionId,
249260
sights,
250261
uploads,
251262
task,
252263
mapTasksToSights,
253264
enableCarCoverage,
254-
onFinish: onCaptureTourFinish,
265+
onFinish: handleCaptureTourFinish,
255266
onPictureUploaded,
256267
onWarningMessage,
257268
endTour,
@@ -348,6 +359,9 @@ const Capture = forwardRef(({
348359
if (typeof onCloseEarly === 'function') {
349360
onCloseEarly();
350361
}
362+
// finish 'capture tour' transaction unsuccessfully
363+
utils.log(['[Event] Capture-Tour sentry transaction cancels']);
364+
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
351365
setEndTour(true);
352366
}, [setEndTour]);
353367

@@ -377,14 +391,80 @@ const Capture = forwardRef(({
377391
handleCloseCaptureEarly();
378392
}, [setCloseEarlyModalState, handleCloseCaptureEarly]);
379393

394+
const handleComplianceCheckFinish = useCallback(() => {
395+
/**
396+
* finish 'capture tour' transaction successfully
397+
* this function will be triggered only when
398+
* enableComplianceCheck = true and UploadCenter component is rendered
399+
*/
400+
utils.log(['[Event] Capture-Tour sentry transaction finishes']);
401+
captureTourTransRef.current.transaction.finish();
402+
onComplianceCheckFinish();
403+
}, []);
404+
405+
const onRetakeAll = useCallback(() => {
406+
captureTourTransRef.current.hasRetakeCalled = true;
407+
captureTourTransRef.current.transaction.setTag(SentryTag.IS_RETAKE, 1);
408+
}, []);
409+
410+
const onSkipRetake = useCallback(() => {
411+
captureTourTransRef.current.transaction.setTag(SentryTag.IS_SKIP, 1);
412+
}, []);
413+
414+
const onRetakeNeeded = useCallback(({ retakesNeeded = 0 }) => {
415+
if (!captureTourTransRef.current.hasRetakeCalled) {
416+
const { transaction } = captureTourTransRef.current;
417+
const percentOfNonCompliancePics = ((100 * retakesNeeded) / states.sights.state.ids.length);
418+
transaction.setTag(SentryTag.RETAKEN_PICTURES, retakesNeeded);
419+
transaction.setTag(SentryTag.PERCENT_OF_NON_COMPLIANCE_PICS, percentOfNonCompliancePics);
420+
}
421+
}, []);
422+
380423
// END HANDLERS //
381424
// EFFECTS //
382425

426+
useEffect(() => {
427+
/**
428+
* create a new transaction with operation name 'Capture Tour' to measure tour performance
429+
*/
430+
utils.log(['[Event] Capture-Tour sentry transaction starts']);
431+
const transaction = measurePerformance(
432+
SentryTransaction.PICTURE_PROCESSING,
433+
SentryOperation.CAPTURE_TOUR,
434+
);
435+
// set tags to identify a transation and relate with an inspection
436+
transaction.setTag(SentryTag.TASK, task);
437+
transaction.setTag(SentryTag.INSPECTION_ID, inspectionId);
438+
transaction.setTag(SentryTag.IS_SKIP, 0);
439+
transaction.setTag(SentryTag.IS_RETAKE, 0);
440+
transaction.setTag(SentryTag.TAKEN_PICTURES, 0);
441+
transaction.setTag(SentryTag.RETAKEN_PICTURES, 0);
442+
captureTourTransRef.current = {
443+
transaction,
444+
takenPictures: 0,
445+
hasRetakeCalled: false,
446+
};
447+
}, []);
448+
383449
useEffect(() => {
384450
try {
451+
/**
452+
* add takenPictures tag in "Capture Tour" transaction for a tour
453+
*/
454+
const takenPicturesLen = Object.values(states.sights.state.takenPictures).length;
455+
const refObj = captureTourTransRef.current;
456+
if (takenPicturesLen
457+
&& refObj.transaction
458+
&& !refObj.hasRetakeCalled
459+
&& takenPicturesLen !== refObj.takenPictures
460+
) {
461+
refObj.takenPictures = takenPicturesLen;
462+
refObj.transaction.setTag(SentryTag.TAKEN_PICTURES, takenPicturesLen);
463+
}
385464
onChange(states, api);
386465
} catch (err) {
387466
log([`Error in \`<Capture />\` \`onChange()\`: ${err}`], 'error');
467+
errorHandler(err);
388468
throw err;
389469
}
390470
}, [api, onChange, states]);
@@ -483,7 +563,7 @@ const Capture = forwardRef(({
483563
<UploadCenter
484564
{...states}
485565
isSubmitting={isSubmitting}
486-
onComplianceCheckFinish={onComplianceCheckFinish}
566+
onComplianceCheckFinish={handleComplianceCheckFinish}
487567
onComplianceCheckStart={onComplianceCheckStart}
488568
onRetakeAll={onRetakeAll}
489569
onSkipRetake={onSkipRetake}
@@ -676,11 +756,8 @@ Capture.propTypes = {
676756
onPictureTaken: PropTypes.func,
677757
onPictureUploaded: PropTypes.func,
678758
onReady: PropTypes.func,
679-
onRetakeAll: PropTypes.func,
680-
onRetakeNeeded: PropTypes.func,
681759
onSettingsChange: PropTypes.func,
682760
onSightsChange: PropTypes.func,
683-
onSkipRetake: PropTypes.func,
684761
onStartUploadPicture: PropTypes.func,
685762
onUploadsChange: PropTypes.func,
686763
onWarningMessage: PropTypes.func,
@@ -789,16 +866,13 @@ Capture.defaultProps = {
789866
onComplianceChange: () => {},
790867
onSettingsChange: () => {},
791868
onSightsChange: () => {},
792-
onSkipRetake: () => {},
793869
onUploadsChange: () => {},
794870
onComplianceCheckFinish: () => {},
795871
onComplianceCheckStart: () => {},
796872
onFinishUploadPicture: () => {},
797873
onWarningMessage: () => {},
798874
onReady: () => {},
799875
onStartUploadPicture: () => {},
800-
onRetakeAll: () => {},
801-
onRetakeNeeded: () => {},
802876
orientationBlockerProps: null,
803877
primaryColor: '#FFF',
804878
resolutionOptions: undefined,

src/screens/InspectionCapture/index.js

Lines changed: 12 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useTheme } from 'react-native-paper';
66
import { Alert, Platform, View } from 'react-native';
77

88
import { Capture, Controls } from '@monkvision/camera';
9-
import monk, { useMonitoring, MonitoringStatus, SentryTransaction, SentryOperation, SentryTag } from '@monkvision/corejs';
9+
import monk, { useMonitoring } from '@monkvision/corejs';
1010
import { utils } from '@monkvision/toolkit';
1111

1212
import * as names from 'screens/names';
@@ -23,15 +23,14 @@ export default function InspectionCapture() {
2323
const dispatch = useDispatch();
2424
const { t } = useTranslation();
2525
const { colors } = useTheme();
26-
const { errorHandler, measurePerformance } = useMonitoring();
26+
const { errorHandler } = useMonitoring();
2727

2828
const { inspectionId, sightIds, taskName, vehicleType, selectedMode } = route.params;
2929

3030
const [isFocused, setFocused] = useState(false);
3131
const [success, setSuccess] = useState(false);
3232
const [cameraLoading, setCameraLoading] = useState(false);
3333
const { setShowMessage, Notice } = useSnackbar();
34-
const captureTourTransRef = useRef({});
3534
const { isFullscreen, requestFullscreen } = useFullscreen();
3635

3736
const handleNavigate = useCallback((confirm = false) => {
@@ -40,11 +39,6 @@ export default function InspectionCapture() {
4039
// eslint-disable-next-line no-alert
4140
const ok = window.confirm(t('capture.quit.title'));
4241
if (ok) {
43-
/**
44-
* cancel 'Capture Tour' transaction and navigate back to landing page
45-
*/
46-
utils.log(['[Click]', 'User suddenly quit the inspection']);
47-
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
4842
navigation.navigate(names.LANDING, { inspectionId });
4943
}
5044
}
@@ -58,11 +52,6 @@ export default function InspectionCapture() {
5852
}, {
5953
text: t('capture.quit.ok'),
6054
onPress: () => {
61-
/**
62-
* cancel 'Capture Tour' transaction and navigate back to landing page
63-
*/
64-
utils.log(['[Click]', 'User suddenly quit the inspection']);
65-
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
6655
navigation.navigate(names.LANDING, { inspectionId });
6756
},
6857
}],
@@ -103,10 +92,9 @@ export default function InspectionCapture() {
10392
setCameraLoading(false);
10493

10594
/**
106-
* finish 'capture tour' transaction and navigate back to landing page
95+
* navigate back to landing page
10796
*/
10897
utils.log(['[Event] Back to landing page with photo taken']);
109-
captureTourTransRef.current.transaction.finish();
11098
handleNavigate();
11199
} catch (err) {
112100
errorHandler(err);
@@ -116,20 +104,6 @@ export default function InspectionCapture() {
116104
}, [dispatch, handleNavigate, inspectionId, success, taskName, isFocused]);
117105

118106
const handleChange = useCallback((state) => {
119-
/**
120-
* add takenPictures tag in "Capture Tour" transaction for a tour
121-
*/
122-
const takenPicturesLen = Object.values(state.sights.state.takenPictures).length;
123-
const refObj = captureTourTransRef.current;
124-
if (takenPicturesLen
125-
&& refObj.transaction
126-
&& !refObj.hasRetakeCalled
127-
&& takenPicturesLen !== refObj.takenPictures
128-
) {
129-
refObj.takenPictures = takenPicturesLen;
130-
refObj.transaction.setTag(SentryTag.TAKEN_PICTURES, takenPicturesLen);
131-
}
132-
//
133107
if (!success && isFocused && !enableComplianceCheck) {
134108
try {
135109
const { takenPictures, tour } = state.sights.state;
@@ -160,8 +134,6 @@ export default function InspectionCapture() {
160134
}
161135
} catch (err) {
162136
errorHandler(err);
163-
// eslint-disable-next-line no-console
164-
console.error(err);
165137
throw err;
166138
}
167139
}
@@ -179,49 +151,19 @@ export default function InspectionCapture() {
179151
{ disabled: cameraLoading, ...Controls.AddDamageButtonProps },
180152
{ disabled: cameraLoading, ...Controls.CaptureButtonProps },
181153
],
182-
{ disabled: cameraLoading, onPress: () => handleNavigate(true), ...Controls.GoBackButtonProps },
154+
{
155+
...Controls.CloseEarlyButtonProps,
156+
confirm: true,
157+
confirmationMessage: {
158+
en: 'Your inspection is not complete, are you sure you want to stop it ?',
159+
fr: 'Votre inspection n\'est pas complète, êtes-vous sûr(e) de vouloir l\'arrêter ?',
160+
},
161+
disabled: cameraLoading,
162+
},
183163
];
184164

185-
const onRetakeAll = useCallback(() => {
186-
captureTourTransRef.current.hasRetakeCalled = true;
187-
captureTourTransRef.current.transaction.setTag(SentryTag.IS_RETAKE, 1);
188-
}, []);
189-
const onSkipRetake = useCallback(() => {
190-
captureTourTransRef.current.transaction.setTag(SentryTag.IS_SKIP, 1);
191-
}, []);
192-
const onRetakeNeeded = useCallback(({ retakesNeeded = 0 }) => {
193-
if (!captureTourTransRef.current.hasRetakeCalled) {
194-
const { transaction } = captureTourTransRef.current;
195-
const percentOfNonCompliancePics = ((100 * retakesNeeded) / sightIds.length);
196-
transaction.setTag(SentryTag.RETAKEN_PICTURES, retakesNeeded);
197-
transaction.setTag(SentryTag.PERCENT_OF_NON_COMPLIANCE_PICS, percentOfNonCompliancePics);
198-
}
199-
}, []);
200-
201165
useEffect(() => { if (success) { handleSuccess(); } }, [handleSuccess, success]);
202166

203-
useEffect(() => {
204-
/**
205-
* create a new transaction with operation name 'Capture Tour' to measure tour performance
206-
*/
207-
const transaction = measurePerformance(
208-
SentryTransaction.PICTURE_PROCESSING,
209-
SentryOperation.CAPTURE_TOUR,
210-
);
211-
// set tags to identify a transation and relate with an inspection
212-
transaction.setTag(SentryTag.TASK, taskName);
213-
transaction.setTag(SentryTag.INSPECTION_ID, inspectionId);
214-
transaction.setTag(SentryTag.IS_SKIP, 0);
215-
transaction.setTag(SentryTag.IS_RETAKE, 0);
216-
transaction.setTag(SentryTag.TAKEN_PICTURES, 0);
217-
transaction.setTag(SentryTag.RETAKEN_PICTURES, 0);
218-
captureTourTransRef.current = {
219-
transaction,
220-
takenPictures: 0,
221-
hasRetakeCalled: false,
222-
};
223-
}, []);
224-
225167
useFocusEffect(() => {
226168
setFocused(true);
227169
return () => setFocused(false);
@@ -243,9 +185,6 @@ export default function InspectionCapture() {
243185
onFinishUploadPicture={() => setCameraLoading(false)}
244186
onWarningMessage={(message) => setShowMessage(message)}
245187
onChange={handleChange}
246-
onRetakeAll={onRetakeAll}
247-
onSkipRetake={onSkipRetake}
248-
onRetakeNeeded={onRetakeNeeded}
249188
enableCarCoverage
250189
enableComplianceCheck={enableComplianceCheck}
251190
onComplianceCheckFinish={() => setSuccess(true)}

0 commit comments

Comments
 (0)