Skip to content

Commit b07fe03

Browse files
v3.3.0
2 parents 188ea20 + 1f3ed18 commit b07fe03

9 files changed

Lines changed: 252 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 3.3.0 (2018-09-26)
4+
5+
* Capture trace of error reporting thread and identify with boolean flag
6+
[#87](https://github.com/bugsnag/bugsnag-java/pull/87)
7+
38
## 3.2.1 (2018-08-21)
49

510
* Add null check when disconnecting HttpUrlConnection

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version=3.2.1
1+
version=3.3.0
22
group=com.bugsnag
33

44
# Default properties

src/main/java/com/bugsnag/Bugsnag.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ public boolean notify(Throwable throwable, Severity severity, Callback callback)
354354

355355
HandledState handledState = HandledState.newInstance(
356356
HandledState.SeverityReasonType.REASON_USER_SPECIFIED, severity);
357-
Report report = new Report(config, throwable, handledState);
357+
Report report = new Report(config, throwable, handledState, Thread.currentThread());
358358
return notify(report, callback);
359359
}
360360

@@ -372,8 +372,8 @@ public boolean notify(Report report) {
372372
}
373373

374374

375-
boolean notify(Throwable throwable, HandledState handledState) {
376-
Report report = new Report(config, throwable, handledState);
375+
boolean notify(Throwable throwable, HandledState handledState, Thread currentThread) {
376+
Report report = new Report(config, throwable, handledState, currentThread);
377377
return notify(report, null);
378378
}
379379

src/main/java/com/bugsnag/ExceptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void uncaughtException(Thread thread, Throwable throwable) {
5555

5656
HandledState handledState = HandledState.newInstance(
5757
HandledState.SeverityReasonType.REASON_UNHANDLED_EXCEPTION, Severity.ERROR);
58-
bugsnag.notify(throwable, handledState);
58+
bugsnag.notify(throwable, handledState, thread);
5959
}
6060

6161
// Pass exception on to original exception handler

src/main/java/com/bugsnag/Notifier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

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

1010
@Expose

src/main/java/com/bugsnag/Report.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class Report {
2424
private Diagnostics diagnostics;
2525
private boolean shouldCancel = false;
2626
private Session session;
27+
private final List<ThreadState> threadStates;
2728

2829
/**
2930
* Create a report for the error.
@@ -33,15 +34,24 @@ public class Report {
3334
*/
3435
protected Report(Configuration config, Throwable throwable) {
3536
this(config, throwable, HandledState.newInstance(
36-
HandledState.SeverityReasonType.REASON_HANDLED_EXCEPTION));
37+
HandledState.SeverityReasonType.REASON_HANDLED_EXCEPTION), Thread.currentThread());
3738
}
3839

39-
Report(Configuration config, Throwable throwable, HandledState handledState) {
40+
Report(Configuration config, Throwable throwable,
41+
HandledState handledState, Thread currentThread) {
4042
this.config = config;
4143
this.exception = new Exception(config, throwable);
4244
this.handledState = handledState;
4345
this.severity = handledState.getOriginalSeverity();
4446
diagnostics = new Diagnostics(this.config);
47+
48+
if (config.sendThreads) {
49+
Throwable exc = handledState.isUnhandled() ? throwable : null;
50+
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
51+
threadStates = ThreadState.getLiveThreads(config, currentThread, allStackTraces, exc);
52+
} else {
53+
threadStates = null;
54+
}
4555
}
4656

4757
@Expose
@@ -80,7 +90,7 @@ SeverityReason getSeverityReason() {
8090

8191
@Expose
8292
protected List<ThreadState> getThreads() {
83-
return config.sendThreads ? ThreadState.getLiveThreads(config) : null;
93+
return threadStates;
8494
}
8595

8696
@Expose

src/main/java/com/bugsnag/ThreadState.java

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,33 @@
99
import java.util.Map;
1010

1111
class ThreadState {
12-
private Configuration config;
13-
private Thread thread;
14-
private StackTraceElement[] stackTraceElements;
12+
13+
private final Configuration config;
14+
private final Thread thread;
15+
private final StackTraceElement[] stackTraceElements;
16+
private Boolean errorReportingThread;
1517

1618
ThreadState(Configuration config, Thread thread, StackTraceElement[] stackTraceElements) {
1719
this.config = config;
1820
this.thread = thread;
1921
this.stackTraceElements = stackTraceElements;
2022
}
2123

22-
static List<ThreadState> getLiveThreads(Configuration config) {
24+
static List<ThreadState> getLiveThreads(Configuration config,
25+
Thread currentThread,
26+
Map<Thread, StackTraceElement[]> liveThreads,
27+
Throwable exc) {
2328
// Get current thread id (the crashing thread) and stacktraces for all live threads
24-
long crashingThreadId = Thread.currentThread().getId();
25-
Map<Thread, StackTraceElement[]> liveThreads = Thread.getAllStackTraces();
29+
long crashingThreadId = currentThread.getId();
30+
31+
// if thread is not present for any reason, add the current stacktrace to the map
32+
// so that the errorReportingThread will always be reported
33+
if (!liveThreads.containsKey(currentThread)) {
34+
liveThreads.put(currentThread, currentThread.getStackTrace());
35+
}
36+
if (exc != null) { // unhandled errors use the exception trace
37+
liveThreads.put(currentThread, exc.getStackTrace());
38+
}
2639

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

3548
List<ThreadState> threads = new ArrayList<ThreadState>();
36-
for (int i = 0; i < keys.length; i++) {
37-
Thread thread = (Thread) keys[i];
38-
39-
// Don't show the current stacktrace here. It'll point at this method
40-
// rather than at the point they crashed.
41-
if (thread.getId() == crashingThreadId) {
42-
continue;
43-
}
4449

50+
for (Object key : keys) {
51+
Thread thread = (Thread) key;
4552
ThreadState threadState = new ThreadState(config, thread, liveThreads.get(thread));
4653
threads.add(threadState);
47-
}
4854

55+
if (threadState.getId() == crashingThreadId) {
56+
threadState.setErrorReportingThread(true);
57+
}
58+
}
4959
return threads;
5060
}
5161

@@ -63,4 +73,13 @@ public String getName() {
6373
public List<Stackframe> getStacktrace() {
6474
return Stackframe.getStacktrace(config, stackTraceElements);
6575
}
76+
77+
@JsonProperty("errorReportingThread")
78+
public Boolean isErrorReportingThread() {
79+
return errorReportingThread;
80+
}
81+
82+
public void setErrorReportingThread(Boolean errorReportingThread) {
83+
this.errorReportingThread = errorReportingThread;
84+
}
6685
}

src/test/java/com/bugsnag/HandledStatePayloadTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void testCallbackSpecified() throws Exception {
107107
}
108108

109109
private Report reportFromHandledState(HandledState handledState) {
110-
return new Report(config, new RuntimeException(), handledState);
110+
return new Report(config, new RuntimeException(), handledState, Thread.currentThread());
111111
}
112112

113113
private JsonNode getJsonPayloadFromReport(Report report) throws IOException {

0 commit comments

Comments
 (0)