feature: integrate Sentry SDK for crash reporting on Android and iOS

This commit is contained in:
Antoine Jaury
2026-09-30 11:18:54 +02:00
parent 87d4f3ce5d
commit 48a78e5743
14 changed files with 284 additions and 41 deletions
+164
View File
@@ -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)