Skip to content

Commit

Permalink
Added ability to log JS stacktraces. #57 (Picked from https://github.…
Browse files Browse the repository at this point in the history
  • Loading branch information
sagrawal31 committed Jul 26, 2019
1 parent a7ae1dd commit e2e32fe
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 14 deletions.
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<source-file src="src/android/FirebasePluginMessagingService.java" target-dir="src/org/apache/cordova/firebase" />
<source-file src="src/android/FirebasePluginMessageReceiver.java" target-dir="src/org/apache/cordova/firebase" />
<source-file src="src/android/FirebasePluginMessageReceiverManager.java" target-dir="src/org/apache/cordova/firebase" />

<source-file src="src/android/JavaScriptException.java" target-dir="src/org/apache/cordova/firebase"/>

<source-file src="src/android/colors.xml" target-dir="res/values" />
<preference name="ANDROID_ICON_ACCENT" default="#FF00FFFF" />
Expand Down
29 changes: 26 additions & 3 deletions src/android/FirebasePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
this.logEvent(callbackContext, args.getString(0), args.getJSONObject(1));
return true;
} else if (action.equals("logError")) {
this.logError(callbackContext, args.getString(0));
this.logError(callbackContext, args);
return true;
}else if(action.equals("setCrashlyticsUserId")){
this.setCrashlyticsUserId(callbackContext, args.getString(0));
Expand Down Expand Up @@ -509,14 +509,37 @@ public void run() {
});
}

private void logError(final CallbackContext callbackContext, final String message) throws JSONException {
private void logError(final CallbackContext callbackContext, final JSONArray args) throws JSONException {
String message = args.getString(0);

cordova.getThreadPool().execute(new Runnable() {
public void run() {
try {
Crashlytics.logException(new Exception(message));
// We can optionally be passed a stack trace generated by stacktrace.js.
if (args.length() == 2) {
JSONArray stackTrace = args.getJSONArray(1);
StackTraceElement[] trace = new StackTraceElement[stackTrace.length()];
for(int i = 0; i < stackTrace.length(); i++) {
JSONObject elem = stackTrace.getJSONObject(i);
trace[i] = new StackTraceElement(
"undefined",
elem.optString("functionName", "undefined"),
elem.optString("fileName", "undefined"),
elem.optInt("lineNumber", -1)
);
}

Exception e = new JavaScriptException(message);
e.setStackTrace(trace);
Crashlytics.logException(e);
} else {
Crashlytics.logException(new JavaScriptException(message));
}

Log.e(TAG, message);
callbackContext.success(1);
} catch (Exception e) {
Crashlytics.log("logError errored. Orig error: " + message);
Crashlytics.log(1, TAG, e.getMessage());
e.printStackTrace();
callbackContext.error(e.getMessage());
Expand Down
45 changes: 45 additions & 0 deletions src/android/JavaScriptException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.apache.cordova.firebase;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
* Exception class to log Javascript based exceptions with stacktrace.
*
* Picked from https://github.com/wizpanda/cordova-plugin-firebase-lib/pull/8/files
*
* @author https://github.com/sagrawal31/
*/
public class JavaScriptException extends Exception {

public JavaScriptException(String message) {
super(message);
}

public JavaScriptException(String message, JSONArray stackTrace) throws JSONException {
super(message);
this.handleStacktrace(stackTrace);
}

private void handleStacktrace(JSONArray stackTrace) throws JSONException {
if (stackTrace == null) {
return;
}

StackTraceElement[] trace = new StackTraceElement[stackTrace.length()];

for (int i = 0; i < stackTrace.length(); i++) {
JSONObject elem = stackTrace.getJSONObject(i);

trace[i] = new StackTraceElement(
"undefined",
elem.optString("functionName", "undefined"),
elem.optString("fileName", "undefined"),
elem.optInt("lineNumber", -1)
);
}

this.setStackTrace(trace);
}
}
30 changes: 22 additions & 8 deletions src/ios/FirebasePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,29 @@ - (void)logEvent:(CDVInvokedUrlCommand *)command {

- (void)logError:(CDVInvokedUrlCommand *)command {
[self.commandDelegate runInBackground:^{
NSString* message = [command argumentAtIndex:0 withDefault:@""];
if(message)
{
NSDictionary* detail = @{@"message":message};
NSError* error = [NSError errorWithDomain:@"Logged error" code:0 userInfo:detail];
[CrashlyticsKit recordError:error];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
NSString* errorMessage = [command.arguments objectAtIndex:0];
NSMutableDictionary* userInfo = [[NSMutableDictionary alloc] init];
CDVCommandStatus status = CDVCommandStatus_OK;

@try {
// We can optionally be passed a stack trace from stackTrace.js which we'll put in userInfo.
if ([command.arguments count] > 1) {
NSArray *stack = [command.arguments objectAtIndex:1];
int lineNum = 1;
for (NSDictionary *entry in stack) {
NSString *key = [NSString stringWithFormat:@"Stack_line_%02d", lineNum++];
userInfo[key] = entry[@"source"];
}
}
} @catch (NSException *exception) {
CLSNSLog(@"Exception in logError: %@, original error: %@", exception.description, errorMessage);
status = CDVCommandStatus_ERROR;
}

NSError *error = [NSError errorWithDomain:errorMessage code:0 userInfo:userInfo];
[CrashlyticsKit recordError:error];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:status];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
}

Expand Down
14 changes: 12 additions & 2 deletions www/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,18 @@ exports.sendCrash = function (success, error) {
exec(success, error, "FirebasePlugin", "sendCrash", []);
};

exports.logError = function (message, success, error) {
exec(success, error, "FirebasePlugin", "logError", [message]);
exports.logError = function (message, stackTrace, success, error) {
var args = [message];
// "stackTrace" is an optional arg that's an array of objects.
if (stackTrace) {
if (typeof stackTrace === 'function') {
error = success;
success = stackTrace;
} else {
args.push(stackTrace);
}
}
exec(success, error, "FirebasePlugin", "logError", args);
};

exports.setCrashlyticsUserId = function (userId, success, error) {
Expand Down

0 comments on commit e2e32fe

Please sign in to comment.