Skip to content

Commit e178b2e

Browse files
buenaflorromtsn
andauthored
refactor: improve interop with objc headers (#265)
* update headers * update * Update * Update sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com> --------- Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
1 parent 5eed211 commit e178b2e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+115
-536
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Improvements
66

7+
- Improve interop with objc headers ([#265](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/265))
78
- Plugin: dont use `latest.release` as default for the KMP dependency ([#262](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/262))
89

910
### Dependencies

sentry-kotlin-multiplatform/build.gradle.kts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,8 @@ kotlin {
177177
macosArm64()
178178
).forEach {
179179
it.compilations.getByName("main") {
180-
cinterops.create("Sentry.NSException") {
181-
includeDirs("$projectDir/src/nativeInterop/cinterop/SentryNSException")
182-
}
183-
cinterops.create("Sentry.Scope") {
184-
includeDirs("$projectDir/src/nativeInterop/cinterop/SentryScope")
185-
}
186-
cinterops.create("Sentry.PrivateSentrySDKOnly") {
187-
includeDirs("$projectDir/src/nativeInterop/cinterop/SentryPrivateSentrySDKOnly")
180+
cinterops.create("Sentry.Internal") {
181+
includeDirs("$projectDir/src/nativeInterop/cinterop/SentryInternal")
188182
}
189183
}
190184
}

sentry-kotlin-multiplatform/sentry_kotlin_multiplatform.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ Pod::Spec.new do |spec|
5050
}
5151
]
5252

53-
end
53+
end

sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/CocoaScopeProvider.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ import io.sentry.kotlin.multiplatform.extensions.toKmpUser
88
import io.sentry.kotlin.multiplatform.extensions.toMutableMap
99
import io.sentry.kotlin.multiplatform.protocol.Breadcrumb
1010
import io.sentry.kotlin.multiplatform.protocol.User
11-
import Scope.Sentry.SentryScope as PrivateCocoaScope
1211

1312
internal class CocoaScopeProvider(private val scope: CocoaScope) : Scope {
14-
1513
/*
1614
This bridge exposes private Cocoa SDK API to fetch internal properties such as user, level, etc.
1715
We need this in order to return properties because the Cocoa SDK doesn't implement getters.
1816
This is only used for get methods.
1917
*/
20-
private val privateScope = scope as? PrivateCocoaScope
18+
private val privateScope = scope as? Internal.Sentry.SentryScope
2119

2220
override var level: SentryLevel?
2321
set(value) {

sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/SentryBridge.apple.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.sentry.kotlin.multiplatform
22

3-
import NSException.Sentry.SentryEvent
4-
import PrivateSentrySDKOnly.Sentry.PrivateSentrySDKOnly
3+
import Internal.Sentry.PrivateSentrySDKOnly
54
import cocoapods.Sentry.SentrySDK
65
import io.sentry.kotlin.multiplatform.extensions.toCocoaBreadcrumb
76
import io.sentry.kotlin.multiplatform.extensions.toCocoaUser
@@ -38,7 +37,7 @@ internal actual fun SentryPlatformOptions.prepareForInit() {
3837
sdk["packages"] = packages
3938
event?.sdk = sdk
4039

41-
dropKotlinCrashEvent(event as SentryEvent?) as CocoaSentryEvent?
40+
dropKotlinCrashEvent(event)
4241
}
4342

4443
cocoa?.setBeforeSend(modifiedBeforeSend)

sentry-kotlin-multiplatform/src/appleMain/kotlin/io/sentry/kotlin/multiplatform/nsexception/SentryUnhandledExceptions.kt

Lines changed: 61 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,37 @@
1414

1515
package io.sentry.kotlin.multiplatform.nsexception
1616

17-
import NSException.Sentry.NSExceptionKt_SentryCrashStackCursorFromNSException
18-
import NSException.Sentry.NSExceptionKt_SentryMechanismSetNotHandled
19-
import NSException.Sentry.NSExceptionKt_SentryThreadSetCrashed
20-
import NSException.Sentry.SentryDependencyContainer
21-
import NSException.Sentry.SentryEnvelope
22-
import NSException.Sentry.SentryEnvelopeHeader
23-
import NSException.Sentry.SentryEnvelopeItem
24-
import NSException.Sentry.SentryEvent
25-
import NSException.Sentry.SentryException
26-
import NSException.Sentry.SentryMechanism
27-
import NSException.Sentry.SentrySDK
28-
import NSException.Sentry.SentryThread
29-
import NSException.Sentry.SentryThreadInspector
30-
import NSException.Sentry.currentHub
31-
import NSException.Sentry.isCrashEvent
32-
import NSException.Sentry.kSentryLevelFatal
33-
import NSException.Sentry.prepareEvent
34-
import NSException.Sentry.storeEnvelope
35-
import NSException.Sentry.threadInspector
17+
import Internal.Sentry.NSExceptionKt_SentryCrashStackCursorFromNSException
18+
import Internal.Sentry.kSentryLevelFatal
3619
import platform.Foundation.NSException
3720
import platform.Foundation.NSNumber
3821

22+
private typealias InternalSentryEvent = Internal.Sentry.SentryEvent
23+
private typealias InternalSentrySDK = Internal.Sentry.SentrySDK
24+
private typealias InternalSentryEnvelope = Internal.Sentry.SentryEnvelope
25+
private typealias InternalSentryDependencyContainer = Internal.Sentry.SentryDependencyContainer
26+
private typealias InternalSentryEnvelopeHeader = Internal.Sentry.SentryEnvelopeHeader
27+
private typealias InternalSentryEnvelopeItem = Internal.Sentry.SentryEnvelopeItem
28+
private typealias InternalSentryThreadInspector = Internal.Sentry.SentryThreadInspector
29+
30+
private typealias CocoapodsSentryEvent = cocoapods.Sentry.SentryEvent
31+
private typealias CocoapodsSentrySDK = cocoapods.Sentry.SentrySDK
32+
private typealias CocoapodsSentryStacktrace = cocoapods.Sentry.SentryStacktrace
33+
private typealias CocoapodsSentryException = cocoapods.Sentry.SentryException
34+
private typealias CocoapodsSentryMechanism = cocoapods.Sentry.SentryMechanism
35+
private typealias CocoapodsSentryThread = cocoapods.Sentry.SentryThread
36+
3937
/**
4038
* Drops the Kotlin crash that follows an unhandled Kotlin exception except our custom SentryEvent.
4139
*/
42-
internal fun dropKotlinCrashEvent(event: SentryEvent?): SentryEvent? {
43-
return event?.takeUnless { it.isCrashEvent && (it.tags?.containsKey(KOTLIN_CRASH_TAG) ?: false) }
40+
internal fun dropKotlinCrashEvent(event: CocoapodsSentryEvent?): CocoapodsSentryEvent? {
41+
return event?.takeUnless {
42+
(it as InternalSentryEvent).isCrashEvent && (
43+
it.tags?.containsKey(
44+
KOTLIN_CRASH_TAG
45+
) ?: false
46+
)
47+
}
4448
}
4549

4650
/**
@@ -53,8 +57,8 @@ public fun setSentryUnhandledExceptionHook(): Unit = wrapUnhandledExceptionHook
5357
val envelope = throwable.asSentryEnvelope()
5458
// The envelope will be persisted, so we can safely terminate afterwards.
5559
// https://github.com/getsentry/sentry-cocoa/blob/678172142ac1d10f5ed7978f69d16ab03e801057/Sources/Sentry/SentryClient.m#L409
56-
SentrySDK.storeEnvelope(envelope)
57-
SentrySDK.configureScope { scope ->
60+
InternalSentrySDK.storeEnvelope(envelope)
61+
CocoapodsSentrySDK.configureScope { scope ->
5862
scope?.setTagValue(KOTLIN_CRASH_TAG, KOTLIN_CRASH_TAG)
5963
}
6064
}
@@ -67,56 +71,60 @@ internal const val KOTLIN_CRASH_TAG = "nsexceptionkt.kotlin_crashed"
6771
/**
6872
* Converts `this` [Throwable] to a [SentryEnvelope].
6973
*/
70-
internal fun Throwable.asSentryEnvelope(): SentryEnvelope {
71-
val event = asSentryEvent()
72-
val preparedEvent = SentrySDK.currentHub().let { hub ->
73-
hub.getClient()?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isCrashEvent = true)
74+
internal fun Throwable.asSentryEnvelope(): InternalSentryEnvelope {
75+
val event = asSentryEvent() as InternalSentryEvent
76+
val preparedEvent = InternalSentrySDK.currentHub().let { hub ->
77+
hub.getClient()
78+
?.prepareEvent(event, hub.scope, alwaysAttachStacktrace = false, isCrashEvent = true)
7479
} ?: event
75-
val item = SentryEnvelopeItem(preparedEvent)
80+
val item = InternalSentryEnvelopeItem(preparedEvent)
7681
// TODO: pass traceState when enabling performance monitoring for KMP SDK
77-
val header = SentryEnvelopeHeader(preparedEvent.eventId, null)
78-
return SentryEnvelope(header, listOf(item))
82+
val header = InternalSentryEnvelopeHeader(preparedEvent.eventId, null)
83+
return InternalSentryEnvelope(header, listOf(item))
7984
}
8085

8186
/**
8287
* Converts `this` [Throwable] to a [SentryEvent].
8388
*/
8489
@Suppress("UnnecessaryOptInAnnotation")
85-
private fun Throwable.asSentryEvent(): SentryEvent = SentryEvent(kSentryLevelFatal).apply {
86-
isCrashEvent = true
87-
@Suppress("UNCHECKED_CAST")
88-
val threads = threadInspector?.getCurrentThreadsWithStackTrace() as List<SentryThread>?
89-
this.threads = threads
90-
val currentThread = threads?.firstOrNull { it.current?.boolValue ?: false }?.apply {
91-
NSExceptionKt_SentryThreadSetCrashed(this)
92-
// Crashed threats shouldn't have a stacktrace, the thread_id should be set on the exception instead
93-
// https://develop.sentry.dev/sdk/event-payloads/threads/
94-
stacktrace = null
90+
private fun Throwable.asSentryEvent(): CocoapodsSentryEvent =
91+
CocoapodsSentryEvent(kSentryLevelFatal).apply {
92+
@Suppress("UNCHECKED_CAST")
93+
val threads =
94+
threadInspector?.getCurrentThreadsWithStackTrace() as List<CocoapodsSentryThread>?
95+
this.threads = threads
96+
val currentThread = threads?.firstOrNull { it.current?.boolValue ?: false }?.apply {
97+
setCrashed(NSNumber(true))
98+
// Crashed threads shouldn't have a stacktrace, the thread_id should be set on the exception instead
99+
// https://develop.sentry.dev/sdk/event-payloads/threads/
100+
stacktrace = null
101+
}
102+
debugMeta = threads?.let {
103+
InternalSentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads(
104+
it
105+
)
106+
}
107+
exceptions = this@asSentryEvent
108+
.let { throwable -> throwable.causes.asReversed() + throwable }
109+
.map { it.asNSException().asSentryException(currentThread?.threadId) }
95110
}
96-
debugMeta = threads?.let {
97-
SentryDependencyContainer.sharedInstance().debugImageProvider.getDebugImagesForThreads(it)
98-
}
99-
exceptions = this@asSentryEvent
100-
.let { throwable -> throwable.causes.asReversed() + throwable }
101-
.map { it.asNSException().asSentryException(currentThread?.threadId) }
102-
}
103111

104112
/**
105113
* Converts `this` [NSException] to a [SentryException].
106114
*/
107115
private fun NSException.asSentryException(
108116
threadId: NSNumber?
109-
): SentryException = SentryException(reason ?: "", name ?: "Throwable").apply {
117+
): CocoapodsSentryException = CocoapodsSentryException(reason ?: "", name ?: "Throwable").apply {
110118
this.threadId = threadId
111-
mechanism = SentryMechanism("generic").apply {
112-
NSExceptionKt_SentryMechanismSetNotHandled(this)
119+
mechanism = CocoapodsSentryMechanism("generic").apply {
120+
setHandled(NSNumber(false))
113121
}
114122
stacktrace = threadInspector?.stacktraceBuilder?.let { stacktraceBuilder ->
115123
val cursor = NSExceptionKt_SentryCrashStackCursorFromNSException(this@asSentryException)
116124
val stacktrace = stacktraceBuilder.retrieveStacktraceFromCursor(cursor)
117-
stacktrace
125+
stacktrace as CocoapodsSentryStacktrace
118126
}
119127
}
120128

121-
private val threadInspector: SentryThreadInspector?
122-
get() = SentrySDK.currentHub().getClient()?.threadInspector
129+
private val threadInspector: InternalSentryThreadInspector?
130+
get() = InternalSentrySDK.currentHub().getClient()?.threadInspector

sentry-kotlin-multiplatform/src/appleTest/kotlin/io/sentry/kotlin/multiplatform/SentryBridgeTest.apple.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.sentry.kotlin.multiplatform
22

3-
import PrivateSentrySDKOnly.Sentry.PrivateSentrySDKOnly
3+
import Internal.Sentry.PrivateSentrySDKOnly
44
import io.sentry.kotlin.multiplatform.fakes.FakeSentryInstance
55
import io.sentry.kotlin.multiplatform.utils.fakeDsn
66
import kotlin.test.BeforeTest
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language = Objective-C
2+
headers = SentryClient.h SentryDebugImageProvider.h SentryEnvelope.h \ SentryHub.h SentryScope.h \
3+
SentryCrashMonitor_NSException.h SentryCrashMonitor_NSException+NSExceptionKt.h \
4+
SentryCrashStackCursor.h SentryDependencyContainer.h SentryHook.h SentrySDK.h \
5+
SentryStacktraceBuilder.h SentryThreadInspector.h PrivateSentrySDKOnly.h \

sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.NSException.def

Lines changed: 0 additions & 7 deletions
This file was deleted.

sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.PrivateSentrySDKOnly.def

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)