All Projects → akaita → Rxjava2debug

akaita / Rxjava2debug

Licence: apache-2.0
RxJava 2.x extension to provide meaningful Stack Traces

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Rxjava2debug

Bugsnag React Native
Error monitoring and reporting tool for native exceptions and JS errors in React Native apps
Stars: ✭ 374 (-44.43%)
Mutual labels:  crash-reporting, crash, stacktrace
Bugsnag Go
Automatic panic monitoring for Go and Go web frameworks, like negroni, gin, and revel
Stars: ✭ 155 (-76.97%)
Mutual labels:  crash-reporting, crash
Countly Sdk Android
Countly Product Analytics Android SDK
Stars: ✭ 626 (-6.98%)
Mutual labels:  crash-reporting, crash
backtrace-unity
First-class error reporting for the Unity game engine.
Stars: ✭ 99 (-85.29%)
Mutual labels:  crash-reporting, crash
Bugsnag Android
Bugsnag crash monitoring and reporting tool for Android apps
Stars: ✭ 990 (+47.1%)
Mutual labels:  crash-reporting, crash
Bugsnag Python
Official bugsnag error monitoring and error reporting for django, flask, tornado and other python apps.
Stars: ✭ 69 (-89.75%)
Mutual labels:  crash-reporting, crash
bugsnag-java
Bugsnag error reporting for Java.
Stars: ✭ 51 (-92.42%)
Mutual labels:  crash-reporting, crash
Panicparse
Crash your app in style (Golang)
Stars: ✭ 2,954 (+338.93%)
Mutual labels:  crash, stack-traces
kotlin-multiplatform-example
A Kotlin multiplatform example app that targets Android, ReactJS, iOS, JavaFx, and Spring Boot
Stars: ✭ 115 (-82.91%)
Mutual labels:  crash-reporting, crash
asmCrashReport
🐞 Installs signal handlers to capture stack traces for MinGW 32 and macOS builds.
Stars: ✭ 39 (-94.21%)
Mutual labels:  stacktrace, crash-reporting
CrashLogger
A dll injected into process to dump stack when crashing.
Stars: ✭ 19 (-97.18%)
Mutual labels:  crash-reporting, crash
Planb Android
A crash recovery library for Android. It allows tracking and handling crashes with different rules for debugging and production.
Stars: ✭ 29 (-95.69%)
Mutual labels:  crash-reporting, crash
Bugsnag Laravel
Bugsnag notifier for the Laravel PHP framework. Monitor and report Laravel errors.
Stars: ✭ 746 (+10.85%)
Mutual labels:  crash-reporting, crash
Xcrash
🔥 xCrash provides the Android app with the ability to capture java crash, native crash and ANR. No root permission or any system permissions are required.
Stars: ✭ 148 (-78.01%)
Mutual labels:  crash-reporting, crash
Sentry Ruby
Sentry SDK for Ruby
Stars: ✭ 724 (+7.58%)
Mutual labels:  crash-reporting, stacktrace
Xcrash
🔥 xCrash provides the Android app with the ability to capture java crash, native crash and ANR. No root permission or any system permissions are required.
Stars: ✭ 2,689 (+299.55%)
Mutual labels:  crash-reporting, crash
Ololog
A better console.log for the log-driven debugging junkies
Stars: ✭ 141 (-79.05%)
Mutual labels:  stack-traces, stacktrace
Stacktrace
C++ library for storing and printing backtraces.
Stars: ✭ 250 (-62.85%)
Mutual labels:  stack-traces, stacktrace
Crashalert
Set of React Native components that allow reporting of the crashes in RN applications.
Stars: ✭ 68 (-89.9%)
Mutual labels:  crash-reporting, crash
Impact
Crash capturing library for Apple platforms
Stars: ✭ 395 (-41.31%)
Mutual labels:  crash-reporting, crash

RxJava2Debug Tweet

License Maven Jcenter Arsenal Methods

A library to make StackTraces involving RxJava2 more meaningful (they will always point to your code!).

Rationale

If you use RxJava2, you know the pain of debugging exceptions generated somwhere across the stream, in another thread, in a nested stream, ... The StackTrace provided by RxJava2 will tell you almost nothing. Even more, if you are using systems like Crashlytics to collect reports for and Android app, most RxJava-related crashes will be reported as a single error instance (omg, no way to fix that).

This library was created from the need to debug such situations when they happen in Android apps; even more, I needed to have a clear and precise report in Crashlytics for each distinct exception.

  1. If you handle exceptions generated in RxJava2 streams, you can query RxJava2Debug to obtain an extended StackTrace pointing to the exact line of code that created the issue.

  2. If you let exceptions generated in RxJava2 streams crash your app, RxJava2Debug will automatically extend the default StackTrace.

  3. If you let exceptions generated in RxJava2 streams crash your app and you configure RxJava2Debug with your package-names, RxJava2Debug will make sure you get unique reports for each issue (to Crashlytics, or whichever reporting system you use).

Installation

Using Maven Central :

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.akaita.java:rxjava2-debug:1.4.0'
}

Using JCenter:

repositories {
    jcenter()
}

dependencies {
    compile 'com.akaita.java:rxjava2-debug:1.4.0'
}

Compatibility

RxJava2Debug 1.3.0+: RxJava 2.2.1+

