diff --git a/.gitignore b/.gitignore index a5892e8..f60ea61 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ android/.DS_Store ios/.DS_Store -build/ \ No newline at end of file +build/ +/android/src/main/java/com/instabug/reactlibrary/wrappedAPIs diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java index ca8783f..35f39ea 100644 --- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java +++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java @@ -6,6 +6,9 @@ import android.net.Uri; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; + import com.instabug.library.Instabug; import com.instabug.library.internal.module.InstabugLocale; import com.instabug.library.invocation.InstabugInvocationEvent; @@ -430,6 +433,36 @@ public class RNInstabugReactnativeModule extends ReactContextBaseJavaModule { } } + /** + * Report a caught exception to Instabug dashboard + * + * @param throwable the exception to be reported + */ + @ReactMethod + public void reportJsException(ReadableArray stack, String message, String errorIdentifier) { + try { + int size = stack != null ? stack.size() : 0; + StackTraceElement[] stackTraceElements = new StackTraceElement[size]; + for (int i = 0; i < size; i++) { + ReadableMap frame = stack.getMap(i); + String methodName = frame.getString("methodName"); + String fileName = frame.getString("file"); + int lineNumber = frame.getInt("lineNumber"); + + stackTraceElements[i] = new StackTraceElement(fileName, methodName, fileName, lineNumber); + } + Throwable throwable = new Throwable(message); + throwable.setStackTrace(stackTraceElements); + if (errorIdentifier != null) + mInstabug.reportException(throwable); + else + mInstabug.reportException(throwable, errorIdentifier); + + } catch (Exception e) { + e.printStackTrace(); + } + } + private Locale getLocaleByKey(String instabugLocale) { String localeInLowerCase = instabugLocale.toLowerCase(); switch (localeInLowerCase) { diff --git a/index.js b/index.js index 17bd7a8..c3b7ae2 100644 --- a/index.js +++ b/index.js @@ -5,8 +5,8 @@ */ import {NativeModules, NativeAppEventEmitter, Platform} from 'react-native'; - let {Instabug} = NativeModules; +import instabugParser from './utils/instabugParser.js'; /** * Instabug @@ -464,6 +464,18 @@ module.exports = { Instabug.isInstabugNotification(dict, isInstabugNotificationCallback); }, + reportJsException: function (error, errorIdentifier) { + if (!error || !error instanceof Error) + throw new Error("You should pass an error object"); + + let jsStackTrace = instabugParser(error); + if (!errorIdentifier) + Instabug.reportJsException(jsStackTrace, error.message, null); + else if (errorIdentifier) { + Instabug.reportJsException(jsStackTrace, error.message, errorIdentifier); + } + }, + /** * The event used to invoke the feedback form * @readonly diff --git a/package.json b/package.json index 03e05c8..ad01992 100644 --- a/package.json +++ b/package.json @@ -28,5 +28,8 @@ "android": { "packageInstance": "new RNInstabugReactnativePackage(\"YOUR_ANDROID_APPLICATION_TOKEN\",MainApplication.this,\"button\")" } + }, + "dependencies": { + "stacktrace-parser": "0.1.3" } } diff --git a/utils/instabugParser.js b/utils/instabugParser.js new file mode 100644 index 0000000..44ffd13 --- /dev/null +++ b/utils/instabugParser.js @@ -0,0 +1,13 @@ +'use strict'; + +var stacktraceParser = require('stacktrace-parser'); + +function parseErrorStack(error) { + if (!error || !error.stack) { + return []; + } + return Array.isArray(error.stack) ? error.stack : + stacktraceParser.parse(error.stack); +} + +module.exports = parseErrorStack; \ No newline at end of file