diff --git a/build.gradle.kts b/build.gradle.kts index dc60e227..6a3ccb15 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,10 +9,11 @@ plugins { kotlin(Config.cocoapods).version(Config.kotlinVersion).apply(false) id(Config.jetpackCompose).version(Config.composeVersion).apply(false) id(Config.androidGradle).version(Config.agpVersion).apply(false) + id(Config.BuildPlugins.buildConfig).version(Config.BuildPlugins.buildConfigVersion).apply(false) } allprojects { - group = "io.sentry" + group = Config.Sentry.group version = properties["versionName"].toString() } diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 9a958203..fdff7da3 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -10,6 +10,11 @@ object Config { val gradleMavenPublishPlugin = "com.vanniktech.maven.publish" val androidGradle = "com.android.library" + object BuildPlugins { + val buildConfig = "com.codingfeline.buildkonfig" + val buildConfigVersion = "0.13.3" + } + object QualityPlugins { val spotless = "com.diffplug.spotless" val spotlessVersion = "6.11.0" @@ -22,7 +27,7 @@ object Config { val sentryAndroid = "io.sentry:sentry-android:$sentryJavaVersion" val sentryJava = "io.sentry:sentry:$sentryJavaVersion" - val sentryCocoaVersion = "~> 8.2.0" + val sentryCocoaVersion = "8.2.0" val sentryCocoa = "Sentry" } @@ -46,4 +51,14 @@ object Config { val tvosDeploymentTarget = "11.0" val watchosDeploymentTarget = "4.0" } + + object Sentry { + val kotlinMultiplatformSdkName = "sentry.kotlin.kmp" + val javaPackageName = "maven:io.sentry:sentry" + val androidPackageName = "maven:io.sentry:sentry-android" + val cocoaPackageName = "cocoapods:sentry-cocoa" + val group = "io.sentry" + val description = "SDK for sentry.io" + val versionNameProp = "versionName" + } } diff --git a/gradle.properties b/gradle.properties index 57b0149a..e1ce4fdd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,13 +17,8 @@ versionName=0.0.1 # Increase memory for in-process compiler execution. org.gradle.jvmargs=-Xmx3g -# Because of: Please try to disable compiler caches and rerun the build. To disable compiler caches, add the following line to the gradle.properties file in the project's root directory -kotlin.native.cacheKind=none - # https://kotlinlang.org/docs/migrating-multiplatform-project-to-14.html#migrate-to-the-hierarchical-project-structure -kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.enableCompatibilityMetadataVariant=true -kotlin.native.enableDependencyPropagation=false kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.enableHierarchicalCommonization=true kotlin.mpp.androidSourceSetLayoutVersion=2 diff --git a/sentry-kotlin-multiplatform/build.gradle.kts b/sentry-kotlin-multiplatform/build.gradle.kts index 9c9fa604..093a562f 100644 --- a/sentry-kotlin-multiplatform/build.gradle.kts +++ b/sentry-kotlin-multiplatform/build.gradle.kts @@ -1,9 +1,11 @@ +import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { - kotlin("multiplatform") - kotlin("native.cocoapods") - id("com.android.library") + kotlin(Config.multiplatform) + kotlin(Config.cocoapods) + id(Config.androidGradle) + id(Config.BuildPlugins.buildConfig) `maven-publish` } @@ -80,7 +82,7 @@ kotlin { summary = "Official Sentry SDK Kotlin Multiplatform" homepage = "https://github.com/getsentry/sentry-kotlin-multiplatform" - pod(Config.Libs.sentryCocoa, Config.Libs.sentryCocoaVersion) + pod(Config.Libs.sentryCocoa, "~> ${Config.Libs.sentryCocoaVersion}") ios.deploymentTarget = Config.Cocoa.iosDeploymentTarget osx.deploymentTarget = Config.Cocoa.osxDeploymentTarget @@ -167,6 +169,9 @@ kotlin { cinterops.create("Sentry.Scope") { includeDirs("$projectDir/src/nativeInterop/cinterop/SentryScope") } + cinterops.create("Sentry.PrivateSentrySDKOnly") { + includeDirs("$projectDir/src/nativeInterop/cinterop/SentryPrivateSentrySDKOnly") + } } } @@ -179,3 +184,22 @@ kotlin { ) } } + +buildkonfig { + packageName = "io.sentry.kotlin.multiplatform" + defaultConfigs { + buildConfigField( + STRING, + "SENTRY_KOTLIN_MULTIPLATFORM_SDK_NAME", + Config.Sentry.kotlinMultiplatformSdkName + ) + buildConfigField(STRING, "VERSION_NAME", project.version.toString()) + buildConfigField(STRING, "SENTRY_JVM_PACKAGE_NAME", Config.Sentry.javaPackageName) + buildConfigField(STRING, "SENTRY_ANDROID_PACKAGE_NAME", Config.Sentry.androidPackageName) + buildConfigField(STRING, "SENTRY_COCOA_PACKAGE_NAME", Config.Sentry.cocoaPackageName) + + buildConfigField(STRING, "SENTRY_JVM_VERSION", Config.Libs.sentryJavaVersion) + buildConfigField(STRING, "SENTRY_ANDROID_VERSION", Config.Libs.sentryJavaVersion) + buildConfigField(STRING, "SENTRY_COCOA_VERSION", Config.Libs.sentryCocoaVersion) + } +} diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryAndroidOptionsExtensions.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryAndroidOptionsExtensions.kt index 263c11c2..6ab883f6 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryAndroidOptionsExtensions.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryAndroidOptionsExtensions.kt @@ -1,6 +1,7 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.android.core.SentryAndroidOptions +import io.sentry.kotlin.multiplatform.BuildKonfig import io.sentry.kotlin.multiplatform.SentryOptions internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = { @@ -9,4 +10,6 @@ internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptio // Apply Android specific options it.isAttachScreenshot = this.attachScreenshot + sdk.addPackage(BuildKonfig.SENTRY_ANDROID_PACKAGE_NAME, BuildKonfig.SENTRY_ANDROID_VERSION) + it.sdkVersion = sdk.toJvmSdkVersion() } 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 e051dfeb..1f0f8347 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 @@ -1,6 +1,8 @@ package io.sentry.kotlin.multiplatform.extensions +import PrivateSentrySDKOnly.Sentry.PrivateSentrySDKOnly import cocoapods.Sentry.SentryEvent +import io.sentry.kotlin.multiplatform.BuildKonfig import io.sentry.kotlin.multiplatform.CocoaSentryOptions import io.sentry.kotlin.multiplatform.SentryOptions import io.sentry.kotlin.multiplatform.nsexception.dropKotlinCrashEvent @@ -28,11 +30,29 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(options: SentryOptions) { this.enableAutoSessionTracking = options.enableAutoSessionTracking this.beforeSend = { event -> dropKotlinCrashEvent(event as NSExceptionSentryEvent?) as SentryEvent? + + val cocoaName = BuildKonfig.SENTRY_COCOA_PACKAGE_NAME + val cocoaVersion = BuildKonfig.SENTRY_COCOA_VERSION + options.sdk.apply { + val names = this.packages?.map { it.name } + if (names?.contains(cocoaName) != true) { + this.addPackage(cocoaName, cocoaVersion) + } + } + val sdk = event?.sdk?.toMutableMap() + sdk?.set( + "packages", + options.sdk.packages?.map { + mapOf("name" to it.name, "version" to it.version) + } + ) + event?.sdk = sdk + + event } + PrivateSentrySDKOnly.setSdkName(options.sdk.name, options.sdk.version) this.beforeBreadcrumb = { cocoaBreadcrumb -> - cocoaBreadcrumb - ?.toKmpBreadcrumb() - .apply { this?.let { options.beforeBreadcrumb?.invoke(it) } } - ?.toCocoaBreadcrumb() + cocoaBreadcrumb?.toKmpBreadcrumb() + .apply { this?.let { options.beforeBreadcrumb?.invoke(it) } }?.toCocoaBreadcrumb() } } diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SdkVersionExtensions.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SdkVersionExtensions.kt new file mode 100644 index 00000000..fa329f93 --- /dev/null +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SdkVersionExtensions.kt @@ -0,0 +1,12 @@ +package io.sentry.kotlin.multiplatform.extensions + +import io.sentry.kotlin.multiplatform.protocol.SdkVersion +import io.sentry.protocol.SdkVersion as JvmSdkVersion + +fun SdkVersion.toJvmSdkVersion(): JvmSdkVersion { + val sdk = JvmSdkVersion(this.name, this.version) + packages?.forEach { pkg -> + sdk.addPackage(pkg.name, pkg.version) + } + return sdk +} diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt index 69972757..8b36e9f1 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.kt @@ -1,10 +1,17 @@ package io.sentry.kotlin.multiplatform.extensions +import io.sentry.kotlin.multiplatform.BuildKonfig import io.sentry.kotlin.multiplatform.JvmSentryOptions import io.sentry.kotlin.multiplatform.SentryOptions internal fun SentryOptions.toJvmSentryOptionsCallback(): (JvmSentryOptions) -> Unit = { it.applyJvmBaseOptions(this) + + // Apply JVM specific options + this.sdk.apply { + addPackage(BuildKonfig.SENTRY_JVM_PACKAGE_NAME, BuildKonfig.SENTRY_JVM_VERSION) + } + it.sdkVersion = this.sdk.toJvmSdkVersion() } /** 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 290204ac..c0b5bee5 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 @@ -1,6 +1,7 @@ package io.sentry.kotlin.multiplatform import io.sentry.kotlin.multiplatform.protocol.Breadcrumb +import io.sentry.kotlin.multiplatform.protocol.SdkVersion open class SentryOptions { @@ -56,4 +57,7 @@ open class SentryOptions { /** Hook that is triggered before a breadcrumb is sent to Sentry */ var beforeBreadcrumb: ((Breadcrumb) -> Breadcrumb)? = null + + /** Information about the Sentry SDK that generated this event. */ + var sdk: SdkVersion = SdkVersion(BuildKonfig.SENTRY_KOTLIN_MULTIPLATFORM_SDK_NAME, BuildKonfig.VERSION_NAME) } diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt new file mode 100644 index 00000000..3a962678 --- /dev/null +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/protocol/SdkVersion.kt @@ -0,0 +1,25 @@ +package io.sentry.kotlin.multiplatform.protocol + +/** The SDK Interface describes the Sentry SDK and its configuration used to capture and transmit an event. */ +data class SdkVersion( + /** The name of the SDK. */ + val name: String, + + /** The version of the SDK. */ + val version: String +) { + /** Packages used by the SDK. */ + var packages: List? = mutableListOf() + private set + + fun addPackage(name: String, version: String) { + val mutableList = packages?.toMutableList() + mutableList?.add(Package(name, version)) + packages = mutableList + } +} + +data class Package( + val name: String, + val version: String +) diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.PrivateSentrySDKOnly.def b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.PrivateSentrySDKOnly.def new file mode 100644 index 00000000..44786412 --- /dev/null +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/Sentry.PrivateSentrySDKOnly.def @@ -0,0 +1,2 @@ +language = Objective-C +headers = PrivateSentrySDKOnly.h diff --git a/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryPrivateSentrySDKOnly/PrivateSentrySDKOnly.h b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryPrivateSentrySDKOnly/PrivateSentrySDKOnly.h new file mode 100644 index 00000000..1ff6bfed --- /dev/null +++ b/sentry-kotlin-multiplatform/src/nativeInterop/cinterop/SentryPrivateSentrySDKOnly/PrivateSentrySDKOnly.h @@ -0,0 +1,25 @@ +#import + +@interface PrivateSentrySDKOnly : NSObject + +/** + * Override SDK information. + */ ++ (void)setSdkName:(NSString *)sdkName andVersionString:(NSString *)versionString; + +/** + * Override SDK information. + */ ++ (void)setSdkName:(NSString *)sdkName; + +/** + * Retrieves the SDK name + */ ++ (NSString *)getSdkName; + +/** + * Retrieves the SDK version string + */ ++ (NSString *)getSdkVersionString; + +@end diff --git a/sentry-samples/kmp-app/shared/build.gradle.kts b/sentry-samples/kmp-app/shared/build.gradle.kts index 8aa4912f..32f9922a 100644 --- a/sentry-samples/kmp-app/shared/build.gradle.kts +++ b/sentry-samples/kmp-app/shared/build.gradle.kts @@ -19,7 +19,7 @@ kotlin { ios.deploymentTarget = "14.1" podfile = project.file("../iosApp/Podfile") - pod(Config.Libs.sentryCocoa, Config.Libs.sentryCocoaVersion) + pod(Config.Libs.sentryCocoa, "~> ${Config.Libs.sentryCocoaVersion}") framework { baseName = "shared"