Skip to content

Commit ed9d6d1

Browse files
author
Mikel Pascual
committed
Initial implementation (hardcoded base package, unordered causes)
1 parent ebd9ffe commit ed9d6d1

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright 2017 akaita
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.akaita.java.rxjava2debug;
18+
19+
import hu.akarnokd.rxjava2.debug.RxJavaAssemblyException;
20+
import hu.akarnokd.rxjava2.debug.RxJavaAssemblyTracking;
21+
import io.reactivex.annotations.NonNull;
22+
import io.reactivex.annotations.Nullable;
23+
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import java.util.regex.Matcher;
27+
import java.util.regex.Pattern;
28+
29+
public class RxJava2Debug {
30+
//Example: "at com.akaita.fgas.MainActivity.onCreate(MainActivity.java:210)"
31+
private static final Pattern STACK_TRACE_ELEMENT_PATTERN = Pattern.compile("^at (.*)\\.(.*)\\((.*):([0-9]+)\\)$");
32+
private static final String NEW_LINE_REGEX = "\\n\\r|\\r\\n|\\n|\\r";
33+
34+
private static String BASE_APP_PACKAGE_NAME = "com.akaita.fgas";
35+
36+
/**
37+
* Enable a system to collect information about RxJava's execution to provide a more meaningful StackTrace in case of crash<br/>
38+
* <b>Beware:</b> Any crash-reporting handler should be set up <i>before</i> calling this method
39+
*/
40+
public static void enableRxJavaAssemblyTracking() {
41+
RxJavaAssemblyTracking.enable();
42+
setRxJavaAssemblyHandler();
43+
}
44+
45+
/**
46+
* Set handler to intercept an exception, improve the StackTrace of RxJava-related ones and rethrow let the exception go through
47+
*/
48+
private static void setRxJavaAssemblyHandler() {
49+
final Thread.UncaughtExceptionHandler previousDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
50+
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
51+
@Override
52+
public void uncaughtException(Thread t, Throwable e) {
53+
Throwable toThrow = e;
54+
55+
RxJavaAssemblyException assembledException = RxJavaAssemblyException.find(e);
56+
if (assembledException != null) {
57+
StackTraceElement[] clearStack = parseStackTrace(assembledException);
58+
Throwable clearException = new Throwable(e);
59+
clearException.setStackTrace(clearStack);
60+
toThrow = clearException;
61+
}
62+
63+
previousDefaultHandler.uncaughtException(t, toThrow);
64+
}
65+
});
66+
}
67+
68+
/**
69+
* Extract StackTrace and filter to show an app-specific entry at its top
70+
*
71+
* @param exception RxJavaAssemblyException to be parsed
72+
* @return StackTrace, filtered so a app-specific line is at the top of it
73+
*/
74+
private @NonNull
75+
static StackTraceElement[] parseStackTrace(@NonNull RxJavaAssemblyException exception) {
76+
String[] lines = exception.stacktrace()
77+
.split(NEW_LINE_REGEX);
78+
79+
List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>();
80+
boolean appSpecificFound = false;
81+
for (String line : lines) {
82+
appSpecificFound = appSpecificFound || line.contains(BASE_APP_PACKAGE_NAME);
83+
if (appSpecificFound) {
84+
StackTraceElement element = parseStackTraceLine(line);
85+
if (element != null) {
86+
stackTrace.add(element);
87+
}
88+
}
89+
}
90+
91+
return stackTrace.toArray(new StackTraceElement[0]);
92+
}
93+
94+
/**
95+
* Parse string containing a <i>single line</i> of a StackTrace
96+
*
97+
* @param stackTraceLine string containing single line of a StackTrace
98+
* @return parsed StackTraceElement
99+
*/
100+
private @Nullable
101+
static StackTraceElement parseStackTraceLine(@NonNull String stackTraceLine) {
102+
StackTraceElement retVal = null;
103+
104+
Matcher matcher = STACK_TRACE_ELEMENT_PATTERN.matcher(stackTraceLine);
105+
if (matcher.matches()) {
106+
String clazz = matcher.group(1);
107+
String method = matcher.group(2);
108+
String filename = matcher.group(3);
109+
int line = Integer.valueOf(matcher.group(4));
110+
retVal = new StackTraceElement(clazz, method, filename, line);
111+
}
112+
return retVal;
113+
}
114+
115+
}

0 commit comments

Comments
 (0)