Skip to content

Commit

Permalink
v3.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalwrench authored Sep 26, 2018
2 parents 188ea20 + 1f3ed18 commit b07fe03
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 32 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 3.3.0 (2018-09-26)

* Capture trace of error reporting thread and identify with boolean flag
[#87](https://github.com/bugsnag/bugsnag-java/pull/87)

## 3.2.1 (2018-08-21)

* Add null check when disconnecting HttpUrlConnection
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=3.2.1
version=3.3.0
group=com.bugsnag

# Default properties
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/bugsnag/Bugsnag.java
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ public boolean notify(Throwable throwable, Severity severity, Callback callback)

HandledState handledState = HandledState.newInstance(
HandledState.SeverityReasonType.REASON_USER_SPECIFIED, severity);
Report report = new Report(config, throwable, handledState);
Report report = new Report(config, throwable, handledState, Thread.currentThread());
return notify(report, callback);
}

Expand All @@ -372,8 +372,8 @@ public boolean notify(Report report) {
}


boolean notify(Throwable throwable, HandledState handledState) {
Report report = new Report(config, throwable, handledState);
boolean notify(Throwable throwable, HandledState handledState, Thread currentThread) {
Report report = new Report(config, throwable, handledState, currentThread);
return notify(report, null);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/bugsnag/ExceptionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void uncaughtException(Thread thread, Throwable throwable) {

HandledState handledState = HandledState.newInstance(
HandledState.SeverityReasonType.REASON_UNHANDLED_EXCEPTION, Severity.ERROR);
bugsnag.notify(throwable, handledState);
bugsnag.notify(throwable, handledState, thread);
}

// Pass exception on to original exception handler
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/bugsnag/Notifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class Notifier {
private static final String NOTIFIER_NAME = "Bugsnag Java";
private static final String NOTIFIER_VERSION = "3.2.1";
private static final String NOTIFIER_VERSION = "3.3.0";
private static final String NOTIFIER_URL = "https://github.com/bugsnag/bugsnag-java";

@Expose
Expand Down
16 changes: 13 additions & 3 deletions src/main/java/com/bugsnag/Report.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Report {
private Diagnostics diagnostics;
private boolean shouldCancel = false;
private Session session;
private final List<ThreadState> threadStates;

/**
* Create a report for the error.
Expand All @@ -33,15 +34,24 @@ public class Report {
*/
protected Report(Configuration config, Throwable throwable) {
this(config, throwable, HandledState.newInstance(
HandledState.SeverityReasonType.REASON_HANDLED_EXCEPTION));
HandledState.SeverityReasonType.REASON_HANDLED_EXCEPTION), Thread.currentThread());
}

Report(Configuration config, Throwable throwable, HandledState handledState) {
Report(Configuration config, Throwable throwable,
HandledState handledState, Thread currentThread) {
this.config = config;
this.exception = new Exception(config, throwable);
this.handledState = handledState;
this.severity = handledState.getOriginalSeverity();
diagnostics = new Diagnostics(this.config);

if (config.sendThreads) {
Throwable exc = handledState.isUnhandled() ? throwable : null;
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
threadStates = ThreadState.getLiveThreads(config, currentThread, allStackTraces, exc);
} else {
threadStates = null;
}
}

@Expose
Expand Down Expand Up @@ -80,7 +90,7 @@ SeverityReason getSeverityReason() {

@Expose
protected List<ThreadState> getThreads() {
return config.sendThreads ? ThreadState.getLiveThreads(config) : null;
return threadStates;
}

@Expose
Expand Down
49 changes: 34 additions & 15 deletions src/main/java/com/bugsnag/ThreadState.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,33 @@
import java.util.Map;

class ThreadState {
private Configuration config;
private Thread thread;
private StackTraceElement[] stackTraceElements;

private final Configuration config;
private final Thread thread;
private final StackTraceElement[] stackTraceElements;
private Boolean errorReportingThread;

ThreadState(Configuration config, Thread thread, StackTraceElement[] stackTraceElements) {
this.config = config;
this.thread = thread;
this.stackTraceElements = stackTraceElements;
}

static List<ThreadState> getLiveThreads(Configuration config) {
static List<ThreadState> getLiveThreads(Configuration config,
Thread currentThread,
Map<Thread, StackTraceElement[]> liveThreads,
Throwable exc) {
// Get current thread id (the crashing thread) and stacktraces for all live threads
long crashingThreadId = Thread.currentThread().getId();
Map<Thread, StackTraceElement[]> liveThreads = Thread.getAllStackTraces();
long crashingThreadId = currentThread.getId();

// if thread is not present for any reason, add the current stacktrace to the map
// so that the errorReportingThread will always be reported
if (!liveThreads.containsKey(currentThread)) {
liveThreads.put(currentThread, currentThread.getStackTrace());
}
if (exc != null) { // unhandled errors use the exception trace
liveThreads.put(currentThread, exc.getStackTrace());
}

// Sort threads by thread-id
Object[] keys = liveThreads.keySet().toArray();
Expand All @@ -33,19 +46,16 @@ public int compare(Object first, Object second) {
});

List<ThreadState> threads = new ArrayList<ThreadState>();
for (int i = 0; i < keys.length; i++) {
Thread thread = (Thread) keys[i];

// Don't show the current stacktrace here. It'll point at this method
// rather than at the point they crashed.
if (thread.getId() == crashingThreadId) {
continue;
}

for (Object key : keys) {
Thread thread = (Thread) key;
ThreadState threadState = new ThreadState(config, thread, liveThreads.get(thread));
threads.add(threadState);
}

if (threadState.getId() == crashingThreadId) {
threadState.setErrorReportingThread(true);
}
}
return threads;
}

Expand All @@ -63,4 +73,13 @@ public String getName() {
public List<Stackframe> getStacktrace() {
return Stackframe.getStacktrace(config, stackTraceElements);
}

@JsonProperty("errorReportingThread")
public Boolean isErrorReportingThread() {
return errorReportingThread;
}

public void setErrorReportingThread(Boolean errorReportingThread) {
this.errorReportingThread = errorReportingThread;
}
}
2 changes: 1 addition & 1 deletion src/test/java/com/bugsnag/HandledStatePayloadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void testCallbackSpecified() throws Exception {
}

private Report reportFromHandledState(HandledState handledState) {
return new Report(config, new RuntimeException(), handledState);
return new Report(config, new RuntimeException(), handledState, Thread.currentThread());
}

private JsonNode getJsonPayloadFromReport(Report report) throws IOException {
Expand Down
Loading

0 comments on commit b07fe03

Please sign in to comment.