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

Support SentryCoroutineExceptionHandler #1524

Open
marandaneto opened this issue Jun 11, 2021 · 8 comments · May be fixed by #4259
Open

Support SentryCoroutineExceptionHandler #1524

marandaneto opened this issue Jun 11, 2021 · 8 comments · May be fixed by #4259
Assignees

Comments

@marandaneto
Copy link
Contributor

marandaneto commented Jun 11, 2021

As we have a sentry-kotlin-extensions module right now and SentryContext for Coroutines, it'd be a nice addition offering a SentryCoroutineExceptionHandler, https://kotlinlang.org/docs/exception-handling.html#coroutineexceptionhandler
so people can use it and when it throws, it captures an event automatically, how does that sound?
Similar to our UncaughtExceptionHandlerIntegration

@marandaneto marandaneto added enhancement New feature or request kotlin-extensions labels Jun 11, 2021
@marandaneto
Copy link
Contributor Author

val handler = SentryCoroutineExceptionHandler { _, exception -> 
    // ideally we create an event with a mechanism
    Sentry.captureException(exception)
}
val job = GlobalScope.launch(handler) {
    throw AssertionError()
}

@marandaneto
Copy link
Contributor Author

examples can be found on https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-core/jvm/test/guide
example-exceptions-{number}-kt files

@marandaneto
Copy link
Contributor Author

works like a try/catch, if no CoroutineExceptionHandler is given, UncaughtExceptionHandlerIntegration gets called and crashes the App, but if a CoroutineExceptionHandler is given, it gets caught and swallowed, so its a bit less boilerplate than a try/catch but works the same way

@marandaneto
Copy link
Contributor Author

one thing to note is:

[CoroutineExceptionHandler] can be invoked from an arbitrary thread

so we cannot use the current thread when creating a ExceptionMechanismException

@marandaneto
Copy link
Contributor Author

marandaneto commented Jun 11, 2021

public object SentryCoroutineExceptionHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler {
    override fun handleException(context: CoroutineContext, exception: Throwable) {
        val mechanism = Mechanism().apply {
            // null and true is the same
            // isHandled = true
            type = "CoroutineExceptionHandler"
        }
        // cannot use the Thread.currentThread()
        // [CoroutineExceptionHandler] can be invoked from an arbitrary thread
        // ExceptionMechanismException should have an overload without a thread
        val error = ExceptionMechanismException(mechanism, exception, Thread.currentThread())
        val event = SentryEvent(error)
       // we probably need a hint here to not append anything from the `currentThread`
        Sentry.captureEvent(event)
    }
}
GlobalScope.launch(SentryCoroutineExceptionHandler) {
    throw AssertionError()
}

Screenshot 2021-06-11 at 10 31 16

@marandaneto
Copy link
Contributor Author

@bruno-garcia bruno-garcia moved this to Needs Discussion in Mobile SDKs Jan 11, 2022
@adinauer adinauer moved this from Needs Discussion to Needs Investigation in Mobile SDKs Mar 29, 2022
@marandaneto
Copy link
Contributor Author

Consider testing https://github.com/Anamorphosee/stacktrace-decoroutinator and adding to the docs if it gives better stack traces

@marandaneto marandaneto moved this from Needs Investigation to Backlog in Mobile SDKs Jun 1, 2023
@marandaneto
Copy link
Contributor Author

Relates to #2687 as well

@lcian lcian self-assigned this Mar 3, 2025
@lcian lcian linked a pull request Mar 13, 2025 that will close this issue
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Backlog
5 participants