react-native-site24x7-rn
Version:
Monitor react native mobile applications with site24x7 Mobile RUM
124 lines (116 loc) • 5.33 kB
JavaScript
import S24Utils from './site24x7Utils';
const { NativeModules } = require('react-native');//No I18N
const MAX_STACK_TRACE_LEN = 20;
const EMPTY_STACK_TRACE="";
const ANONYMOUS="?";
const { Site24x7Rn } = NativeModules;
class site24x7RnErrorTracker{
constructor(enableErrorTracking,enableConsoleErrors,enableUnhandledRejections){
this.enableErrorTracking = enableErrorTracking;
this.enableConsoleErrors = enableConsoleErrors;
this.enableUnhandledRejections = enableUnhandledRejections;
if(this.enableErrorTracking){
//making a copy of previous old error handler.
const oldJsExceptionHandler = ErrorUtils.getGlobalHandler();
//intercepting global error handler before returning to the original error handler.
ErrorUtils.setGlobalHandler(async (error, isFatal) => {
await this.parseError(error, isFatal);
oldJsExceptionHandler && oldJsExceptionHandler(error, isFatal);
});
}
//need to get file exclusion for code check from integ team
// if(this.enableConsoleErrors){
// const consoleError = console.error;
// console.error = (...args) => {
// ErrorUtils.reportError(...args);
// consoleError(...args);
// };
// }
// https://github.com/iyegoroff/react-native-promise-rejection-utils/blob/master/index.js
if(this.enableUnhandledRejections){
const { polyfillGlobal } = require('react-native/Libraries/Utilities/PolyfillFunctions');//No I18N
const Promise = require('promise/setimmediate/es6-extensions');//No I18N
const tracking = require('promise/setimmediate/rejection-tracking');//No I18N
// Set up rejection handler to divert rejections to crash reporter
polyfillGlobal('Promise', () => {//No I18N
tracking.enable({
allRejections: true,
onUnhandled: site24x7RnErrorTracker.parseUnhandledRejection.bind(this)
});
return Promise;
});
}
}
//Not used Currently
static getErrorStackTrace(error) {
let stack = EMPTY_STACK_TRACE;
if ('componentStack' in error) {
stack = String(error.componentStack);
} else if ('sourceURL' in error && 'line' in error && 'column' in error) {
stack = `at ${error.sourceURL}:${error.line}:${error.column}`;
}
return stack;
}
static parseUnhandledRejection(id, error) {
if (__DEV__) {
const warning =`site24x7mobileRUM Possible Unhandled Promise Rejection (id: ${id}):\n` +`${error}\n`;
//console.warn(warning)
}
this.parseError(error, false);
}
async parseError(error, isFatal) {
this.parseErrorWithHandledExceptionCheck(error, isFatal, false);
}
async parseErrorWithHandledExceptionCheck(error, isFatal, handledException) {
if (S24Utils.isEmpty(error) || S24Utils.isEmpty(error.stack)) {
return;
}
const parseErrorStack = require('react-native/Libraries/Core/Devtools/parseErrorStack');//No I18N
let stack;
try {
stack = parseErrorStack(error);
}
catch (e) {// parseErrorStack in ReactNative 0.64 requires a string
stack = parseErrorStack(error.stack);
}
const errorData = await this.site24x7RumError(stack,error);
Site24x7Rn.addJsError(errorData.msg,errorData.type,errorData.file,errorData.function,errorData.stack,JSON.stringify(errorData.breadcrumbs),S24Utils.getCurrentScreen(),Date.now().toString(), handledException);
S24Utils.clearBreadCrumbs();//No I18N
}
async site24x7RumError(stack,error){
stack = S24Utils.cleanFilePath(stack);
error = S24Utils.isEmpty(error) ? {"name":ANONYMOUS,"message":ANONYMOUS} : error;//No I18N
const errorDetails = {
"breadcrumbs" : S24Utils.getBreadCrumbs(),//No I18N
"type" : error.name,//No I18N
"msg" : error.message,//No I18N
"stack" : await this.computeStackTrace(stack)//No I18N
};
if(stack.length>0){
errorDetails.function = stack[0].methodName || ANONYMOUS;
errorDetails.file = stack[0].file;
}else{
errorDetails.function = ANONYMOUS;
errorDetails.file = ANONYMOUS;
}
return errorDetails;
}
async computeStackTrace(stack){
const convertToCrashReportingStackFrame = ({ file, methodName, lineNumber, column }) => ({
fname: file,
func: methodName || ANONYMOUS,
lineno: lineNumber,
colno: column
});
stack = Array.isArray(stack) ? stack.map(convertToCrashReportingStackFrame) : [convertToCrashReportingStackFrame(stack)];
if(Array.isArray(stack)){
//removing native code errors from stack trace
stack = stack.filter((item)=>{
return item.fname.indexOf("native code") == -1;
})
stack=stack.slice(Math.max(stack.length - MAX_STACK_TRACE_LEN, 0));
}
return JSON.stringify(stack);
}
}
module.exports = site24x7RnErrorTracker;