Skip to content

Commit 2f57da4

Browse files
authored
error.type attribute support (#44)
* Prevent ANR duplicates * typo * Format change * Add error type attribute * rollback main activity * Formatting rules * Set different attribute size * Use variables * Remove unsupported test case * backtrace.version attribute (#45) * Add build version * Ignore dynamic attributes - attributes that changes over the time * Bring back native library initialization * Include backtrace.version attribute * Formatting changes * styles
1 parent eb58884 commit 2f57da4

File tree

15 files changed

+188
-28
lines changed

15 files changed

+188
-28
lines changed

backtrace-library/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ android {
99
targetSdkVersion 30
1010
versionCode 360
1111
versionName "3.6.0"
12+
buildConfigField("String", "VERSION_NAME", "\"${versionName}\"")
1213

1314
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1415

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package backtraceio.library;
2+
3+
import static junit.framework.TestCase.assertTrue;
4+
import static junit.framework.TestCase.fail;
5+
import static org.junit.Assert.assertEquals;
6+
7+
import android.content.Context;
8+
import android.support.test.InstrumentationRegistry;
9+
import android.support.test.runner.AndroidJUnit4;
10+
11+
import net.jodah.concurrentunit.Waiter;
12+
13+
import org.junit.Before;
14+
import org.junit.Test;
15+
import org.junit.runner.RunWith;
16+
17+
import java.util.concurrent.TimeUnit;
18+
19+
import backtraceio.library.events.OnServerResponseEventListener;
20+
import backtraceio.library.events.RequestHandler;
21+
import backtraceio.library.models.BacktraceAttributeConsts;
22+
import backtraceio.library.models.BacktraceData;
23+
import backtraceio.library.models.BacktraceResult;
24+
import backtraceio.library.models.json.BacktraceReport;
25+
import backtraceio.library.models.types.BacktraceResultStatus;
26+
27+
@RunWith(AndroidJUnit4.class)
28+
public class BacktraceErrorTypeAttributeTest {
29+
30+
private Context context;
31+
private BacktraceCredentials credentials;
32+
33+
@Before
34+
public void setUp() {
35+
context = InstrumentationRegistry.getContext();
36+
credentials = new BacktraceCredentials("https://example-endpoint.com/", "");
37+
}
38+
39+
@Test
40+
public void setDefaultErrorTypeForExceptionTypeOfError() {
41+
BacktraceReport report = new BacktraceReport(new Exception("test exception"));
42+
43+
assertTrue(report.attributes.containsKey(BacktraceAttributeConsts.ErrorType));
44+
assertEquals(report.attributes.get(BacktraceAttributeConsts.ErrorType), BacktraceAttributeConsts.HandledExceptionAttributeType);
45+
}
46+
47+
@Test
48+
public void setDefaultErrorTypeForMessageType() {
49+
BacktraceReport report = new BacktraceReport("test message");
50+
51+
assertTrue(report.attributes.containsKey(BacktraceAttributeConsts.ErrorType));
52+
assertEquals(report.attributes.get(BacktraceAttributeConsts.ErrorType), BacktraceAttributeConsts.MessageAttributeType);
53+
}
54+
55+
@Test
56+
public void sendBacktraceExceptionWithErrorType() {
57+
58+
BacktraceClient backtraceClient = new BacktraceClient(context, credentials);
59+
60+
final Waiter waiter = new Waiter();
61+
RequestHandler rh = new RequestHandler() {
62+
@Override
63+
public BacktraceResult onRequest(BacktraceData data) {
64+
return new BacktraceResult(data.report, data.report.exception.getMessage(),
65+
BacktraceResultStatus.Ok);
66+
}
67+
};
68+
backtraceClient.setOnRequestHandler(rh);
69+
70+
// WHEN
71+
backtraceClient.send(new Exception("test exception"), new
72+
OnServerResponseEventListener() {
73+
@Override
74+
public void onEvent(BacktraceResult backtraceResult) {
75+
// THEN
76+
String errorType = backtraceResult.getBacktraceReport().attributes.get(BacktraceAttributeConsts.ErrorType).toString();
77+
assertEquals(
78+
errorType,
79+
BacktraceAttributeConsts.HandledExceptionAttributeType);
80+
81+
waiter.resume();
82+
}
83+
}
84+
);
85+
// WAIT FOR THE RESULT FROM ANOTHER THREAD
86+
try {
87+
waiter.await(5, TimeUnit.SECONDS);
88+
} catch (Exception ex) {
89+
fail(ex.getMessage());
90+
}
91+
}
92+
}
Submodule crashpad-builds updated 194 files

backtrace-library/src/main/java/backtraceio/library/BacktraceDatabase.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import backtraceio.library.interfaces.DatabaseContext;
2222
import backtraceio.library.interfaces.DatabaseFileContext;
2323
import backtraceio.library.logger.BacktraceLogger;
24+
import backtraceio.library.models.BacktraceAttributeConsts;
2425
import backtraceio.library.models.BacktraceData;
2526
import backtraceio.library.models.BacktraceResult;
2627
import backtraceio.library.models.database.BacktraceDatabaseRecord;
@@ -177,7 +178,9 @@ public Boolean setupNativeIntegration(BacktraceBase client, BacktraceCredentials
177178
// Path to Crashpad native handler
178179
String handlerPath = _applicationContext.getApplicationInfo().nativeLibraryDir + _crashpadHandlerName;
179180

180-
BacktraceAttributes crashpadAttributes = new BacktraceAttributes(_applicationContext, null, client.attributes);
181+
// setup default native attribtues
182+
BacktraceAttributes crashpadAttributes = new BacktraceAttributes(_applicationContext, client.attributes);
183+
crashpadAttributes.attributes.put(BacktraceAttributeConsts.ErrorType, BacktraceAttributeConsts.CrashAttributeType);
181184
String[] keys = crashpadAttributes.attributes.keySet().toArray(new String[0]);
182185
String[] values = crashpadAttributes.attributes.values().toArray(new String[0]);
183186

backtrace-library/src/main/java/backtraceio/library/base/BacktraceBase.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import backtraceio.library.BacktraceCredentials;
1212
import backtraceio.library.BacktraceDatabase;
13+
import backtraceio.library.BuildConfig;
1314
import backtraceio.library.enums.BacktraceBreadcrumbLevel;
1415
import backtraceio.library.enums.BacktraceBreadcrumbType;
1516
import backtraceio.library.enums.UnwindingMode;
@@ -47,6 +48,11 @@ public class BacktraceBase implements Client {
4748
*/
4849
public final Database database;
4950

51+
/**
52+
* Backtrace client version
53+
*/
54+
public static String version = BuildConfig.VERSION_NAME;
55+
5056
/**
5157
* Get custom client attributes. Every argument stored in dictionary will be send to Backtrace API
5258
*/

backtrace-library/src/main/java/backtraceio/library/common/DeviceAttributesHelper.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ public DeviceAttributesHelper(Context context) {
4444
*
4545
* @return device attributes
4646
*/
47-
public HashMap<String, String> getDeviceAttributes() {
47+
public HashMap<String, String> getDeviceAttributes(Boolean includeDynamicAttributes) {
4848
HashMap<String, String> result = new HashMap<>();
4949
result.put("guid", this.generateDeviceId());
5050
result.put("uname.sysname", "Android");
5151
result.put("uname.machine", System.getProperty("os.arch"));
52-
result.put("cpu.boottime", String.valueOf(java.lang.System.currentTimeMillis() - android.os.SystemClock
53-
.elapsedRealtime()));
52+
if (includeDynamicAttributes == false) {
53+
return result;
54+
}
5455
result.put("device.airplane_mode", String.valueOf(isAirplaneModeOn()));
5556
result.put("device.location", getLocationServiceStatus().toString());
5657
result.put("device.nfc.status", getNfcStatus().toString());
@@ -65,6 +66,9 @@ public HashMap<String, String> getDeviceAttributes() {
6566
result.put("app.storage_used", getAppUsedStorageSize());
6667
result.put("battery.level", String.valueOf(getBatteryLevel()));
6768
result.put("battery.state", getBatteryState().toString());
69+
result.put("cpu.boottime", String.valueOf(java.lang.System.currentTimeMillis() - android.os.SystemClock
70+
.elapsedRealtime()));
71+
6872
return result;
6973
}
7074

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package backtraceio.library.models;
2+
3+
public class BacktraceAttributeConsts {
4+
public static final String ErrorType = "error.type";
5+
public static final String CrashAttributeType = "Crash";
6+
public static final String UnhandledExceptionAttributeType = "Unhandled Exception";
7+
public static final String HandledExceptionAttributeType = "Exception";
8+
public static final String MessageAttributeType = "Message";
9+
public static final String AnrAttributeType = "Hang";
10+
}

backtrace-library/src/main/java/backtraceio/library/models/BacktraceData.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import java.util.List;
88
import java.util.Map;
99

10-
import backtraceio.library.common.DeviceAttributesHelper;
10+
import backtraceio.library.BacktraceClient;
1111
import backtraceio.library.common.FileHelper;
1212
import backtraceio.library.logger.BacktraceLogger;
1313
import backtraceio.library.models.json.Annotations;
@@ -178,12 +178,7 @@ private void setReportInformation() {
178178
timestamp = report.timestamp;
179179
classifiers = report.exceptionTypeReport ? new String[]{report.classifier} : null;
180180
langVersion = System.getProperty("java.version"); //TODO: Fix problem with read Java version
181-
try {
182-
agentVersion = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
183-
} catch (Exception e) {
184-
BacktraceLogger.e(LOG_TAG, "Could not resolve package version name");
185-
agentVersion = "";
186-
}
181+
agentVersion = BacktraceClient.version;
187182
}
188183

189184
/**

backtrace-library/src/main/java/backtraceio/library/models/BacktraceExceptionHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public void uncaughtException(final Thread thread, final Throwable throwable) {
5353

5454
if (throwable instanceof Exception) {
5555
BacktraceLogger.e(LOG_TAG, "Sending uncaught exception to Backtrace API", throwable);
56-
this.client.send(new BacktraceReport((Exception) throwable, BacktraceExceptionHandler.customAttributes), callback);
56+
BacktraceReport report = new BacktraceReport((Exception) throwable, BacktraceExceptionHandler.customAttributes);
57+
report.attributes.put(BacktraceAttributeConsts.ErrorType, BacktraceAttributeConsts.UnhandledExceptionAttributeType);
58+
this.client.send(report, callback);
5759
BacktraceLogger.d(LOG_TAG, "Uncaught exception sent to Backtrace API");
5860
}
5961
BacktraceLogger.d(LOG_TAG, "Default uncaught exception handler");

backtrace-library/src/main/java/backtraceio/library/models/json/BacktraceAttributes.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.Map;
1515
import java.util.UUID;
1616

17+
import backtraceio.library.BacktraceClient;
1718
import backtraceio.library.BuildConfig;
1819
import backtraceio.library.common.BacktraceStringHelper;
1920
import backtraceio.library.common.DeviceAttributesHelper;
@@ -61,6 +62,15 @@ public class BacktraceAttributes {
6162
*/
6263
public BacktraceAttributes(Context context, BacktraceReport report, Map<String, Object>
6364
clientAttributes) {
65+
this(context, report, clientAttributes, true);
66+
}
67+
68+
public BacktraceAttributes(Context context, Map<String, Object> clientAttributes) {
69+
this(context, null, clientAttributes, false);
70+
}
71+
72+
public BacktraceAttributes(Context context, BacktraceReport report, Map<String, Object>
73+
clientAttributes, Boolean includeDynamicAttributes) {
6474
this.context = context;
6575
if (report != null) {
6676
this.convertReportAttributes(report);
@@ -73,8 +83,8 @@ public BacktraceAttributes(Context context, BacktraceReport report, Map<String,
7383
BacktraceReport.concatAttributes(report, clientAttributes);
7484
}
7585
setAppInformation();
76-
setDeviceInformation();
77-
setScreenInformation();
86+
setDeviceInformation(includeDynamicAttributes);
87+
setScreenInformation(includeDynamicAttributes);
7888

7989
// For tracking crash-free sessions we need to add
8090
// application.session and application.version to Backtrace attributes
@@ -90,7 +100,7 @@ public Map<String, Object> getComplexAttributes() {
90100
/**
91101
* Set information about device eg. lang, model, brand, sdk, manufacturer, os version
92102
*/
93-
private void setDeviceInformation() {
103+
private void setDeviceInformation(Boolean includeDynamicAttributes) {
94104
this.attributes.put("uname.version", Build.VERSION.RELEASE);
95105
this.attributes.put("culture", Locale.getDefault().getDisplayLanguage());
96106
this.attributes.put("build.type", BuildConfig.DEBUG ? "Debug" : "Release");
@@ -103,7 +113,7 @@ private void setDeviceInformation() {
103113
this.attributes.put("device.os_version", System.getProperty("os.version"));
104114

105115
DeviceAttributesHelper deviceAttributesHelper = new DeviceAttributesHelper(this.context);
106-
this.attributes.putAll(deviceAttributesHelper.getDeviceAttributes());
116+
this.attributes.putAll(deviceAttributesHelper.getDeviceAttributes(includeDynamicAttributes));
107117
}
108118

109119
private void setAppInformation() {
@@ -117,19 +127,23 @@ private void setAppInformation() {
117127
// But we keep version attribute name as to not break any customer workflows
118128
this.attributes.put("version", version);
119129
}
130+
this.attributes.put("backtrace.version", BacktraceClient.version);
120131
}
121132

122133
/**
123134
* Set information about screen such as screen width, height, dpi, orientation
124135
*/
125-
private void setScreenInformation() {
136+
private void setScreenInformation(Boolean includeDynamicAttributes) {
126137
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
127138
Display display = wm.getDefaultDisplay();
128139
DisplayMetrics metrics = new DisplayMetrics();
129140
display.getMetrics(metrics);
130141
this.attributes.put("screen.width", String.valueOf(metrics.widthPixels));
131142
this.attributes.put("screen.height", String.valueOf(metrics.heightPixels));
132143
this.attributes.put("screen.dpi", String.valueOf(metrics.densityDpi));
144+
if (includeDynamicAttributes == false) {
145+
return;
146+
}
133147
this.attributes.put("screen.orientation", getScreenOrientation().toString());
134148
this.attributes.put("screen.brightness", String.valueOf(getScreenBrightness()));
135149
}

0 commit comments

Comments
 (0)