Closed thevishnupradeep closed 6 years ago
I am using the following code in my app and I get errors recorded on both dev and production.
const defaultHandler = (ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler()) || ErrorUtils._globalHandler;
ErrorUtils.setGlobalHandler(({ stack }) => {
const { uid, email, displayName } = firebase.auth().currentUser;
firebase.crashlytics().setStringValue('Name', displayName);
firebase.crashlytics().setStringValue('Email', email);
firebase.crashlytics().setUserIdentifier(uid);
window.log('Sending error to Crashlytics:', stack);
firebase.crashlytics().log(stack);
defaultHandler.apply(this, arguments);
});
We are using something very similar to @oakis. But thought I could share for further reference. Note that you can store the sourcemap of your react native bundle when exporting it and then it will be possible to get the actual line and source file that is responsible for many fatals.
// crashlyticsSetup.js
import firebase from 'react-native-firebase'
/* global global */
const defaultHandler = global.ErrorUtils.getGlobalHandler()
const crashlytics = firebase.crashlytics()
global.ErrorUtils.setGlobalHandler((...args) => {
const error = args[0] || 'Unknown'
console.log('Crashlytics error sent', error);
if (error instanceof Error) {
crashlytics.setStringValue('stack', `${error.stack}`)
crashlytics.recordError(0, `RN Fatal: ${error.message}`)
} else {
// Have never gotten this log so far. Might not be necessary.
crashlytics.recordError(0, `RN Fatal: ${error}`)
}
defaultHandler.apply(this, args);
});
@simonbengtsson Awesome ^^!
@simonbengtsson where do you place/import crashlyticsSetup.js so that it runs properly in the App?
As early as possible. We have it before registering our react native components in our root index file.
Sorry for the late response. I actually forgot about this issue I created. By reinstalling from scratch and manually uploading dsym file when there is a release, I was able to make it work.
Is anybody tried connect error line number with sourcemap ?
After reading this issue, it's not clear to me if, in order to get automatic reporting for crashes happening in the JavaScript side of the app, we need to override the global handler or not. I assume we don't need it, as it's not documented in the integration guide, but, in our tests, we don't get the crashes we force in our JavaScript code reported as we do with the native ones.
Could anyone confirm us this? Thanks.
I have test it if without crashlytics.setStringValue('stack', `${error.stack}`)
you will get this error but it wont be clear where it happens
so adding this line gives info where it happened crashlytics.setStringValue('stack', `${error.stack}`)
in bundle
correct me if i am wrong
also currently i am looking how to connect it with sourcemaps
@ButuzGOL > also currently i am looking how to connect it with sourcemaps
Not currently possible I'm afraid. Something we've been looking into but it has some complications with the bundle size becoming huge.
This is what we have been able to get in our tests (note that adding the code posted by @simonbengtsson made no difference for us):
Has anyone experienced this? What are we doing wrong?
@Ehesp About sourcemaps, we generate them and store one locally for each build. Then we can see the exact component and line the error happened at by running it through something like this script:
const fs = require('fs')
const sourceMap = require('source-map');
(async () => {
// Replace with the logged stacktrace from crashlytics
const stacktrace = 't@/var/containers/Bundle/Application/A65EDD36-BFEA[...]';
const pairs = stacktrace
.match(/\d+:\d+/g)
.map(str =>
str
.split(':')
.map(str => parseInt(str))
)
const rawSourceMap = JSON.parse(fs.readFileSync(`./sourcemap.ios.js`))
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMap);
pairs.forEach(([line, column]) => {
const pos = consumer.originalPositionFor({line, column})
console.log(JSON.stringify(pos))
})
consumer.destroy();
})()
To detect crashes in JavaScript code happening inside a React component render method you can wrap all your project in ErrorBoundary and in componentDidCatch use firebase.crashlytics().recordError(). If you don't want to use ErrorBoundary, just add componentDidCatch to your main component.
componentDidCatch (error, errorInfo) { this.setState({ error: error, errorInfo: errorInfo }, () => { firebase.crashlytics().recordError(0, 'this.state.error' + 'JSON.stringify(this.state.errorInfo.componentStack)') }) }
@simonbengtsson can you pls explain, where do you import I add this crashlyticsSetup.js ?
@isurugajasinghe Read before commenting. :)
"As early as possible. We have it before registering our react native components in our root index file."
Hi @oakis please explain me, if your don't mind, I'm native iOS guy. sorry for my knowledge. where i need to place this crashlyticsSetup.js in my index.js? In below I mentioned my index.js
'''console.disableYellowBox = true;
import { Navigation } from "react-native-navigation"; import { registerScreens } from "./src/config/routes"; import { addListeners } from "./src/utilities/listeners"; import { Provider } from "react-redux"; import setup from "./src/store/setup"; import { iconsMap, iconsLoaded } from "./src/utilities/AppIcons";
Navigation.events().registerAppLaunchedListener(() => {
const store = setup();
registerScreens(store, Provider);
addListeners();
});'''
I do not use react-native-navigation (yet at least) but this is how my index.js looks like right now:
import { AppRegistry } from 'react-native';
import './src/setupLogging';
import './src/setupCrashlytics';
import App from './src/App';
AppRegistry.registerComponent('minahallplatser', () => App);
See I'm just injecting my crashlytics code directly into the entry file (index.js), even before the App component
@oakis So you are from Gothenburg and have made a Västtrafik app? 😄I've done the same but chose to experiment with flutter this time https://github.com/simonbengtsson/arctic-tern
Planning on release on iOS?
@simonbengtsson I've actually been on an interview with you guys when I was working at Raceone. We talked about it then. So to answer your questions, yes. Except for the iOS part because I don't want to add any ads and Apple Dev is expensive. :)
Haha the Gothenburg dev scene sure is small! Should have checked the profile pic! ^^
Issue
Usually we expect an app to crash in case of an error if the app is in release configuration and the crashlyitcs to trigger and record the bug. But if the error is in Javascript side I am seeing white screen instead of app crashing. This makes the app harder to debug and kind of renders crashlyitcs integration useless to a large extend.
I am developing two different apps using two different setup and I am seeing same issue on both projects.
I am not sure if the issue is with React Native or react-native-firebase or with my configuration. Any help would be great. Thank you.
Environment
Application Target Platform: Both.
Development Operating System: macOS High Sierra
Build Tools: xCode 9.3, Targets: iOS 10, Android SDK 26
React Native version: 0.51.0 & 0.55.3
RNFirebase Version: 3.3.1 & 4.0.6
Firebase Module: Crashlytics