Skip to content

Instantly share code, notes, and snippets.

@levic92
Forked from jrichardlai/ErrorManager.java
Created May 18, 2016 16:29
Show Gist options
  • Save levic92/702f5d1e7452bea744d277b88e9b2602 to your computer and use it in GitHub Desktop.
Save levic92/702f5d1e7452bea744d277b88e9b2602 to your computer and use it in GitHub Desktop.
ErrorManager for React Native

To use the ErrorManager.

Require the configureErrorManager.js and to set your user:

ErrorManager.setIdentifier({
  id: account.data.id,
  email: account.data.email,
  full_name: account.data.full_name,
});
const ErrorUtils = require('ErrorUtils');
import { NativeModules } from 'react-native';
import parseErrorStack from 'parseErrorStack';
import _ from 'underscore';
const ErrorManager = NativeModules.ErrorManager;
let exceptionID = 0;
if (ErrorManager && ErrorUtils._globalHandler) {
const previousGlobalHandler = ErrorUtils._globalHandler;
const wrapGlobalHandler = (error, isFatal) => {
let currentExceptionID = ++exceptionID;
const stack = parseErrorStack(error);
const timeoutPromise = new Promise((resolve) => {
global.setTimeout(() => {
resolve();
}, 1000);
});
const reportExceptionPromise = new Promise((resolve) => {
ErrorManager.reportException(error.message, stack, currentExceptionID, {}, resolve);
});
return Promise.race([reportExceptionPromise, timeoutPromise]).then(() => {
previousGlobalHandler(error, isFatal);
});
};
ErrorUtils.setGlobalHandler(wrapGlobalHandler);
}
global.notifyError = (error, errorData) => {
if (error instanceof Error) {
console.log('notifyError', error, errorData);
let currentExceptionID = ++exceptionID;
const stack = parseErrorStack(error);
ErrorManager.reportException(
error.message,
stack,
currentExceptionID,
// Make all values string
_.mapObject(errorData || {}, (val, key) => (val || 'NULL').toString()),
() => {}
);
} else {
console.warn('attempt to call notifyError without an Error', error, errorData);
}
}
import com.bugsnag.android.Bugsnag;
import com.bugsnag.android.MetaData;
import com.bugsnag.android.Severity;
import com.facebook.react.bridge.*;
import java.io.File;
import java.util.HashMap;
public class ErrorManager extends ReactContextBaseJavaModule {
public ErrorManager(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "ErrorManager";
}
@ReactMethod
public void setIdentifier(ReadableMap params) {
if (!BuildConfig.NOTIFY_ERRORS) { return; }
Bugsnag.setUser(params.getString("id"), params.getString("email"), params.getString("full_name"));
}
@ReactMethod
public void reportException(String title, ReadableArray details, int exceptionId, ReadableMap errorData, Callback callback) {
if (!BuildConfig.NOTIFY_ERRORS) {
callback.invoke();
return;
}
Error error = new Error(title);
error.setStackTrace(stackTraceToStackTraceElement(details));
MetaData metaData = new MetaData();
metaData.addToTab("Custom", "Stacktrace", stackTraceToString(details));
ReadableMapKeySetIterator iterator = errorData.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
metaData.addToTab("Custom", key, errorData.getString(key));
}
Bugsnag.notify(title, title, stackTraceToStackTraceElement(details), Severity.ERROR, metaData);
callback.invoke();
}
private StackTraceElement[] stackTraceToStackTraceElement(ReadableArray stack) {
StackTraceElement[] stackTraceElements = new StackTraceElement[stack.size()];
for (int i = 0; i < stack.size(); i++) {
ReadableMap frame = stack.getMap(i);
stackTraceElements[i] = new StackTraceElement(
"ReactJS",
frame.getString("methodName"),
new File(frame.getString("file")).getName(),
frame.getInt("lineNumber")
);
}
return stackTraceElements;
}
private String stackTraceToString(ReadableArray stack) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < stack.size(); i++) {
ReadableMap frame = stack.getMap(i);
stringBuilder.append(frame.getString("methodName"));
stringBuilder.append("\n ");
stringBuilder.append(new File(frame.getString("file")).getName());
stringBuilder.append(":");
stringBuilder.append(frame.getInt("lineNumber"));
if (frame.hasKey("column") && !frame.isNull("column")) {
stringBuilder
.append(":")
.append(frame.getInt("column"));
}
stringBuilder.append("\n");
}
return stringBuilder.toString();
}
}
//
// TestRunnerManager.m
// Tasker
//
// Created by Jean-Richard Lai on 8/9/15.
// Copyright (c) 2015 TaskRabbit. All rights reserved.
//
#import "Bugsnag.h"
#import "ErrorManager.h"
@implementation ErrorManager
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(setIdentifier:(NSDictionary*)attributes)
{
#ifdef DEBUG
return;
#endif
[[Bugsnag configuration] setUser:attributes[@"id"] withName:attributes[@"email"] andEmail:attributes[@"full_name"]];
}
RCT_EXPORT_METHOD(reportException:(NSString *)message
stack:(NSArray<NSDictionary *> *)stack
exceptionId:(nonnull NSNumber *)exceptionId
errorData:(NSDictionary *)errorData
callback:(RCTResponseSenderBlock)callback)
{
#ifdef DEBUG
callback(@[]);
return;
#endif
NSMutableArray *frameArray = [[NSMutableArray alloc] init];
NSMutableArray *stringFrameArray = [[NSMutableArray alloc] init];
for (NSDictionary *stackFrame in stack) {
CLSStackFrame *newStackFrame = [[CLSStackFrame alloc] init];
newStackFrame.fileName = [NSString stringWithFormat:@"%@ @ %zd:%zd",
[stackFrame[@"file"] lastPathComponent],
[stackFrame[@"lineNumber"] integerValue],
[stackFrame[@"column"] integerValue]];
newStackFrame.symbol = stackFrame[@"methodName"];
newStackFrame.library = @"React Native";
newStackFrame.lineNumber = (uint32_t) [stackFrame[@"lineNumber"] integerValue];
newStackFrame.offset = [stackFrame[@"lineNumber"] integerValue];
newStackFrame.address = [stackFrame[@"lineNumber"] integerValue];
[frameArray addObject:newStackFrame];
[stringFrameArray addObject:[NSString stringWithFormat:@"%@ %@", newStackFrame.fileName, newStackFrame.symbol]];
}
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString([stringFrameArray componentsJoinedByString:@"\n"], nil),
};
NSError *error = [NSError errorWithDomain:message code:-88 userInfo:userInfo];
NSMutableDictionary *allErrorData = [errorData mutableCopy];
[allErrorData addEntriesFromDictionary:@{@"Stacktrace": [stringFrameArray componentsJoinedByString:@"\n"]}];
[Bugsnag notify:[NSException exceptionWithName:message reason:[stringFrameArray componentsJoinedByString:@"\n"] userInfo:userInfo]
withData:allErrorData atSeverity:BugsnagSeverityError];
callback(@[]);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment