Use our Kotlin Multiplatform SDK in your applications for Android, iOS and web.
Add the bugsnag-kmp
dependency to your Module Gradle Settings, usually found at build.gradle.kts
:
dependencies {
implementation("com.bugsnag:bugsnag-kmp:+")
}
In your Xcode project add bugsnag-cocoa
as a Swift Package Manager (recommended) or other project dependency. See our iOS integration guide for instructions.
We recommend sharing your BugSnag configuration code in a common module and called from the platform-specific initialization code in each of your Kotlin Multiplatform apps:
// BugsnagStartup.kt
import com.bugsnag.kmp.Bugsnag
import com.bugsnag.kmp.Configuration
fun startBugsnag(configuration: Configuration) {
// common configuration here
configuration.addMetadata("App", "multiplatform", true)
Bugsnag.start(configuration)
}
The Bugsnag
client should be initialized as early as possible in your application lifecycle. The following are our recommended approaches for Android, iOS and web apps:
Configure your API key in the <application>
tag of your App Manifest file (usually in src/main/AndroidManifest.xml
):
<application ...>
<meta-data android:name="com.bugsnag.android.API_KEY"
android:value="your-api-key-here"/>
</application>
You can find your API key in your project’s settings (shortcut: g
s
) in the dashboard.
Initialize BugSnag in the onCreate
callback of your Application subclass using the common startBugsnag
function and the Configuration
class from the bugsnag-kmp
package:
import com.bugsnag.kmp.Configuration
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
startBugsnag(Configuration(this))
}
}
Don’t accidentally import com.bugsnag.android.Configuration
if you want common configuration
Configure your API key by adding a bugsnag
Dictionary to your Info.plist
file:
Or in XML:
<key>bugsnag</key>
<dict>
<key>apiKey</key>
<string>YOUR-API-KEY</string>
</dict>
You can find your API key in your project’s settings (shortcut: g
s
) in the dashboard.
Initialize BugSnag in the didFinishLaunchingWithOptions
method of your AppDelegate class, or in the init
method of your App
class:
@main
struct iOSApp: App {
init() {
BugsnagStartupKt.startBugsnag(
configuration: Bugsnag_kmpConfiguration())
}
}
Initialize BugSnag as early as possible in your web apps:
startBugsnag(Configuration("your-api-key-here"))
In order to see the original method names, file paths and line numbers in the stacktraces that are reported on your dashboard, certain symbol and mapping files need to be uploaded for each of your builds.
To upload these files, we recommend using the bugsnag-cli tool. This will attempt to locate and upload the appropriate symbol files for each platform from your Kotlin Multiplatform project and can be added to your CI/CD pipeline:
bugsnag-cli upload android-aab app
bugsnag-cli upload xcode-archive iosApp
bugsnag-cli upload jsApp --api-key=YOUR_API_KEY --base-url="https://example.com/js"
Each CLI command can be customized with configuration options to suit the layout of your project. See the upload reference documentation for each command for more information.
After completing installation and basic configuration, crashes will be reported and automatically appear on your BugSnag dashboard.
If you would like to send handled exceptions to BugSnag, you can pass any Throwable
object to the Bugsnag.notify
method:
Bugsnag.notify(Throwable("Something went wrong"))
It can often be helpful to adjust the severity or attach custom diagnostics to handled errors. This can be achieved by passing an OnErrorCallback
as an argument to notify
.
The callback receives an Event
object as a parameter which can be used to add or amend the data sent to your BugSnag dashboard. You can also return false
from the callback to prevent the event being sent at all:
Bugsnag.notify(exception, { event ->
// Add extra information
event.addMetadata("account", "name", "Acme Co.")
event.addMetadata("account", "paying_customer", true)
// Increase severity
event.severity = Severity.ERROR
// Return `false` if you'd like to stop this error being reported
true
})
BugSnag will automatically capture and attach the following diagnostic data to every error report:
For more information see the native platform guides for Android, iOS and JavaScript.
It can often be helpful to attach application-specific diagnostic data to error reports. This can be accomplished by setting a callback which will be invoked before any reports are sent to BugSnag:
val configuration = Configuration()
configuration.addOnSendError { event ->
event.addMetadata("account", "name", "Acme Co.")
event.addMetadata("account", "paying_customer", true)
return true
}
In order to correlate errors with customer reports, or to see a list of users who experienced each error, it is helpful to capture and display user information. BugSnag includes helpers for attaching an identifier, email address and name to reports that will be searchable in the dashboard.
By default we will generate a unique ID and send this ID along with every error report from an individual device. If you would like to override this identifier you can set the user ID property.
Bugsnag.setUser("3", "bugs.nag@bugsnag.com", "Bugs Nag")
In order to understand what happened in your application before each error, it can be helpful to leave short log statements that we call breadcrumbs. A configurable number of breadcrumbs are attached to each error report to help diagnose what events led to the error.
By default, BugSnag captures some common events automatically.
For more information see the native platform guides for Android, iOS and JavaScript.
You can use the leaveBreadcrumb
method to log potentially useful events in your own applications:
Bugsnag.leaveBreadcrumb("User clicked a button")
BugSnag will keep track of the time and order of the breadcrumbs and show them on your dashboard.
Additional data can also be attached to breadcrumbs by providing the optional type
and metadata
parameters:
val metadata = mapOf(
"from" to "moka",
"to" to "french press"
)
Bugsnag.leaveBreadcrumb("Preference updated", metadata, BreadcrumbType.STATE)
The BugSnag SDK tracks the number of “sessions” that happen within your application. This allows you to compare stability scores between releases on your dashboard and helps you to understand the quality of your releases.
BugSnag will automatically report a session each time the app is launched or enters the foreground after being in the background for at least 30 seconds.
If you want control over what is deemed a session, you can switch off automatic session tracking with the autoTrackSessions
option, and manage the session lifecycle using startSession
, pauseSession
and resumeSession
on the Bugsnag
client.
Bugsnag.startSession()
Monitor errors as you roll out features or run experiments and A/B tests by declaring your feature flag and experiment usage in the BugSnag SDK. You can use the Features dashboard to identify whether these features have introduced errors into your app.
Bugsnag.addFeatureFlag("Checkout button color", "Blue")
Bugsnag.addFeatureFlag("New checkout flow")
By default BugSnag will identify crashes that occur whilst your app is launching, allowing you to prioritize fixing high-impact launch crashes.
Additionally you can use BugSnag to detect recurrent launch crashes: allowing you to take evasive action in your app, such as resetting data or turning off application features.
By default, BugSnag will treat crashes that occur during the first 5 seconds after calling Bugsnag.start()
as having occurred during launch. You can modify the launch time period using the launchDurationMillis
configuration option.
If the previous run of your app crashed during app launch, Bugsnag.start()
will block the calling thread for up to 2 seconds to allow the crash report to be sent before the app continues launching. In cases where a launch crash is persistent, this improves the reliability of crash reporting.
After a launch crash, it may be appropriate to take some actions in your app, such as removing cached data or resetting some persistent state, to make another one less likely to occur.
if (Bugsnag.getLastRunInfo()?.crashedDuringLaunch == true) {
// Enable "safe mode"
}