RxJava2Debug 1.2.2: RxJava 2.1.0 to 2.2.0

Usage

Just enable RxJava2Debug as soon as possible. In Android, for example:

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        
        Fabric.with(this, new Crashlytics());
        
        // Enable RxJava assembly stack collection, to make RxJava crash reports clear and unique
        // Make sure this is called AFTER setting up any Crash reporting mechanism as Crashlytics
        RxJava2Debug.enableRxJava2AssemblyTracking(new String[]{"com.example.myapp", "com.example.mylibrary"});
    }
}

This will:

  • Enhance stack traces of all RxJava2-related crashes making sure they contain a reference to the method that generated the first event in the Rx pipeline
  • Make sure that Stack Traces contain a reference to your code (some class in com.example.myapp or com.example.mylibrary)
  • Make sure that crash reports in Crashlytics are actually different for each pipeline (avoid bundling every RXJava error into one reports)

You will now also be able to obtain an enhanced Stack Trace even when you implement onError (really, you should implement it):

responseSubject
    .subscribe(
        responseObservable -> handleResponse(responseObservable),
        throwable -> RxJava2Debug.getEnhancedStackTrace(throwable)
    );
Without RxJava2Debug With RxJava2Debug
raw stack trace enhanced stack trace
raw crash report enhanced crash report

API

Start collecting information about RxJava's execution to provide a more meaningful StackTrace in case of crash
Beware: Any crash-reporting handler should be set up before calling this method

void enableRxJava2AssemblyTracking()

Start collecting filtered information about RxJava's execution to provide a more meaningful StackTrace in case of crash
Beware: Any crash-reporting handler should be set up before calling this method

void enableRxJava2AssemblyTracking(@Nullable String[] basePackageNames)

Disable the collection of more information about RxJava's execution
Information collected before calling this method will still be reported

void disableRxJava2AssemblyTracking()

Obtain a copy of the original Throwable with an extended StackTrace

@Nullable Throwable getEnhancedStackTrace(Throwable originalException)

Features

StackTrace generation

Regardless of the thread a crash happens in, a nice StackTrace referring to the origin of the RxJava2 pipeline will be added to the causes of the crash.

Config:

RxJava2Debug.enableRxJava2AssemblyTracking();

Example (pointing to my own faulty code in com.akaita.fgas.activities.TopActivity.onResume(TopActivity.java:205)):

FATAL EXCEPTION: main
Process: com.akaita.fgas.debug, PID: 22538
java.lang.Throwable: The mapper function returned a null value.
   at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
   at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
   at hu.akarnokd.rxjava2.debug.ObservableOnAssembly$OnAssemblyObserver.onNext(ObservableOnAssembly.java:55)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
   at hu.akarnokd.rxjava2.debug.ObservableOnAssembly$OnAssemblyObserver.onNext(ObservableOnAssembly.java:55)
   at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248)
   at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
   at io.reactivex.Observable.subscribe(Observable.java:10838)
   at hu.akarnokd.rxjava2.debug.ObservableOnAssemblyScalarCallable.subscribeActual(ObservableOnAssemblyScalarCallable.java:41)
   at io.reactivex.Observable.subscribe(Observable.java:10838)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
   at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
   at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
   at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
   at java.lang.Thread.run(Thread.java:761)
Caused by: caused by java.lang.NullPointerException: The mapper function returned a null value.
   at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
   at com.akaita.fgas.activities.TopActivity.onResume(TopActivity.java:205)
   at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
   at android.app.Activity.performResume(Activity.java:6766)
   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377)
   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6077)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

Instead of the obscure:

FATAL EXCEPTION: main
Process: com.akaita.fgas.debug, PID: 27300
io.reactivex.exceptions.OnErrorNotImplementedException: The mapper function returned a null value.
   at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
   at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
   at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)
   at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.checkTerminated(ObservableObserveOn.java:276)
   at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:172)
   at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
   at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
   at android.os.Handler.handleCallback(Handler.java:751)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6077)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.NullPointerException: The mapper function returned a null value.
   at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
   at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
   at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248)
   at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
   at io.reactivex.Observable.subscribe(Observable.java:10838)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
   at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
   at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
   at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
   at java.lang.Thread.run(Thread.java:761)

StackTrace filtering

Tell RxJava2Debug which packages names you want to highlight, and RxJava2Debug will make sure they appear as the top of the StackTrace

Config:

RxJava2Debug.enableRxJava2AssemblyTracking(new String[]{"com.akaita.fgas", "com.akaita.android"});

Result:

FATAL EXCEPTION: main
Process: com.akaita.fgas.debug, PID: 22538
java.lang.Throwable: caused by java.lang.NullPointerException: The mapper function returned a null value.
   at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
   at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
   [...]
Caused by: java.lang.Throwable
   at com.akaita.fgas.activities.TopActivity.onResume(TopActivity.java:205)
   at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
   at android.app.Activity.performResume(Activity.java:6766)
   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377)
   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3440)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6077)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

This comes in very handy when you work with a error reporting system such as Crashlytics.

Instead of getting a multitude of reports involving RxJava2 into a single report entry, you'll get one entry per crash.

Credits

This library is using a subset of classes from akarnokd's RxJava2Extensions.

RxJava2Extensions takes about 1mb and contains 5231 methods. RxJava2Debug takes about 38kb and contains 239 methods.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].