Skip to content

ADFA-4397: Migrate crash and log reporting from Sentry to GlitchTip#1490

Open
Daniel-ADFA wants to merge 1 commit into
stagefrom
ADFA-4397
Open

ADFA-4397: Migrate crash and log reporting from Sentry to GlitchTip#1490
Daniel-ADFA wants to merge 1 commit into
stagefrom
ADFA-4397

Conversation

@Daniel-ADFA

Copy link
Copy Markdown
Contributor

Point the Sentry Android SDK at GlitchTip instead of Sentry. The SDK, DSN format, and tooling stay the same; only the endpoint moves. The DSN comes from local.properties for local builds and from CI secrets for release builds, so nothing is hardcoded.

Point the Sentry Android SDK at GlitchTip instead of Sentry. The SDK,
DSN format, and tooling stay the same; only the endpoint moves. The DSN
comes from local.properties for local builds and from CI secrets for
release builds, so nothing is hardcoded.

- Forward the app's logback output to GlitchTip. WARN and above go to the
  Logs view; INFO and above ride along as breadcrumbs (breadcrumbs are free).
- Tag each event with the device as the user so crashes can be filtered
  per user.
- Drop Sentry features GlitchTip does not support: session replay and
  profiling (dependency plus manifest flags removed).
- Keep event volume inside the 100k plan: error logs no longer become
  issues (real crashes are still captured), and performance transactions
  are disabled. Logs bill at 0.1 and share the same event pool.
@Daniel-ADFA Daniel-ADFA requested a review from a team July 7, 2026 21:39

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough
  • Migrated Android crash/log reporting from Sentry to GlitchTip while keeping the existing Sentry SDK and DSN wiring intact.

  • Added Logback integration so app logs are forwarded to GlitchTip, with WARN+ captured in Logs and INFO+ added as breadcrumbs.

  • Tagged crash events with device identity information to improve filtering and triage.

  • Removed unsupported Sentry features for GlitchTip, including session replay and profiling.

  • Reduced telemetry volume by disabling performance transactions and error-log issue creation to stay within the plan limits.

  • Risk: send-default-pii is enabled, so user/device-identifying data may be attached to events and should be reviewed for privacy/compliance impact.

  • Risk: Disabling performance transactions and replay/profiling removes observability data that may be useful during incident investigation.

  • Best-practice note: the DSN is sourced externally rather than hardcoded, which helps avoid secret leakage in source control.

Walkthrough

This PR replaces the Sentry Android session-replay dependency with Sentry Logback integration. It wires a SentryAppender into the Logback root logger during Sentry initialization, sets Sentry user info from device identifiers, removes replay quality configuration, and trims related manifest metadata.

Changes

Sentry Logback Migration

Layer / File(s) Summary
Dependency and version catalog updates
gradle/libs.versions.toml, app/build.gradle.kts
Replaces sentry-android-replay with sentry-logback dependency, keeping the shared Sentry version reference.
Sentry initialization and Logback appender wiring
app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt
Removes SentryReplayQuality config, adds Logback/Sentry imports, configures a SentryAppender attached to the root logger, and sets Sentry user via ANDROID_ID, manufacturer, and model.
Manifest Sentry metadata reduction
app/src/main/AndroidManifest.xml
Sets io.sentry.traces.sample-rate to 0.0 and removes profiling/session-replay metadata while retaining send-default-pii and logs.enabled.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DeviceProtectedApplicationLoader
  participant SentryAndroid
  participant LoggerContext
  participant SentryAppender
  participant Sentry

  DeviceProtectedApplicationLoader->>SentryAndroid: init(options)
  DeviceProtectedApplicationLoader->>LoggerContext: get root logger
  DeviceProtectedApplicationLoader->>SentryAppender: configure thresholds and start
  DeviceProtectedApplicationLoader->>LoggerContext: attach SentryAppender to root logger
  DeviceProtectedApplicationLoader->>Sentry: setUser(ANDROID_ID, MANUFACTURER, MODEL)
Loading

Possibly related PRs

Suggested reviewers: itsaky-adfa

Poem

Hop, hop, I traced a log so bright, 🐇
Replay is gone, logback's in sight,
A SentryAppender perched on the tree,
Whispering user data quietly,
Carrots and code, all wired just right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving crash and log reporting from Sentry to GlitchTip.
Description check ✅ Passed The description matches the PR intent and mentions the GlitchTip endpoint migration and DSN sourcing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-4397

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/build.gradle.kts (1)

357-360: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale comment references removed replay dependency.

The comment above still says "core + replay for quality configuration" but sentry.android.replay was removed and sentry.logback was added.

📝 Proposed fix
-	// Sentry Android SDK (core + replay for quality configuration)
+	// Sentry Android SDK (core + Logback appender for GlitchTip log/breadcrumb forwarding)
 	implementation(libs.sentry.core)
 	implementation(libs.sentry.android.core)
 	implementation(libs.sentry.logback)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/build.gradle.kts` around lines 357 - 360, The dependency block for the
Sentry Android SDK has a stale comment that still references replay even though
only core, android core, and logback are included now. Update the comment near
the Sentry dependency declarations to match the actual set of dependencies in
the build script, using the existing Sentry dependency entries as the reference
point.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt`:
- Around line 75-97: Wrap the Sentry and Logback initialization in
DeviceProtectedApplicationLoader.load() in a runCatching block so
startup-critical failures do not abort direct-boot setup. Keep the existing
SentryAndroid.init, LoggerContext/SentryAppender configuration, and
Sentry.setUser logic inside the guarded block, and make sure any exception is
swallowed or logged without preventing the later ShizukuSettings.initialize()
and EventBus setup from running.

