Last active
July 17, 2023 10:15
-
-
Save tianjianchn/af8bdbdf4c19135f505a59d0d637745b to your computer and use it in GitHub Desktop.
Error report util with fabric/crashlytics in react-native
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global __DEV__*/ | |
import StackTrace from 'stacktrace-js'; | |
const Fabric = require('react-native-fabric'); | |
const { Crashlytics } = Fabric; | |
//call this to start capturing any no-handled errors | |
exports.init = function(captrueOnDebugMode){ | |
if (__DEV__ && !captrueOnDebugMode) { | |
return; | |
} | |
const originalHandler = global.ErrorUtils.getGlobalHandler(); | |
function errorHandler(e) { | |
exports.issue(e) | |
if (originalHandler) { | |
originalHandler(e); | |
} | |
} | |
global.ErrorUtils.setGlobalHandler(errorHandler); | |
} | |
//user: {id: ,name: ,email: } | |
exports.setUser = function(user){ | |
const {id, name, email} = {id: 'anony', name: 'anony', email: 'anony', ...user}; | |
Crashlytics.setUserIdentifier(id+''); | |
Crashlytics.setUserName(name+''); | |
Crashlytics.setUserEmail(email+''); | |
} | |
exports.setAttrs = function(obj){ | |
for(let kk in obj){ | |
exports.setAttr(kk, obj[kk]); | |
} | |
} | |
exports.setAttr = function(key, value){ | |
if(!key) return; | |
if(typeof key !== 'string') key = key + ''; | |
let type = typeof value; | |
if(type==='boolean') Crashlytics.setBool(key, value); | |
else if(type==='number') Crashlytics.setNumber(key, value); | |
else if(type==='string') Crashlytics.setString(key, value); | |
else Crashlytics.setString(key, JSON.stringify(value)); | |
} | |
//things that will be in issue's session logs | |
exports.log = function(value){ | |
if(!value) return; | |
if(value instanceof Error){ | |
value = value.stack || value.message; | |
} | |
if(typeof value !== 'string') value += ''; | |
return Crashlytics.log(value); | |
} | |
//create a new issue. fileName will be the the error message as the `index.bundle.js` is meaningless | |
exports.issue = function(e){ | |
return StackTrace.fromError(e, {offline: true}).then((stack)=>{ | |
return stack.map(row=>{ | |
let {source, lineNumber} = row; | |
if(!lineNumber){ | |
lineNumber = parseInt(source.split(':').slice(-2, -1)) || 0 | |
} | |
return {fileName: e.message, lineNumber, functionName: source} | |
}) | |
}) | |
.then((stack)=>{ | |
Crashlytics.recordCustomExceptionName(e.message, e.message, stack) | |
}) | |
} | |
exports.crash = function(){ | |
return Crashlytics.crash(); | |
} | |
In my case, cannot execute recordCustomExceptionName
.
So I changed code like this. This work well in my case, but I don't know this is good idea.
const issue = (e, isFatal, originalHandler) => {
StackTrace.fromError(e, { offline: true }).then((stack) => (
stack.map((row) => {
let { lineNumber } = row;
const { source } = row;
if (!lineNumber) {
lineNumber = parseInt(source.split(':').slice(-2, -1), 10) || 0;
} return { fileName: e.message, lineNumber, functionName: source };
})
)).then((stack) => {
Crashlytics.recordCustomExceptionName(e.message, e.message, stack);
originalHandler(e, isFatal, originalHandler);
});
};
const init() => {
if (__DEV__) {
return;
}
const originalHandler = global.ErrorUtils.getGlobalHandler();
function errorHandler(e, isFatal) {
if (originalHandler) {
issue(e, isFatal, originalHandler);
// originalHandler(e, isFatal);
}
issue(e);
}
global.ErrorUtils.setGlobalHandler(errorHandler);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice gist!
next step: bundle or link the sourcemap \o/