diff --git a/CHANGELOG.md b/CHANGELOG.md index 4da6dc17..7e9f0c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### Features -- Improve Objc/Swift experience with @HiddenFromObjc ([#62](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/62)) +- feat: configuring http client errors for Apple targets ([#76](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/76)) +- feat: improve Objc/Swift experience with @HiddenFromObjc ([#62](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/62)) - feat: add view hierarchy ([#53](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/53)) ### Fixes diff --git a/sentry-kotlin-multiplatform/src/commonAppleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt b/sentry-kotlin-multiplatform/src/commonAppleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt index 15c9916b..3268eab5 100644 --- a/sentry-kotlin-multiplatform/src/commonAppleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt +++ b/sentry-kotlin-multiplatform/src/commonAppleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt @@ -2,6 +2,7 @@ package io.sentry.kotlin.multiplatform.extensions import PrivateSentrySDKOnly.Sentry.PrivateSentrySDKOnly import cocoapods.Sentry.SentryEvent +import cocoapods.Sentry.SentryHttpStatusCodeRange import io.sentry.kotlin.multiplatform.BuildKonfig import io.sentry.kotlin.multiplatform.CocoaSentryOptions import io.sentry.kotlin.multiplatform.SentryOptions @@ -59,4 +60,13 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(options: SentryOptions) { cocoaBreadcrumb?.toKmpBreadcrumb() ?.let { options.beforeBreadcrumb?.invoke(it) }?.toCocoaBreadcrumb() } + + enableCaptureFailedRequests = options.enableCaptureFailedRequests + failedRequestTargets = options.failedRequestTargets + failedRequestStatusCodes = options.failedRequestStatusCodes.map { + SentryHttpStatusCodeRange( + min = it.min.convert(), + max = it.max.convert() + ) + } } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt new file mode 100644 index 00000000..b96a889c --- /dev/null +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/HttpStatusCodeRange.kt @@ -0,0 +1,21 @@ +package io.sentry.kotlin.multiplatform + +/** + * The Http status code range. Example for a range: 400 to 499, 500 to 599, 400 to 599 The range is + * inclusive so the min and max is considered part of the range. + * + * Example for a single status code 400, 500 + */ +public data class HttpStatusCodeRange(val min: Int = DEFAULT_MIN, val max: Int = DEFAULT_MAX) { + + public constructor(statusCode: Int) : this(statusCode, statusCode) + + public fun isInRange(statusCode: Int): Boolean { + return statusCode in min..max + } + + public companion object { + public const val DEFAULT_MIN: Int = 500 + public const val DEFAULT_MAX: Int = 599 + } +} diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryOptions.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryOptions.kt index 0a8faa83..015cc3b7 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryOptions.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryOptions.kt @@ -72,4 +72,28 @@ public open class SentryOptions { * This is only available on iOS and Android. */ public var attachViewHierarchy: Boolean = false + + /** + * Enables or disables the feature to automatically capture HTTP client errors. + * This is enabled by default. + * + * Available on Apple. + */ + public var enableCaptureFailedRequests: Boolean = true + + /** + * A list of HTTP status code ranges indicating which client errors should be captured as errors. + * By default, only HTTP client errors with a response code between 500 and 599 are captured as errors. + * + * Available on Apple. + */ + public var failedRequestStatusCodes: List = listOf(HttpStatusCodeRange()) + + /** + * A list of HTTP request targets indicating which client errors should be captured as errors with either regex or a plain string. + * By default, HTTP client errors from every target (.* regular expression) are automatically captured. + * + * Available on Apple. + */ + public var failedRequestTargets: List = listOf(".*") } diff --git a/sentry-samples/kmp-app/iosApp/iosApp/ContentView.swift b/sentry-samples/kmp-app/iosApp/iosApp/ContentView.swift index d35c002a..ec6ad541 100644 --- a/sentry-samples/kmp-app/iosApp/iosApp/ContentView.swift +++ b/sentry-samples/kmp-app/iosApp/iosApp/ContentView.swift @@ -11,6 +11,9 @@ struct ContentView: View { Button("Capture Exception") { LoginImpl().login(username: "MyUsername") } + Button("Capture Http Client Error") { + HttpClientKt.captureHttpClientError() + } Button("Hard Crash") { LoginImpl().login(username: nil) } diff --git a/sentry-samples/kmp-app/shared/src/commonMain/kotlin/sample.kmp.app/AppSetup.kt b/sentry-samples/kmp-app/shared/src/commonMain/kotlin/sample.kmp.app/AppSetup.kt index 37e05517..24515ee2 100644 --- a/sentry-samples/kmp-app/shared/src/commonMain/kotlin/sample.kmp.app/AppSetup.kt +++ b/sentry-samples/kmp-app/shared/src/commonMain/kotlin/sample.kmp.app/AppSetup.kt @@ -2,6 +2,7 @@ package sample.kmp.app import io.sentry.kotlin.multiplatform.Attachment import io.sentry.kotlin.multiplatform.Context +import io.sentry.kotlin.multiplatform.HttpStatusCodeRange import io.sentry.kotlin.multiplatform.OptionsConfiguration import io.sentry.kotlin.multiplatform.Sentry @@ -45,6 +46,8 @@ private fun optionsConfiguration(): OptionsConfiguration { it.attachScreenshot = true it.attachViewHierarchy = true it.release = "kmp-release@0.0.1" + it.failedRequestStatusCodes = listOf(HttpStatusCodeRange(400, 599)) + it.failedRequestTargets = listOf("httpbin.org") it.beforeBreadcrumb = { breadcrumb -> breadcrumb.message = "Add message before every breadcrumb" breadcrumb diff --git a/sentry-samples/kmp-app/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt b/sentry-samples/kmp-app/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt new file mode 100644 index 00000000..b63d03af --- /dev/null +++ b/sentry-samples/kmp-app/shared/src/iosMain/kotlin/sample.kmp.app/HttpClient.kt @@ -0,0 +1,21 @@ +package sample.kmp.app + +import platform.Foundation.NSURL +import platform.Foundation.NSURLRequest +import platform.Foundation.NSURLSession +import platform.Foundation.dataTaskWithRequest + +@Suppress("Unused") // Called from Swift +fun captureHttpClientError() { + val url = NSURL(string = "https://httpbin.org/status/404") + val request = NSURLRequest(uRL = url) + NSURLSession.sharedSession.dataTaskWithRequest(request) { data, response, error -> + if (error != null) { + // handle error + println("error: $error") + } else { + // handle successful response + println("response: $response") + } + }.resume() +}