---

Nitpick comments:
In `@app/build.gradle.kts`:
- Around line 357-360: The dependency block for the Sentry Android SDK has a
stale comment that still references replay even though only core, android core,
and logback are included now. Update the comment near the Sentry dependency
declarations to match the actual set of dependencies in the build script, using
the existing Sentry dependency entries as the reference point.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79fe817f-c893-4847-8028-6adf51828d4e

📥 Commits

Reviewing files that changed from the base of the PR and between db0137a and 6637313.

📒 Files selected for processing (4)
  • app/build.gradle.kts
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt
  • gradle/libs.versions.toml

Comment on lines 75 to +97
SentryAndroid.init(app) { options ->
// Reduce replay quality to LOW to prevent OOM
// This reduces screenshot compression to 10 and bitrate to 50kbps
// (defaults to MEDIUM quality)
options.sessionReplay.quality = SentryReplayQuality.LOW
options.environment =
if (BuildConfig.DEBUG) IDEApplication.SENTRY_ENV_DEV else IDEApplication.SENTRY_ENV_PROD
}

val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
val sentryLogAppender =
SentryAppender().apply {
context = loggerContext
setMinimumEventLevel(Level.OFF)
setMinimumBreadcrumbLevel(Level.INFO)
setMinimumLevel(Level.WARN)
start()
}
loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(sentryLogAppender)

Sentry.setUser(
User().apply {
id = Settings.Secure.getString(app.contentResolver, Settings.Secure.ANDROID_ID)
username = "${Build.MANUFACTURER} ${Build.MODEL}"
},
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File list =="
git ls-files app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt

echo
echo "== Outline: DeviceProtectedApplicationLoader.kt =="
ast-grep outline app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt --view expanded || true

echo
echo "== Outline: IDEApplication.kt =="
ast-grep outline app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt --view expanded || true

echo
echo "== Relevant search: runCatching / direct boot / ANR / Sentry =="
rg -n "runCatching|direct boot|ANR|Sentry|LoggerContext|SentryAppender|Settings\.Secure\.ANDROID_ID" app/src/main/java/com/itsaky/androidide/app -S

Repository: appdevforall/CodeOnTheGo

Length of output: 6511


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DeviceProtectedApplicationLoader.kt (lines 50-105) =="
sed -n '50,105p' app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt | cat -n

echo
echo "== IDEApplication.kt (lines 160-185) =="
sed -n '160,185p' app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt | cat -n

echo
echo "== CredentialProtectedApplicationLoader.kt (selected runCatching/Sentry uses) =="
sed -n '130,205p' app/src/main/java/com/itsaky/androidide/app/CredentialProtectedApplicationLoader.kt | cat -n

Repository: appdevforall/CodeOnTheGo

Length of output: 6445


🌐 Web query:

Android direct boot Settings.Secure.ANDROID_ID ContentResolver availability

💡 Result:

In Android, Settings.Secure.ANDROID_ID is available to encryption-aware applications during Direct Boot mode [1][2]. Direct Boot mode allows an Android device to boot to a state where it is powered on but the user has not yet entered their credentials (such as a PIN, pattern, or password) [1][3]. To access system resources or perform operations during this phase, an application must be marked as encryption-aware by setting the android:directBootAware attribute to true in its manifest [2][4]. Regarding the specific availability of Settings.Secure.ANDROID_ID and ContentResolver: 1. Settings.Secure.ANDROID_ID: The Settings provider is generally available during Direct Boot, meaning applications can retrieve the ANDROID_ID via the standard ContentResolver interface [5][6]. 2. ContentResolver: While the ContentResolver class is available during Direct Boot, its utility is restricted by the encryption state of the underlying data [2][6]. An encryption-aware app can successfully use a ContentResolver to query data stored in device-encrypted storage [2]. However, attempts to access data in credential-encrypted storage (which is only decrypted after the user unlocks the device) will fail or be unavailable [2]. Developers should ensure that any components interacting with these APIs during the locked state are correctly registered and handle potential limitations regarding data access gracefully [2][4].

Citations:


Wrap the Sentry/Logback setup in runCatching.
DeviceProtectedApplicationLoader is startup-critical in direct boot, and any exception here can abort load() before ShizukuSettings.initialize() and EventBus setup. IDEApplication.kt already warns that failures in this loader can lead to ANRs after reboot.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/com/itsaky/androidide/app/DeviceProtectedApplicationLoader.kt`
around lines 75 - 97, Wrap the Sentry and Logback initialization in
DeviceProtectedApplicationLoader.load() in a runCatching block so
startup-critical failures do not abort direct-boot setup. Keep the existing
SentryAndroid.init, LoggerContext/SentryAppender configuration, and
Sentry.setUser logic inside the guarded block, and make sure any exception is
swallowed or logged without preventing the later ShizukuSettings.initialize()
and EventBus setup from running.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant