-
Notifications
You must be signed in to change notification settings - Fork 34
Description
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.