Closed elihart closed 2 years ago
Hi @elihart
Thanks for reporting the issue. We'll take a look to see if there are any optimizations we can make to mitigate this.
@elihart we'll look into doing some profiling to confirm how much Bugsnag might be contributing to the issue. As you have other libraries hooking in to onActivityResumed
it's not necessarily the case that Bugsnag is having the most significant impact, just because that's what is in the stack when we capture the stacktrace in some of these cases.
In the meantime if this is a concern one option to mitigate this would be to disable BreadcrumbType.STATE
breadcrumbs in enabledBreadcrumbTypes
, as this would prevent Bugsnag hooking in to ActivityBreadcrumbCollector
:
https://docs.bugsnag.com/platforms/android/configuration-options/#enabledbreadcrumbtypes
Following up on this, we are seeing ANRs from bugsnag breadcrumbs that happen in other places beyond just activity resume. We have a bugsnag error grouping for ANRs that happen on any custom place that we leave a breadcrumb in the app.
They all share this part of the stacktrace:
ANR
Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 24. Wait queue head age: 14105.7ms.)
[vdso]:1248 __kernel_rt_sigreturn
/data/app/com.airbnb.android-1/oat/arm64/base.odex:139548288 oatexec
unknown:-2 com.bugsnag.android.ndk.NativeBridge.addBreadcrumb
NativeBridge:109 com.bugsnag.android.ndk.NativeBridge.update
Observable.java:161 java.util.Observable.notifyObservers
BaseObservable:8 com.bugsnag.android.BaseObservable.notifyObservers
BreadcrumbState:39 com.bugsnag.android.BreadcrumbState.add
Client:844 com.bugsnag.android.Client.leaveBreadcrumb
BugsnagWrapperImpl:104 com.airbnb.android.base.debugimpl.BugsnagWrapperImpl.leaveBreadcrumb
BugsnagWrapper:231 com.airbnb.android.base.debug.BugsnagWrapper.leaveBreadcrumb
Has there been any progress in improving this? Could breadcrumbs be left asynchronously?
Thanks for the additional info.
We've already released a few performance optimizations in recent versions which reduce the amount of work Bugsnag does on the main thread.
We also are working on some more significant changes to how Bugsnag persists data to device storage which should further reduce the likelihood of such ANRs. I'll update this issue once these improvements are released.
Fantastic, thank you!
I assume work is ongoing on the more significant changes to address bugsnag performance, but I thought I'd share some recent ANR stacktraces where the Bugsnag client was caught logging breadcrumbs in onPause
ANR: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago. Wait queue length: 52. Wait queue head age: 5496.2ms.)
at java.util.Date.<init>(Date.java:165)
at com.bugsnag.android.Client.leaveBreadcrumb(Client:896)
at com.bugsnag.android.Client$2.invoke(Client:196)
at com.bugsnag.android.Client$2.invoke(Client:192)
at com.bugsnag.android.ActivityBreadcrumbCollector.leaveBreadcrumb(ActivityBreadcrumbCollector:46)
at com.bugsnag.android.ActivityBreadcrumbCollector.leaveBreadcrumb$default(ActivityBreadcrumbCollector:36)
at com.bugsnag.android.ActivityBreadcrumbCollector.onActivityPaused(ActivityBreadcrumbCollector:23)
at android.app.Application.dispatchActivityPaused(Application.java:251)
at android.app.Activity.onPause(Activity.java:1731)
ANR
Broadcast of Intent { act=android.intent.action.SCREEN_OFF flg=0x50200010 }
[vdso]:1672 __kernel_rt_sigreturn
/system/lib64/libart.so:3828120 art::OatFile::OatMethod::LinkMethod(art::ArtMethod*) const
/system/lib64/libart.so:1089968
/system/lib64/libart.so:1086428 art::ClassLinker::LoadClassMembers(art::Thread*, art::DexFile const&, unsigned char const*, art::Handle<art::mirror::Class>)
/system/lib64/libart.so:1062680 art::ClassLinker::DefineClass(art::Thread*, char const*, unsigned long, art::Handle<art::mirror::ClassLoader>, art::DexFile const&, art::DexFile::ClassDef const&)
/system/lib64/libart.so:1061016 art::ClassLinker::FindClassInBaseDexClassLoader(art::ScopedObjectAccessAlreadyRunnable&, art::Thread*, char const*, unsigned long, art::Handle<art::mirror::ClassLoader>, art::ObjPtr<art::mirror::Class>*)
/system/lib64/libart.so:1065572 art::ClassLinker::FindClass(art::Thread*, char const*, art::Handle<art::mirror::ClassLoader>)
/system/lib64/libart.so:991352 art::ClassLinker::ResolveType(art::DexFile const&, art::dex::TypeIndex, art::Handle<art::mirror::DexCache>, art::Handle<art::mirror::ClassLoader>)
/system/lib64/libart.so:1127660 art::ClassLinker::ResolveType(art::DexFile const&, art::dex::TypeIndex, art::ObjPtr<art::mirror::Class>)
/system/lib64/libart.so:1077612 art::ClassLinker::LoadSuperAndInterfaces(art::Handle<art::mirror::Class>, art::DexFile const&)
/system/lib64/libart.so:1062764 art::ClassLinker::DefineClass(art::Thread*, char const*, unsigned long, art::Handle<art::mirror::ClassLoader>, art::DexFile const&, art::DexFile::ClassDef const&)
/system/lib64/libart.so:1061016 art::ClassLinker::FindClassInBaseDexClassLoader(art::ScopedObjectAccessAlreadyRunnable&, art::Thread*, char const*, unsigned long, art::Handle<art::mirror::ClassLoader>, art::ObjPtr<art::mirror::Class>*)
/system/lib64/libart.so:1065572 art::ClassLinker::FindClass(art::Thread*, char const*, art::Handle<art::mirror::ClassLoader>)
/system/lib64/libart.so:991352 art::ClassLinker::ResolveType(art::DexFile const&, art::dex::TypeIndex, art::Handle<art::mirror::DexCache>, art::Handle<art::mirror::ClassLoader>)
/system/lib64/libart.so:742564
/system/lib64/libart.so:2473332
/system/lib64/libart.so:5049072 MterpNewInstance
/system/lib64/libart.so:5064468 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5045560 MterpInvokeVirtualQuick
/system/lib64/libart.so:5089944 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5037696 MterpInvokeDirect
/system/lib64/libart.so:5074456 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5037696 MterpInvokeDirect
/system/lib64/libart.so:5074456 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5045560 MterpInvokeVirtualQuick
/system/lib64/libart.so:5089944 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5038392 MterpInvokeStatic
/system/lib64/libart.so:5074584 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:2358568 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)
/system/lib64/libart.so:2459788 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)
/system/lib64/libart.so:5037696 MterpInvokeDirect
/system/lib64/libart.so:5074456 ExecuteMterpImpl
/system/lib64/libart.so:2332200
/system/lib64/libart.so:4983440 artQuickToInterpreterBridge
/system/lib64/libart.so:5171232
/system/framework/arm64/boot-framework.oat:7780552 oatexec
unknown:-2 com.bugsnag.android.ndk.NativeBridge.addBreadcrumb
NativeBridge:109 com.bugsnag.android.ndk.NativeBridge.onStateChange
BaseObservable:37 com.bugsnag.android.BaseObservable.updateState$bugsnag_android_core_release
BreadcrumbState:104 com.bugsnag.android.BreadcrumbState.add
Client:896 com.bugsnag.android.Client.leaveBreadcrumb
Client:196 com.bugsnag.android.Client$2.invoke
Client:192 com.bugsnag.android.Client$2.invoke
ActivityBreadcrumbCollector:46 com.bugsnag.android.ActivityBreadcrumbCollector.leaveBreadcrumb
ActivityBreadcrumbCollector:36 com.bugsnag.android.ActivityBreadcrumbCollector.leaveBreadcrumb$default
ActivityBreadcrumbCollector:23 com.bugsnag.android.ActivityBreadcrumbCollector.onActivityPaused
Application.java:236 android.app.Application.dispatchActivityPaused
Activity.java:1795 android.app.Activity.onPause
We've now released v5.16.0 which includes performance improvements around breadcrumb date formatting that should address this. (#1525).
Thanks again for raising this @elihart!
Describe the bug
We had an ANR reported by bugsnag that shows bugsnag's internal
ActivityBreadcrumbCollector
in the trace. This was Bugsnag's automatic logging of a breadcrumb on activity resumed.Note that this is fairly rare, so it's not a big problem for us, but of course we'd prefer if this was optimized. Also we do have similar ANR stacktraces showing other libraries that use the onActivityResumed application hook to do their own things, and these all together contribute.
Environment