feature: integrate Sentry SDK for crash reporting on Android and iOS
This commit is contained in:
@@ -32,3 +32,6 @@ data/resources/src/commonMain/composeResources/files/records.json
|
|||||||
keystore.properties
|
keystore.properties
|
||||||
*.jks
|
*.jks
|
||||||
*.keystore
|
*.keystore
|
||||||
|
|
||||||
|
# Secrets — see docs/sentry-glitchtip.md (the .example template stays versioned)
|
||||||
|
.sentryclirc
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
; Template for the local `.sentryclirc` used by sentry-cli to upload debug symbols
|
||||||
|
; to GlitchTip. Copy it to `.sentryclirc` at the repository root and fill in the token:
|
||||||
|
;
|
||||||
|
; cp .sentryclirc.example .sentryclirc
|
||||||
|
; chmod 600 .sentryclirc
|
||||||
|
;
|
||||||
|
; `.sentryclirc` is git-ignored and must never be committed — it holds a credential.
|
||||||
|
; See docs/sentry-glitchtip.md for the full procedure.
|
||||||
|
|
||||||
|
[auth]
|
||||||
|
; Created in GlitchTip under your user menu > Profile > Auth Tokens.
|
||||||
|
token=<your-glitchtip-auth-token>
|
||||||
|
|
||||||
|
[defaults]
|
||||||
|
url=https://eu.glitchtip.com/
|
||||||
|
org=kerlenn-sten-kidna
|
||||||
|
project=chom-bev-e-brezhoneg
|
||||||
@@ -93,6 +93,18 @@ See [Resource's README.md](data/resources/README.md) to handle the resource file
|
|||||||
audio files,
|
audio files,
|
||||||
and subtitles).
|
and subtitles).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Crash reporting — Sentry SDK on GlitchTip](./docs/sentry-glitchtip.md): DSN configuration,
|
||||||
|
`.sentryclirc` setup, and the iOS Archive procedure for uploading dSYM files.
|
||||||
|
|
||||||
|
## Crash reporting
|
||||||
|
|
||||||
|
Crashes are reported with the Sentry Kotlin Multiplatform SDK to a [GlitchTip](https://glitchtip.com)
|
||||||
|
instance. The DSN is read from `local.properties` and never committed, so a fresh clone builds and
|
||||||
|
runs with crash reporting disabled until you configure it. See
|
||||||
|
[docs/sentry-glitchtip.md](./docs/sentry-glitchtip.md).R
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
|
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
# Android app
|
# Android app
|
||||||
|
|
||||||
## Crash logging
|
|
||||||
|
|
||||||
GlitchTip is configured in the project. It uses the open source solution Senstry to log crashes
|
|
||||||
generated by the app and send them to GlitchTip on a European server.
|
|
||||||
|
|
||||||
## StrictMode (debug builds)
|
## StrictMode (debug builds)
|
||||||
|
|
||||||
The app enables Android [StrictMode](https://developer.android.com/reference/android/os/StrictMode)
|
The app enables Android [StrictMode](https://developer.android.com/reference/android/os/StrictMode)
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ dependencies {
|
|||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(libs.compose.uiToolingPreview)
|
implementation(libs.compose.uiToolingPreview)
|
||||||
debugImplementation(libs.compose.uiTooling)
|
debugImplementation(libs.compose.uiTooling)
|
||||||
|
|
||||||
// Crash logging
|
|
||||||
implementation(libs.glitchtips)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -55,10 +52,6 @@ android {
|
|||||||
.toInt()
|
.toInt()
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0.0-alpha02"
|
versionName = "1.0.0-alpha02"
|
||||||
|
|
||||||
// Crash-reporting DSN, kept out of the public repo: read from local.properties
|
|
||||||
// (glitchtip.dsn=...). Empty when absent, which disables the Sentry SDK.
|
|
||||||
manifestPlaceholders["glitchtipDsn"] = localProperty("glitchtip.dsn") ?: ""
|
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
@@ -76,12 +69,3 @@ android {
|
|||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reads a key from the root local.properties, or null when the file or key is absent. */
|
|
||||||
fun localProperty(key: String): String? {
|
|
||||||
val file = rootProject.file("local.properties")
|
|
||||||
if (!file.exists()) return null
|
|
||||||
return Properties()
|
|
||||||
.apply { file.inputStream().use { load(it) } }
|
|
||||||
.getProperty(key)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,11 +20,6 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<!-- Injected from local.properties (glitchtip.dsn); an empty DSN disables the SDK. -->
|
|
||||||
<meta-data android:name="io.sentry.dsn" android:value="${glitchtipDsn}" />
|
|
||||||
<meta-data android:name="io.sentry.traces.sample-rate" android:value="0.01" />
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -10,10 +10,11 @@ class ChomBevApp : Application() {
|
|||||||
if (isDebuggable()) {
|
if (isDebuggable()) {
|
||||||
enableStrictMode()
|
enableStrictMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SentryHelper.initializeSentry()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isDebuggable(): Boolean =
|
private fun isDebuggable(): Boolean = applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
|
||||||
applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables StrictMode for debug builds only. All violations are logged
|
* Enables StrictMode for debug builds only. All violations are logged
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# Crash reporting — Sentry SDK on GlitchTip
|
||||||
|
|
||||||
|
Chom Bev reports crashes and handled errors with the
|
||||||
|
[Sentry Kotlin Multiplatform SDK](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/),
|
||||||
|
but sends them to [GlitchTip](https://glitchtip.com) instead of Sentry. GlitchTip is an
|
||||||
|
open-source, Sentry-API-compatible backend, so the Sentry SDKs and `glitchtip-cli` work against
|
||||||
|
it unchanged — only the DSN (and the CLI's `url`) point somewhere else.
|
||||||
|
|
||||||
|
Our instance is the hosted EU one: <https://eu.glitchtip.com>.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|-----------------------|------------------------------------------------------------------------------------------------------|
|
||||||
|
| SDK | `io.sentry.kotlin.multiplatform` (see `sentry` in `gradle/libs.versions.toml`) |
|
||||||
|
| Gradle plugin | `io.sentry.kotlin.multiplatform.gradle`, applied in `shared/build.gradle.kts` |
|
||||||
|
| iOS native dependency | `sentry-cocoa` via Swift Package Manager, declared in the Xcode project |
|
||||||
|
| Initialisation | `initializeSentry()` in `shared/src/commonMain/kotlin/bzh/ajaury/chombev/SentryHelper.kt` |
|
||||||
|
| Called from | `ChomBevApp.onCreate()` (Android), `AppDelegate.application(_:didFinishLaunchingWithOptions:)` (iOS) |
|
||||||
|
|
||||||
|
There are two distinct pieces of configuration, and they are easy to confuse:
|
||||||
|
|
||||||
|
1. **The DSN** — where the *app* sends events at runtime. Injected at build time from
|
||||||
|
`local.properties`. See [Runtime configuration](#1-runtime-configuration--the-dsn).
|
||||||
|
2. **The auth token** — how *your machine or CI* uploads debug symbols to GlitchTip.
|
||||||
|
Stored in `.sentryclirc`. See [CLI configuration](#2-cli-configuration--sentryclirc).
|
||||||
|
|
||||||
|
Neither is committed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Runtime configuration — the DSN
|
||||||
|
|
||||||
|
The DSN is a write-only endpoint URL identifying the GlitchTip project. It is kept out of
|
||||||
|
version control by the `gwenedeg.secrets` convention plugin
|
||||||
|
(`build-logic/src/main/kotlin/gwenedeg.secrets.gradle.kts`), which reads it at build
|
||||||
|
time and generates an internal `BuildSecrets` object into `commonMain`.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Add the DSN to `local.properties` at the repository root (this file is git-ignored):
|
||||||
|
|
||||||
|
```properties
|
||||||
|
glitchtip.dsn=https://<key>@eu.glitchtip.com/<project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Find the value in GlitchTip under **Settings → Projects → _Chom Bev e Brezhoneg_ → Client Keys (DSN)**.
|
||||||
|
|
||||||
|
On CI, set the `GLITCHTIP_DSN` environment variable instead — it takes precedence over
|
||||||
|
`local.properties`.
|
||||||
|
|
||||||
|
### Behaviour when it is missing
|
||||||
|
|
||||||
|
`initializeSentry()` returns early when the DSN is blank, so a fresh clone builds and runs
|
||||||
|
with crash reporting simply disabled. No placeholder or dummy DSN is needed.
|
||||||
|
|
||||||
|
### Adding other secrets
|
||||||
|
|
||||||
|
Extend the `secret(environmentVariable, localPropertyKey)` helper in the convention plugin
|
||||||
|
rather than hardcoding values in Kotlin sources.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. CLI configuration — `.sentryclirc`
|
||||||
|
|
||||||
|
`sentry-cli` needs an auth token to upload debug symbols. It reads its settings from a
|
||||||
|
`.sentryclirc` INI file in the current working directory (and from `~/.sentryclirc`),
|
||||||
|
or from environment variables.
|
||||||
|
|
||||||
|
> **`.sentryclirc` contains a credential and must never be committed.**
|
||||||
|
> It is listed in `.gitignore`. Only `.sentryclirc.example` is versioned.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .sentryclirc.example .sentryclirc
|
||||||
|
chmod 600 .sentryclirc
|
||||||
|
```
|
||||||
|
|
||||||
|
Then edit `.sentryclirc` and replace the token placeholder:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[auth]
|
||||||
|
token=<your-glitchtip-auth-token>
|
||||||
|
|
||||||
|
[defaults]
|
||||||
|
url=https://eu.glitchtip.com/
|
||||||
|
org=kerlenn-sten-kidna
|
||||||
|
project=chom-bev-e-brezhoneg
|
||||||
|
```
|
||||||
|
|
||||||
|
- `url` is mandatory: without it `glitchtip-cli` talks to sentry.io, not GlitchTip.
|
||||||
|
- `org` and `project` are the *slugs* shown in the GlitchTip URLs, not the display names.
|
||||||
|
|
||||||
|
### Creating the token
|
||||||
|
|
||||||
|
In GlitchTip: **user menu → Profile → Auth Tokens → Create New Token**. Grant it at least
|
||||||
|
`project:read`, `project:write` and `project:releases`. Copy the token immediately — it is
|
||||||
|
shown only once.
|
||||||
|
|
||||||
|
### On CI
|
||||||
|
|
||||||
|
Do not write the file. Export the equivalent environment variables, sourced from your CI
|
||||||
|
secret store:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export SENTRY_URL=https://eu.glitchtip.com/
|
||||||
|
export SENTRY_ORG=kerlenn-sten-kidna
|
||||||
|
export SENTRY_PROJECT=chom-bev-e-brezhoneg
|
||||||
|
export SENTRY_AUTH_TOKEN=***
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installing glitchtip-cli
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://glitchtip.com/install.sh | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Check that the configuration resolves:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
glitchtip-cli info
|
||||||
|
```
|
||||||
|
|
||||||
|
It should print the GlitchTip URL and report the token as valid.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. iOS Archive — uploading dSYM files
|
||||||
|
|
||||||
|
### Why this is needed
|
||||||
|
|
||||||
|
A release iOS binary ships without symbol names. Without the matching dSYM, GlitchTip shows
|
||||||
|
crash frames as raw memory addresses. Uploading the dSYM lets it resolve them back to
|
||||||
|
function names and line numbers.
|
||||||
|
|
||||||
|
The shared Kotlin framework is linked **statically** (`isStatic = true` in
|
||||||
|
`shared/build.gradle.kts`), so Kotlin/Native frames end up in the app's own dSYM — there is
|
||||||
|
no separate framework dSYM to upload.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
You need `glitchtip-cli` installed and `.sentryclirc` filled in ([section 2](#2-cli-configuration--sentryclirc)).
|
||||||
|
|
||||||
|
### Upload after an archive
|
||||||
|
|
||||||
|
1. **Product → Archive** in Xcode.
|
||||||
|
2. In the Organizer, right-click the archive → **Show in Finder**.
|
||||||
|
3. Right-click the `.xcarchive` → **Show Package Contents**.
|
||||||
|
4. Upload the `dSYMs` folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/Gwenedeg
|
||||||
|
glitchtip-cli debug-files upload /path/to/Gwenedeg.xcarchive/dSYMs
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `--include-sources` if you also want source context attached to native frames.
|
||||||
|
|
||||||
|
## 4. References
|
||||||
|
|
||||||
|
- [Sentry — Kotlin Multiplatform SDK](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/)
|
||||||
|
- [Sentry — Uploading debug symbols for Apple platforms](https://docs.sentry.io/platforms/apple/guides/ios/dsym/)
|
||||||
|
- [Sentry — data collected by the SDK](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/data-management/data-collected/)
|
||||||
|
- [GlitchTip documentation](https://glitchtip.com/documentation)
|
||||||
|
- [GlitchTip CLI documentation](https://glitchtip.com/documentation/cli)
|
||||||
|
- [Kotlin — symbolicating iOS crash reports](https://kotlinlang.org/docs/native-ios-symbolication.html)
|
||||||
+11
-11
@@ -6,24 +6,24 @@ androidTargetSdk = "37"
|
|||||||
androidxActivity = "1.13.0"
|
androidxActivity = "1.13.0"
|
||||||
androidxLifecycle = "2.11.0"
|
androidxLifecycle = "2.11.0"
|
||||||
androidxWebkit = "1.16.0"
|
androidxWebkit = "1.16.0"
|
||||||
media3 = "1.11.0"
|
|
||||||
navigation3 = "1.1.1"
|
|
||||||
composeMultiplatform = "1.11.1"
|
|
||||||
composeIconsExtended = "1.7.3"
|
composeIconsExtended = "1.7.3"
|
||||||
glitchtips = "8.52.0"
|
composeMultiplatform = "1.11.1"
|
||||||
|
datastore = "1.2.1" # https://developer.android.com/jetpack/androidx/releases/datastore
|
||||||
googleServices = "4.5.0"
|
googleServices = "4.5.0"
|
||||||
|
kermit = "2.1.0"
|
||||||
|
koin = "4.2.2"
|
||||||
kotlin = "2.4.10"
|
kotlin = "2.4.10"
|
||||||
|
kotlinSerialization = "2.4.10"
|
||||||
kotlinWrappers = "2026.8.0"
|
kotlinWrappers = "2026.8.0"
|
||||||
kotlinxBrowser = "0.5.0"
|
kotlinxBrowser = "0.5.0"
|
||||||
kotlinxCoroutines = "1.11.0"
|
kotlinxCoroutines = "1.11.0"
|
||||||
kotlinSerialization = "2.4.10"
|
|
||||||
kotlinxSerializationJson = "1.11.0"
|
kotlinxSerializationJson = "1.11.0"
|
||||||
material3 = "1.11.0-alpha07"
|
material3 = "1.11.0-alpha07"
|
||||||
koin = "4.2.2"
|
media3 = "1.11.0"
|
||||||
kermit = "2.1.0"
|
navigation3 = "1.1.1"
|
||||||
vorbisspi = "1.0.3.3"
|
|
||||||
datastore = "1.2.1" # https://developer.android.com/jetpack/androidx/releases/datastore
|
|
||||||
okio = "3.18.1"
|
okio = "3.18.1"
|
||||||
|
sentry = "0.27.0"
|
||||||
|
vorbisspi = "1.0.3.3"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# Gradle plugin artifacts, used by build-logic convention plugins only
|
# Gradle plugin artifacts, used by build-logic convention plugins only
|
||||||
@@ -44,7 +44,6 @@ compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.re
|
|||||||
compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "composeMultiplatform" }
|
compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "composeMultiplatform" }
|
||||||
compose-uiTooling = { module = "org.jetbrains.compose.ui:ui-tooling", version.ref = "composeMultiplatform" }
|
compose-uiTooling = { module = "org.jetbrains.compose.ui:ui-tooling", version.ref = "composeMultiplatform" }
|
||||||
compose-uiToolingPreview = { module = "org.jetbrains.compose.ui:ui-tooling-preview", version.ref = "composeMultiplatform" }
|
compose-uiToolingPreview = { module = "org.jetbrains.compose.ui:ui-tooling-preview", version.ref = "composeMultiplatform" }
|
||||||
glitchtips = { module = "io.sentry:sentry-android", version.ref = "glitchtips" }
|
|
||||||
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin" }
|
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin" }
|
||||||
koin-compose = { module = "io.insert-koin:koin-compose" }
|
koin-compose = { module = "io.insert-koin:koin-compose" }
|
||||||
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" }
|
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" }
|
||||||
@@ -75,4 +74,5 @@ composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "k
|
|||||||
googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" }
|
googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" }
|
||||||
kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinSerialization"}
|
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinSerialization"}
|
||||||
|
sentry = { id = "io.sentry.kotlin.multiplatform.gradle", version.ref = "sentry" }
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
objectVersion = 77;
|
objectVersion = 77;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
F36B7319302CAEC900B3E490 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = F36B7318302CAEC900B3E490 /* Sentry */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
9DA43AABF87DF46F5E794E72 /* Chom Bev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Chom Bev.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
9DA43AABF87DF46F5E794E72 /* Chom Bev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Chom Bev.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@@ -41,6 +45,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F36B7319302CAEC900B3E490 /* Sentry in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -85,6 +90,7 @@
|
|||||||
);
|
);
|
||||||
name = iosApp;
|
name = iosApp;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
F36B7318302CAEC900B3E490 /* Sentry */,
|
||||||
);
|
);
|
||||||
productName = iosApp;
|
productName = iosApp;
|
||||||
productReference = 9DA43AABF87DF46F5E794E72 /* Chom Bev.app */;
|
productReference = 9DA43AABF87DF46F5E794E72 /* Chom Bev.app */;
|
||||||
@@ -114,6 +120,9 @@
|
|||||||
);
|
);
|
||||||
mainGroup = A562F15E4A0F12F420BB5B12;
|
mainGroup = A562F15E4A0F12F420BB5B12;
|
||||||
minimizedProjectReferenceProxies = 1;
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
packageReferences = (
|
||||||
|
F36B7317302CAEC900B3E490 /* XCRemoteSwiftPackageReference "sentry-cocoa" */,
|
||||||
|
);
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = 47B0C8770C82BEADFE13EF77 /* Products */;
|
productRefGroup = 47B0C8770C82BEADFE13EF77 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -176,7 +185,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "$(TEAM_ID)";
|
DEVELOPMENT_TEAM = 492RZGQ5SU;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
@@ -269,7 +278,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = "$(TEAM_ID)";
|
DEVELOPMENT_TEAM = 492RZGQ5SU;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
@@ -368,6 +377,25 @@
|
|||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
F36B7317302CAEC900B3E490 /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/getsentry/sentry-cocoa";
|
||||||
|
requirement = {
|
||||||
|
kind = exactVersion;
|
||||||
|
version = 8.58.2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
F36B7318302CAEC900B3E490 /* Sentry */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = F36B7317302CAEC900B3E490 /* XCRemoteSwiftPackageReference "sentry-cocoa" */;
|
||||||
|
productName = Sentry;
|
||||||
|
};
|
||||||
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 50584B9465876AB65BD227D3 /* Project object */;
|
rootObject = 50584B9465876AB65BD227D3 /* Project object */;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.swift
|
||||||
|
// iosApp
|
||||||
|
//
|
||||||
|
// Created by Antoine Jaury on 12/08/2026.
|
||||||
|
//
|
||||||
|
import UIKit
|
||||||
|
import Shared
|
||||||
|
|
||||||
|
final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
|
|
||||||
|
|
||||||
|
func application(_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
|
SentryHelper().initializeSentry()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@ import SwiftUI
|
|||||||
|
|
||||||
@main
|
@main
|
||||||
struct iOSApp: App {
|
struct iOSApp: App {
|
||||||
|
|
||||||
|
@UIApplicationDelegateAdaptor(AppDelegate.self)
|
||||||
|
private var appDelegate
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ plugins {
|
|||||||
id("gwenedeg.kmp.library")
|
id("gwenedeg.kmp.library")
|
||||||
id("gwenedeg.compose")
|
id("gwenedeg.compose")
|
||||||
alias(libs.plugins.kotlinSerialization)
|
alias(libs.plugins.kotlinSerialization)
|
||||||
|
id("gwenedeg.secrets")
|
||||||
|
alias(libs.plugins.sentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package bzh.ajaury.chombev
|
||||||
|
|
||||||
|
import io.sentry.kotlin.multiplatform.Sentry
|
||||||
|
|
||||||
|
object SentryHelper {
|
||||||
|
fun initializeSentry() {
|
||||||
|
// The DSN is injected at build time from local.properties (or the GLITCHTIP_DSN
|
||||||
|
// environment variable) so it never lands in version control. Without it, crash
|
||||||
|
// reporting is simply disabled.
|
||||||
|
val dsn = BuildSecrets.GLITCHTIP_DSN
|
||||||
|
if (dsn.isBlank()) return
|
||||||
|
|
||||||
|
Sentry.init { options ->
|
||||||
|
options.dsn = dsn
|
||||||
|
options.debug = true
|
||||||
|
options.sendDefaultPii = false
|
||||||
|
options.enableAutoSessionTracking = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user