The logging infrastructure is good but barely connected, so submitted DebugReports carry almost no useful breadcrumbs:
AppLog (the facade that mirrors to logcat and the RingLogBuffer → DebugReport.logs) is used only 5 times, in 2 files (LibreMailApplication, IdleService).
~22 raw android.util.Log.* calls across 10 files bypass the buffer (logcat-only, never in a report) — and they're the diagnostically valuable ones: AppLockViewModel ×9 (auth-seal/keystore failures), ImapClient (IDLE drops), SendWorker (Graph→SMTP fallback), DatabaseKeyCipher ×4, DatabaseEncryption, AccountDataMigrator, AccountSetupViewModel (Outlook sign-in fail), RestartActivity.
Overall sparse (~27 statements / ~120 files): the sync engine (MailSyncer/MailBackfiller/MailPruner), repositories, and most ViewModels are silent.
AppLog.e() records only the message to the buffer, not the throwable (AppLog.kt:37).
PII reaches logcat via raw Log.w("…\${account.email}…") in SendWorker/IdleService (also Backlog #297) — must be scrubbed as calls are migrated.
Goal
Route diagnostic logging through AppLog so debug reports carry useful, PII-safe breadcrumbs; add breadcrumbs at key sync/auth/lifecycle points; make AppLog.e record the throwable; and prevent regression with a static-analysis guard so new code can't bypass the facade.
Approach — strangler-fig
Incrementally migrate area by area (package/subsystem), behavior-preserving, until raw android.util.Log.* is gone from app code (only AppLog itself may import it). Add a detekt/lint guard (forbid android.util.Log outside AppLog.kt) as the strangler seam so the old path can't regrow. Hard PII constraint stays: never log emails/hosts/message content/credentials.
Next step
An Opus spike (this epic's first task) will inventory the full logging surface, design the target state + the guard rule, and break the work into independent, parallelizable area sub-tickets for agents to implement. Sub-tickets will link back here.
## Problem (assessment 2026-07-04)
The logging **infrastructure is good but barely connected**, so submitted `DebugReport`s carry almost no useful breadcrumbs:
- `AppLog` (the facade that mirrors to logcat **and** the `RingLogBuffer` → `DebugReport.logs`) is used only **5 times, in 2 files** (`LibreMailApplication`, `IdleService`).
- **~22 raw `android.util.Log.*` calls across 10 files bypass the buffer** (logcat-only, never in a report) — and they're the diagnostically valuable ones: `AppLockViewModel` ×9 (auth-seal/keystore failures), `ImapClient` (IDLE drops), `SendWorker` (Graph→SMTP fallback), `DatabaseKeyCipher` ×4, `DatabaseEncryption`, `AccountDataMigrator`, `AccountSetupViewModel` (Outlook sign-in fail), `RestartActivity`.
- Overall **sparse** (~27 statements / ~120 files): the sync engine (`MailSyncer`/`MailBackfiller`/`MailPruner`), repositories, and most ViewModels are silent.
- `AppLog.e()` records only the message to the buffer, **not the throwable** (`AppLog.kt:37`).
- PII reaches **logcat** via raw `Log.w("…\${account.email}…")` in `SendWorker`/`IdleService` (also Backlog #297) — must be scrubbed as calls are migrated.
## Goal
Route diagnostic logging through `AppLog` so debug reports carry useful, **PII-safe** breadcrumbs; add breadcrumbs at key sync/auth/lifecycle points; make `AppLog.e` record the throwable; and prevent regression with a static-analysis guard so new code can't bypass the facade.
## Approach — strangler-fig
Incrementally migrate **area by area** (package/subsystem), behavior-preserving, until raw `android.util.Log.*` is gone from app code (only `AppLog` itself may import it). Add a detekt/lint guard (forbid `android.util.Log` outside `AppLog.kt`) as the strangler seam so the old path can't regrow. Hard PII constraint stays: never log emails/hosts/message content/credentials.
## Next step
An Opus **spike** (this epic's first task) will inventory the full logging surface, design the target state + the guard rule, and break the work into independent, parallelizable **area sub-tickets** for agents to implement. Sub-tickets will link back here.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem (assessment 2026-07-04)
The logging infrastructure is good but barely connected, so submitted
DebugReports carry almost no useful breadcrumbs:AppLog(the facade that mirrors to logcat and theRingLogBuffer→DebugReport.logs) is used only 5 times, in 2 files (LibreMailApplication,IdleService).android.util.Log.*calls across 10 files bypass the buffer (logcat-only, never in a report) — and they're the diagnostically valuable ones:AppLockViewModel×9 (auth-seal/keystore failures),ImapClient(IDLE drops),SendWorker(Graph→SMTP fallback),DatabaseKeyCipher×4,DatabaseEncryption,AccountDataMigrator,AccountSetupViewModel(Outlook sign-in fail),RestartActivity.MailSyncer/MailBackfiller/MailPruner), repositories, and most ViewModels are silent.AppLog.e()records only the message to the buffer, not the throwable (AppLog.kt:37).Log.w("…\${account.email}…")inSendWorker/IdleService(also Backlog #297) — must be scrubbed as calls are migrated.Goal
Route diagnostic logging through
AppLogso debug reports carry useful, PII-safe breadcrumbs; add breadcrumbs at key sync/auth/lifecycle points; makeAppLog.erecord the throwable; and prevent regression with a static-analysis guard so new code can't bypass the facade.Approach — strangler-fig
Incrementally migrate area by area (package/subsystem), behavior-preserving, until raw
android.util.Log.*is gone from app code (onlyAppLogitself may import it). Add a detekt/lint guard (forbidandroid.util.LogoutsideAppLog.kt) as the strangler seam so the old path can't regrow. Hard PII constraint stays: never log emails/hosts/message content/credentials.Next step
An Opus spike (this epic's first task) will inventory the full logging surface, design the target state + the guard rule, and break the work into independent, parallelizable area sub-tickets for agents to implement. Sub-tickets will link back here.