Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

### 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 crashes

### Dependencies

- Bump Java SDK from v8.25.0 to v8.27.1 ([#487](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/487))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -54,12 +55,22 @@ 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)
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(appendCausedBy = true))
} else {
// Fallback to old 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)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@

#import <Foundation/Foundation.h>
#import <SentryDebugImageProvider.h>
#import <SentryCrash.h>

@interface SentryDependencyContainer : NSObject

+ (nonnull instancetype)sharedInstance;

@property (nonatomic, strong, nonnull) SentryDebugImageProvider *debugImageProvider;
@property (nonatomic, strong, nonnull) SentryCrash *crashReporter;

@end