bugsnag / bugsnag-java

BugSnag error reporting for Java.
https://www.bugsnag.com/platforms/java/
MIT License
56 stars 34 forks source link

Options for client-side apps #212

Open zacharee opened 4 months ago

zacharee commented 4 months ago

Description

I've got a desktop JVM app as part of a Compose Multiplatform project. I'm using Bugsnag's JVM library for reporting errors, but it's pretty obvious it was built with server-sided apps in mind.

I can handle reporting sessions using the library's API, by calling startSession() when I initialize the Bugsnag client, and then using close() before the application terminates, but I haven't figured out how to associate users with sessions to enable the User Stability metric.

Describe the solution you'd like It'd be really helpful to have (default-null/disabled) APIs in the library for enabling a "client-side mode" of some sort that could handle session and user tracking like the Android and iOS libraries, or at least a public way to add that information into the payloads sent into Bugsnag.

Describe alternatives you've considered I checked around for third-party Bugsnag libraries for client-side Java apps but couldn't find any.

It might be possible to implement the C++ Bugsnag library, but then I'd lose Java stacktraces.

Additional context I noticed that the logic for associating users with sessions is at least partly implemented, but I couldn't figure out how to get it to work, even when using reflection.

To add the user object into a Report, I made a CustomReport class that extends Report and overrides setSession():

class CustomReport(config: Configuration, throwable: Throwable?) : Report(config, throwable) {
    constructor(bugsnag: Bugsnag, throwable: Throwable?) : this(bugsnag.config, throwable)
    internal override fun setSession(session: Session?) {
        super.setSession(session)
        getSession()["user"] = hashMapOf("id" to BifrostSettings.Keys.bugsnagUuid())
    }
}

I use that in my notify() wrapper instead of the normal Report class, and I have a custom Exception handler that calls my notify() wrapper on unhandled Exceptions.

I also used reflection to add a BeforeSendSessionCallback to the Bugsnag client and add a user object to the session diagnostics:

val beforeSendSessionClass = Class.forName("com.bugsnag.BeforeSendSession")
val sessionPayloadClass = Class.forName("com.bugsnag.SessionPayload")
val diagnosticsClass = Class.forName("com.bugsnag.Diagnostics")
bugsnag::class.java.getDeclaredMethod("addBeforeSendSession", beforeSendSessionClass)
    .apply {
        isAccessible = true
    }.invoke(
        bugsnag,
        Proxy.newProxyInstance(
            beforeSendSessionClass.classLoader,
            arrayOf(beforeSendSessionClass)
        ) { _, _, args ->
            val payload = args[0]

            val diagnostics = sessionPayloadClass.getDeclaredField("diagnostics")
                .apply { isAccessible = true }
                .get(payload)

            val userMap = diagnosticsClass.getDeclaredField("user")
                .apply { isAccessible = true }
                .get(diagnostics) as HashMap<String, String?>

            userMap["id"] = uuid

            null
        }
    )

But this combination doesn't seem to make User Stability show up.

clr182 commented 3 months ago

Hi @zacharee

Apologies for the delay in response time.

We are currently investigating this issue and will reach out once we have more information to share.

RobertoSmartBear commented 2 months ago

The Stability Score is actually calculated from the device.id and not the user.id. As the device.id is not currently available in a session or an event when using our Java notifier, we have raised some feedback with our Product Team, and we will update this thread when any news becomes available.

hannah-smartbear commented 1 month ago

Hi @zacharee

We have some work in our backlog to add device.id to sessions and events in our Java notifier in order to support session and user stability scores. While we don’t have an ETA on when this will be implemented, we will be sure to let you know of any updates.