From f0e551a9f1c9b0ed7e3cddae4ab377f30fa1846a Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 1 Dec 2025 19:11:45 +0100 Subject: [PATCH 1/9] Update --- .../nsexception/SentryUnhandledExceptions.kt | 24 ++++++++++++++----- .../cinterop/Sentry.Internal.def | 2 +- .../cinterop/SentryInternal/SentryCrash.h | 8 +++++++ .../SentryDependencyContainer.h | 3 +++ 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt index 047ca6b2..6238814e 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt @@ -16,6 +16,7 @@ package io.sentry.kotlin.multiplatform.nsexception import Internal.Sentry.NSExceptionKt_SentryCrashStackCursorFromNSException import Internal.Sentry.kSentryLevelFatal +import kotlinx.cinterop.invoke import platform.Foundation.NSException import platform.Foundation.NSNumber @@ -54,12 +55,23 @@ internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentry * @see wrapUnhandledExceptionHook */ public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook { throwable -> - val envelope = throwable.asSentryEnvelope() - // The envelope will be persisted, so we can safely terminate afterwards. - // https://github.com/getsentry/sentry-cocoa/blob/678172142ac1d10f5ed7978f69d16ab03e801057/Sources/Sentry/SentryClient.m#L409 - InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) - CocoapodsSentrySDK.configureScope { scope -> - scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) + // Get the crash reporter and its exception handler + val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter + val handler = crashReporter.uncaughtExceptionHandler + + if (handler != null) { + // This will: + // 1. Write a crash report to disk with ALL synced scope data + // 2. Include tags, user, context, breadcrumbs, etc. + // 3. The crash will be sent on next app launch + handler.invoke(throwable.asNSException()) + } else { + // Fallback to current approach if handler not available + val envelope = throwable.asSentryEnvelope() + InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) + CocoapodsSentrySDK.configureScope { scope -> + scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG) + } } } diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.Internal.def b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.Internal.def index 03d115d4..c48f354e 100644 --- a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.Internal.def +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.Internal.def @@ -2,4 +2,4 @@ language = Objective-C headers = SentryClient.h SentryEvent.h SentryDebugImageProvider.h SentryHub.h SentryScope.h \ SentryCrashMonitor_NSException.h SentryCrashMonitor_NSException+NSExceptionKt.h \ SentryCrashStackCursor.h SentryDependencyContainer.h SentryHook.h SentrySDKInternal.h \ - SentryStacktraceBuilder.h SentryThreadInspector.h PrivateSentrySDKOnly.h \ + SentryStacktraceBuilder.h SentryThreadInspector.h PrivateSentrySDKOnly.h SentryCrash.h \ diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h new file mode 100644 index 00000000..2159a6c7 --- /dev/null +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h @@ -0,0 +1,8 @@ +// SentryCrash interface - expose the uncaughtExceptionHandler +// Based on: https://github.com/getsentry/sentry-cocoa/blob/main/Sources/Sentry/include/SentryCrash.h + +@interface SentryCrash : NSObject + +@property (nonatomic, assign, nullable) NSUncaughtExceptionHandler *uncaughtExceptionHandler; + +@end \ No newline at end of file diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h index 0c58c825..710b32c9 100644 --- a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h @@ -18,11 +18,14 @@ #import #import +#import @interface SentryDependencyContainer : NSObject + (nonnull instancetype)sharedInstance; @property (nonatomic, strong, nonnull) SentryDebugImageProvider *debugImageProvider; +@property (nonatomic, strong, nonnull) SentryCrash *crashReporter; @end + From 4617e8c70307e467b71ad1a6e680d2e1edb1b49c Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 1 Dec 2025 19:12:24 +0100 Subject: [PATCH 2/9] Update --- .../src/nativeInterop/cinterop/SentryInternal/SentryCrash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h index 2159a6c7..e502a4bd 100644 --- a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryCrash.h @@ -5,4 +5,4 @@ @property (nonatomic, assign, nullable) NSUncaughtExceptionHandler *uncaughtExceptionHandler; -@end \ No newline at end of file +@end From 32f05edbd785322cb47da8101218b0f647b9fecc Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 1 Dec 2025 19:12:55 +0100 Subject: [PATCH 3/9] Update --- .../multiplatform/nsexception/SentryUnhandledExceptions.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt index 6238814e..c84855ff 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt @@ -55,7 +55,6 @@ internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentry * @see wrapUnhandledExceptionHook */ public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook { throwable -> - // Get the crash reporter and its exception handler val crashReporter = InternalSentryDependencyContainer.sharedInstance().crashReporter val handler = crashReporter.uncaughtExceptionHandler From 7122b2a0a8c099bd2ffe37e95f0af75ea36d0b26 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 1 Dec 2025 19:21:05 +0100 Subject: [PATCH 4/9] Update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2988586b..cc9d718c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Improve iOS crash reports by adding scope data ([#491](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/491)) + ### Dependencies - Bump Java SDK from v8.25.0 to v8.27.1 ([#487](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/487)) From 4b38561037f9d61fbbb4796de6e84375a881cf36 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 1 Dec 2025 19:44:59 +0100 Subject: [PATCH 5/9] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc9d718c..9d7c76b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Improve iOS crash reports by adding scope data ([#491](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/491)) + - ⚠️ This change will most likely affect issue grouping ### Dependencies From f2c2ed0c0c9582ca95cb2e1f3650c9ce323b427d Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 2 Dec 2025 12:57:18 +0100 Subject: [PATCH 6/9] Update CHANGELOG.md Co-authored-by: Roman Zavarnitsyn --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d7c76b3..6f3c187e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features - Improve iOS crash reports by adding scope data ([#491](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/491)) - - ⚠️ This change will most likely affect issue grouping + - ⚠️ This change will most likely affect issue grouping as Sentry now properly symbolicates Kotlin iOS exceptions ### Dependencies From 82fc50ad6ad53073d178e0cac2d49d2bdccd3305 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 3 Dec 2025 01:05:02 +0100 Subject: [PATCH 7/9] set appendCausedBy to true by default when handling ios crashes --- .../multiplatform/nsexception/SentryUnhandledExceptions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt index c84855ff..1039b2bc 100644 --- a/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt +++ b/sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt @@ -63,9 +63,9 @@ public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook // 1. Write a crash report to disk with ALL synced scope data // 2. Include tags, user, context, breadcrumbs, etc. // 3. The crash will be sent on next app launch - handler.invoke(throwable.asNSException()) + handler.invoke(throwable.asNSException(appendCausedBy = true)) } else { - // Fallback to current approach if handler not available + // Fallback to old approach if handler not available val envelope = throwable.asSentryEnvelope() InternalSentrySDK.storeEnvelope(envelope as objcnames.classes.SentryEnvelope) CocoapodsSentrySDK.configureScope { scope -> From 6f06f85001fcf8cccbc95ecf18cca2b36fd4f895 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 3 Dec 2025 16:18:06 +0100 Subject: [PATCH 8/9] Update CHANGELOG for iOS crash reports and SDK bump --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3c187e..eafdab16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features - Improve iOS crash reports by adding scope data ([#491](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/491)) - - ⚠️ This change will most likely affect issue grouping as Sentry now properly symbolicates Kotlin iOS exceptions + - ⚠️ This change will most likely affect issue grouping as Sentry now properly symbolicates Kotlin iOS crashes ### Dependencies From e845bb3be94e8f5a42b3451399521b0fe8ee7f5e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 3 Dec 2025 16:18:23 +0100 Subject: [PATCH 9/9] Update SentryDependencyContainer.h --- .../cinterop/SentryInternal/SentryDependencyContainer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h index 710b32c9..ed227812 100644 --- a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryInternal/SentryDependencyContainer.h @@ -28,4 +28,3 @@ @property (nonatomic, strong, nonnull) SentryCrash *crashReporter; @end -