Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make event.unhandled overridable for JVM errors #1025

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## TBD

* Make `event.unhandled` overridable for JVM errors
[#1025](https://github.com/bugsnag/bugsnag-android/pull/1025)

## 5.3.0 (2020-12-02)

* Add integrity header to verify Error and Session API payloads have not changed
Expand Down
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
source "https://rubygems.org"

# You can run against local Maze Runner branches and uncommitted changes:
gem 'bugsnag-maze-runner', path: '../maze-runner'
#gem 'bugsnag-maze-runner', path: '../maze-runner'

# Or a specific release:
#gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v3.2.0'
gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v3.5.1'

# Or follow master:
#gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner'
12 changes: 7 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
PATH
remote: ../maze-runner
GIT
remote: https://github.com/bugsnag/maze-runner
revision: 6f71772f97dd1b9f2d28e397f0f1faee061f37a0
tag: v3.5.1
specs:
bugsnag-maze-runner (3.2.0)
bugsnag-maze-runner (3.5.1)
appium_lib (~> 10.2)
cucumber (~> 3.1.2)
cucumber-expressions (~> 6.0.0)
Expand All @@ -21,7 +23,7 @@ GEM
appium_lib_core (~> 3.3)
nokogiri (~> 1.8, >= 1.8.1)
tomlrb (~> 1.1)
appium_lib_core (3.11.0)
appium_lib_core (3.11.1)
faye-websocket (~> 0.11.0)
selenium-webdriver (~> 3.14, >= 3.14.1)
backports (3.18.2)
Expand Down Expand Up @@ -64,7 +66,7 @@ GEM
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
test-unit (3.3.6)
test-unit (3.3.7)
power_assert
tomlrb (1.3.0)
websocket-driver (0.7.3)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class EventPayloadTest {
public void setUp() {
ImmutableConfig config = BugsnagTestUtils.generateImmutableConfig();
RuntimeException exception = new RuntimeException("Something broke");
HandledState handledState = HandledState.newInstance(HandledState.REASON_ANR);
Event event = new Event(exception, config, handledState, NoopLogger.INSTANCE);
SeverityReason severityReason = SeverityReason.newInstance(SeverityReason.REASON_ANR);
Event event = new Event(exception, config, severityReason, NoopLogger.INSTANCE);
event.setApp(generateAppWithState());
event.setDevice(generateDeviceWithState());
eventPayload = new EventPayload("api-key", event, new Notifier());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.bugsnag.android;

import static com.bugsnag.android.HandledState.REASON_HANDLED_EXCEPTION;
import static com.bugsnag.android.ImmutableConfigKt.sanitiseConfiguration;
import static com.bugsnag.android.SeverityReason.REASON_HANDLED_EXCEPTION;

import android.app.ActivityManager;
import android.app.Application;
Expand Down Expand Up @@ -614,9 +614,9 @@ public void notify(@NonNull Throwable exception) {
*/
public void notify(@NonNull Throwable exc, @Nullable OnErrorCallback onError) {
if (exc != null) {
HandledState handledState = HandledState.newInstance(REASON_HANDLED_EXCEPTION);
SeverityReason severityReason = SeverityReason.newInstance(REASON_HANDLED_EXCEPTION);
Metadata metadata = metadataState.getMetadata();
Event event = new Event(exc, immutableConfig, handledState, metadata, logger);
Event event = new Event(exc, immutableConfig, severityReason, metadata, logger);
populateAndNotifyAndroidEvent(event, onError);
} else {
logNull("notify");
Expand All @@ -629,10 +629,10 @@ public void notify(@NonNull Throwable exc, @Nullable OnErrorCallback onError) {
* Should only ever be called from the {@link ExceptionHandler}.
*/
void notifyUnhandledException(@NonNull Throwable exc, Metadata metadata,
@HandledState.SeverityReason String severityReason,
@SeverityReason.SeverityReasonType String severityReason,
@Nullable String attributeValue) {
HandledState handledState
= HandledState.newInstance(severityReason, Severity.ERROR, attributeValue);
SeverityReason handledState
= SeverityReason.newInstance(severityReason, Severity.ERROR, attributeValue);
Metadata data = Metadata.Companion.merge(metadataState.getMetadata(), metadata);
Event event = new Event(exc, immutableConfig, handledState, data, logger);
populateAndNotifyAndroidEvent(event, null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.bugsnag.android;

import static com.bugsnag.android.HandledState.REASON_PROMISE_REJECTION;
import static com.bugsnag.android.SeverityReason.REASON_PROMISE_REJECTION;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
Expand Down Expand Up @@ -45,7 +45,7 @@ void deliver(@NonNull Event event) {
}
}

if (event.isUnhandled()) {
if (event.impl.getOriginalUnhandled()) {
// should only send unhandled errors if they don't terminate the process (i.e. ANRs)
String severityReasonType = event.impl.getSeverityReasonType();
boolean promiseRejection = REASON_PROMISE_REJECTION.equals(severityReasonType);
Expand Down
26 changes: 21 additions & 5 deletions bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ public class Event implements JsonStream.Streamable, MetadataAware, UserAware {

Event(@Nullable Throwable originalError,
@NonNull ImmutableConfig config,
@NonNull HandledState handledState,
@NonNull SeverityReason severityReason,
@NonNull Logger logger) {
this(originalError, config, handledState, new Metadata(), logger);
this(originalError, config, severityReason, new Metadata(), logger);
}

Event(@Nullable Throwable originalError,
@NonNull ImmutableConfig config,
@NonNull HandledState handledState,
@NonNull SeverityReason severityReason,
@NonNull Metadata metadata,
@NonNull Logger logger) {
this(new EventInternal(originalError, config, handledState, metadata), logger);
this(new EventInternal(originalError, config, severityReason, metadata), logger);
}

Event(@NonNull EventInternal impl, @NonNull Logger logger) {
Expand Down Expand Up @@ -289,9 +289,25 @@ public void toStream(@NonNull JsonStream stream) throws IOException {
/**
* Whether the event was a crash (i.e. unhandled) or handled error in which the system
* continued running.
*
* Unhandled errors count towards your stability score. If you don't want certain errors
* to count towards your stability score, you can alter this property through an
* {@link OnErrorCallback}.
*/
public boolean isUnhandled() {
return impl.isUnhandled();
return impl.getUnhandled();
}

/**
* Whether the event was a crash (i.e. unhandled) or handled error in which the system
* continued running.
*
* Unhandled errors count towards your stability score. If you don't want certain errors
* to count towards your stability score, you can alter this property through an
* {@link OnErrorCallback}.
*/
public void setUnhandled(boolean unhandled) {
impl.setUnhandled(unhandled);
}

protected boolean shouldDiscardClass() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.io.IOException
internal class EventInternal @JvmOverloads internal constructor(
val originalError: Throwable? = null,
config: ImmutableConfig,
private var handledState: HandledState,
private var severityReason: SeverityReason,
data: Metadata = Metadata()
) : JsonStream.Streamable, MetadataAware, UserAware {

Expand All @@ -16,23 +16,32 @@ internal class EventInternal @JvmOverloads internal constructor(
internal var session: Session? = null

var severity: Severity
get() = handledState.currentSeverity
get() = severityReason.currentSeverity
set(value) {
handledState.currentSeverity = value
severityReason.currentSeverity = value
}

var apiKey: String = config.apiKey
lateinit var app: AppWithState
lateinit var device: DeviceWithState
val isUnhandled: Boolean = handledState.isUnhandled
var breadcrumbs: MutableList<Breadcrumb> = mutableListOf()
var unhandled: Boolean
get() = severityReason.unhandled
set(value) {
severityReason.unhandled = value
}
val unhandledOverridden: Boolean
get() = severityReason.unhandledOverridden

val originalUnhandled: Boolean
get() = severityReason.originalUnhandled

var errors: MutableList<Error> = when (originalError) {
null -> mutableListOf()
else -> Error.createError(originalError, config.projectPackages, config.logger)
}

var threads: MutableList<Thread> = ThreadState(originalError, isUnhandled, config).threads
var threads: MutableList<Thread> = ThreadState(originalError, unhandled, config).threads
var groupingHash: String? = null
var context: String? = null

Expand All @@ -58,6 +67,7 @@ internal class EventInternal @JvmOverloads internal constructor(
return "ANR" == errorClass
}


@Throws(IOException::class)
override fun toStream(writer: JsonStream) {
// Write error basics
Expand All @@ -66,8 +76,8 @@ internal class EventInternal @JvmOverloads internal constructor(
writer.name("metaData").value(metadata)

writer.name("severity").value(severity)
writer.name("severityReason").value(handledState)
writer.name("unhandled").value(handledState.isUnhandled)
writer.name("severityReason").value(severityReason)
writer.name("unhandled").value(severityReason.unhandled)

// Write exception info
writer.name("exceptions")
Expand Down Expand Up @@ -105,12 +115,12 @@ internal class EventInternal @JvmOverloads internal constructor(
}

protected fun updateSeverityInternal(severity: Severity) {
handledState = HandledState.newInstance(handledState.severityReasonType,
severity, handledState.attributeValue)
severityReason = SeverityReason.newInstance(severityReason.severityReasonType,
severity, severityReason.attributeValue)
this.severity = severity
}

fun getSeverityReasonType(): String = handledState.severityReasonType
fun getSeverityReasonType(): String = severityReason.severityReasonType

override fun setUser(id: String?, email: String?, name: String?) {
_user = User(id, email, name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwab
}

String severityReason = strictModeThrowable
? HandledState.REASON_STRICT_MODE : HandledState.REASON_UNHANDLED_EXCEPTION;
? SeverityReason.REASON_STRICT_MODE : SeverityReason.REASON_UNHANDLED_EXCEPTION;

if (strictModeThrowable) { // writes to disk on main thread
StrictMode.ThreadPolicy originalThreadPolicy = StrictMode.getThreadPolicy();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.bugsnag.android;

import static com.bugsnag.android.DeliveryHeadersKt.HEADER_INTERNAL_ERROR;
import static com.bugsnag.android.HandledState.REASON_UNHANDLED_EXCEPTION;
import static com.bugsnag.android.SeverityReason.REASON_UNHANDLED_EXCEPTION;

import android.annotation.SuppressLint;
import android.content.Context;
Expand Down Expand Up @@ -51,8 +51,8 @@ class InternalReportDelegate implements EventStore.Delegate {
@Override
public void onErrorIOFailure(Exception exc, File errorFile, String context) {
// send an internal error to bugsnag with no cache
HandledState handledState = HandledState.newInstance(REASON_UNHANDLED_EXCEPTION);
Event err = new Event(exc, immutableConfig, handledState, logger);
SeverityReason severityReason = SeverityReason.newInstance(REASON_UNHANDLED_EXCEPTION);
Event err = new Event(exc, immutableConfig, severityReason, logger);
err.setContext(context);

err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "canRead", errorFile.canRead());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ public boolean onError(@NonNull Event event) {
@NonNull
public static Event createEvent(@Nullable Throwable exc,
@NonNull Client client,
@NonNull HandledState handledState) {
return new Event(exc, client.getConfig(), handledState, client.logger);
@NonNull SeverityReason severityReason) {
return new Event(exc, client.getConfig(), severityReason, client.logger);
}

@NonNull
Expand Down
Loading