Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NO QA]Feature: Critical Error Handling #3527

Merged
merged 8 commits into from
Jun 11, 2021

Conversation

kidroca
Copy link
Contributor

@kidroca kidroca commented Jun 10, 2021

@Jag96

Details

Created a new ErrorBoundary component
This component can serve to warp the whole app, or specific parts like documented here: https://reactjs.org/docs/error-boundaries.html#where-to-place-error-boundaries

@react-native-firebase/crashlytics is available only for iOS and Android so a platform specific component was created to handle the logging - Android and iOS would log to E.cash server and crashlytics, while desktop and web would log only to the E.cash server (Reference: invertase/react-native-firebase#1530)

Wrapped the main component Expensify with ErrorBoundary
For the moment we're not rendering fallback UI, but just log the error that crashed React to the server and crashlytics

Fixed Issues

Fixes #3339

Tests

To test this you can trigger an exception in the render method of some component
In my sample video (iOS screenshots section) I've changed ReportScreen to throw an error when a specific report is opened

QA Steps

N/A

Tested On

I've verified the app starts and works on these platforms

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web

image

Mobile Web

image

Desktop

image

iOS

Screen.Recording.2021-06-10.at.23.20.01.mov

Android

image

@kidroca kidroca requested a review from a team as a code owner June 10, 2021 21:26
@MelvinBot MelvinBot requested review from NikkiWines and removed request for a team June 10, 2021 21:26
tests/unit/loginTest.js Outdated Show resolved Hide resolved
@kidroca
Copy link
Contributor Author

kidroca commented Jun 10, 2021

Here's a sample content logged to the server on error:

[alrt] [App] A Crash was intercepted by the main error boundary -
{
    "error": "This is a dev test for the Error Boundary component",
    "errorInfo": {
        "componentStack": "
    at ReportScreen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:261999:81)
    at StaticContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27865:16)
    at EnsureSingleNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27513:23)
    at SceneView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27752:21)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at Background (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:34048:20)
    at Screen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:35217:107)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at NativeScreen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:176589:81)
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:195457:32)
    at AnimatedComponentWrapper
    at MaybeScreen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:32895:23)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at MaybeScreenContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:32881:22)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:161863:83)
    at AnimatedComponentWrapper
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:161863:83)
    at AnimatedComponentWrapper
    at Dummy (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:32815:23)
    at DrawerView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:33080:81)
    at DrawerViewBase (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:32556:21)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at SafeAreaProviderCompat (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:35166:23)
    at DrawerView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:32777:26)
    at DrawerNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:31778:31)
    at MainDrawerNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:251550:69)
    at withOnyx (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:148923:85)
    at WithWindowDimensions (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:248567:83)
    at StaticContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27865:16)
    at EnsureSingleNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27513:23)
    at SceneView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27752:21)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at CardSheet (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:42498:22)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:195457:32)
    at AnimatedComponentWrapper
    at Dummy (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:40970:23)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:195457:32)
    at AnimatedComponentWrapper
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at Card (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:41684:81)
    at CardContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:42207:20)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at NativeScreen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:176589:81)
    at AnimatedComponent (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:195457:32)
    at AnimatedComponentWrapper
    at MaybeScreen (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:41532:23)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at MaybeScreenContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:41520:22)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at Background (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:35468:20)
    at CardStack (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:42766:81)
    at SafeAreaProviderCompat (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:36586:23)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at StackView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:43178:81)
    at CustomRootStackNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:251852:23)
    at AuthScreens (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:251241:81)
    at withOnyx (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:148923:85)
    at WithWindowDimensions (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:248567:83)
    at AppNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:251907:16)
    at EnsureSingleNavigator (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27513:23)
    at BaseNavigationContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:27140:27)
    at ThemeProvider (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:37335:20)
    at NavigationContainerInner (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:37016:25)
    at NavigationRoot (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:252229:81)
    at Expensify (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:237802:81)
    at withOnyx (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:148923:85)
    at BaseErrorBoundary (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:240229:81)
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at NativeSafeAreaView (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:176002:23)
    at SafeAreaProvider (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:176183:24)
    at App
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at div
    at http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:186665:25
    at AppContainer (http://localhost:8080/app-20d106c1d4efa146f27f.bundle.js:177100:24)"
    }
}

Produced by

Log.alert(errorMessage, 0, {error: error.message, errorInfo}, false);

I've deliberately inserted new lines in the printout here, the log sent to the server is condensed as one line

The error logs as "{}" in the log, probably because it's a special object
Updated to pass the error message instead
The stack trace is not interesting as it just traces to
the moment we call `Log.alert` in `logError`
Also the `errorInfo` contains the actual stack from React
@kidroca
Copy link
Contributor Author

kidroca commented Jun 10, 2021

Updated

As per my last commit messages, I've spotted some small issues

update parameters because the error message is not logging
The error logs as "{}" in the log, probably because it's a special object
Updated to pass the error message instead

refactor: remove stack trace and set captured messages
The stack trace is not interesting as it just traces to
the moment we call Log.alert in logError
Also the errorInfo contains the actual stack from React

I'm done making any more updates, until the review passes

Copy link
Contributor

@Jag96 Jag96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a great improvement! I added a few comments and some screenshots after testing

src/App.js Outdated Show resolved Hide resolved
src/App.js Outdated Show resolved Hide resolved
src/components/ErrorBoundary/index.native.js Outdated Show resolved Hide resolved
tests/unit/loginTest.js Outdated Show resolved Hide resolved
@kidroca kidroca requested a review from Jag96 June 11, 2021 08:59
@kidroca
Copy link
Contributor Author

kidroca commented Jun 11, 2021

Thanks,
The requested changes are applied

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, leaving the final review to @Jag96

Copy link
Contributor

@Jag96 Jag96 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and tests well 👍

@Jag96 Jag96 merged commit be7fee0 into Expensify:main Jun 11, 2021
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging in version: 1.0.68-5🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

🚀 Deployed to production in version: 1.0.73-3🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[HOLD for payment + bonus on Jun 18] Feature: Critical Error Handling | Prevent white screens on startup
4 participants