perf(observability): add PII-free AppLog latency breadcrumbs to the reader / openMessage path #358

Closed
opened 2026-07-05 20:54:18 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-07-05 20:54:18 +00:00 (Migrated from github.com)

Summary

The message-open path emits no AppLog breadcrumbs, so the 35–74 s open stalls this perf
run measured are invisible in field diagnostics — they could only be caught by adb-driving a
physical device. Instrument the reader / openMessage path with PII-free latency breadcrumbs so
this class of regression is observable from Problem Reports and so the fixes in #355/#356/#357 can be
verified in the field.

Evidence (physical-device perf run, 2026-07-05)

  • Opening an uncached message took avg 48.4 s (35–74 s) on real Gmail over LTE (Pixel 10 Pro
    XL, origin/main 6118b6d) — see #355 for full data and correlation with backfill.
  • The perf write-up explicitly notes: "in-app navigation / message-open (ReaderViewModel) emits
    no AppLog breadcrumbs — AppLog is only wired into sync/backfill/prune workers, IMAP IDLE
    push, app-lock, DB encryption, and 'Application created'." The only reason this stall is
    quantified at all is external adb instrumentation (am start -W, uiautomator polling).
  • This also aligns with the maintainer DoD rule that no app source change is done without
    appropriate PII-free AppLog logging.

Root cause

ReaderViewModel.init and MailRepositoryImpl.openMessage() do the body fetch with no timing
log around the network round-trip; there is no signal distinguishing a cache hit (instant) from a
cold fetch (seconds–minutes), nor any record of contention with backfill.

Proposed approach

  • Add PII-free AppLog breadcrumbs around openMessage():
    • open requested / cache-hit vs cold-fetch / body-fetch duration (ms) / attachment-meta count /
      result (success|error). No subject, sender, addresses, or body — only ids/durations/flags
      (e.g. a hashed or account-scoped opaque id, folder name, byte/kb size bucket).
  • Emit a breadcrumb when backfill yields to / resumes after an interactive fetch (#355) and for
    prefetch hit/miss + connection reuse (#357), so the whole interactive-vs-background interaction is
    traceable from one report.
  • Follow the existing AppLog tag/level conventions used by the sync/backfill workers.

Affected files

  • app/src/main/kotlin/org/libremail/ui/reader/ReaderViewModel.kt
  • app/src/main/kotlin/org/libremail/data/repository/MailRepositoryImpl.kt (openMessage, prefetchMessage, inlineImages)
  • whichever AppLog util the sync workers already use (match its tags/levels)

Definition of done (per repo DoD)

  • Unit test asserting a cold open logs a duration breadcrumb and a cached open logs a cache-hit
    breadcrumb, with no PII fields present in the logged payload.
  • Instrumented/E2E coverage that the reader path produces the breadcrumb (and it surfaces in the
    diagnostics/Problem Report collector).

Relates to

Enables verification of #355/#356/#357. Maintainer DoD: PII-free AppLog logging. Filed from the
2026-07-05 Pixel 10 Pro XL perf run.

## Summary The message-open path emits **no `AppLog` breadcrumbs**, so the 35–74 s open stalls this perf run measured are invisible in field diagnostics — they could only be caught by adb-driving a physical device. Instrument the reader / `openMessage` path with PII-free latency breadcrumbs so this class of regression is observable from Problem Reports and so the fixes in #355/#356/#357 can be verified in the field. ## Evidence (physical-device perf run, 2026-07-05) - Opening an uncached message took **avg 48.4 s (35–74 s)** on real Gmail over LTE (Pixel 10 Pro XL, origin/main `6118b6d`) — see #355 for full data and correlation with backfill. - The perf write-up explicitly notes: "in-app navigation / message-open (`ReaderViewModel`) emits **no** AppLog breadcrumbs — AppLog is only wired into sync/backfill/prune workers, IMAP IDLE push, app-lock, DB encryption, and 'Application created'." The only reason this stall is quantified at all is external adb instrumentation (`am start -W`, uiautomator polling). - This also aligns with the maintainer DoD rule that no app source change is done without appropriate PII-free `AppLog` logging. ## Root cause `ReaderViewModel.init` and `MailRepositoryImpl.openMessage()` do the body fetch with no timing log around the network round-trip; there is no signal distinguishing a cache hit (instant) from a cold fetch (seconds–minutes), nor any record of contention with backfill. ## Proposed approach - Add PII-free `AppLog` breadcrumbs around `openMessage()`: - open requested / cache-hit vs cold-fetch / body-fetch duration (ms) / attachment-meta count / result (success|error). **No** subject, sender, addresses, or body — only ids/durations/flags (e.g. a hashed or account-scoped opaque id, folder name, byte/kb size bucket). - Emit a breadcrumb when backfill yields to / resumes after an interactive fetch (#355) and for prefetch hit/miss + connection reuse (#357), so the whole interactive-vs-background interaction is traceable from one report. - Follow the existing `AppLog` tag/level conventions used by the sync/backfill workers. ## Affected files - `app/src/main/kotlin/org/libremail/ui/reader/ReaderViewModel.kt` - `app/src/main/kotlin/org/libremail/data/repository/MailRepositoryImpl.kt` (`openMessage`, `prefetchMessage`, `inlineImages`) - whichever `AppLog` util the sync workers already use (match its tags/levels) ## Definition of done (per repo DoD) - Unit test asserting a cold open logs a duration breadcrumb and a cached open logs a cache-hit breadcrumb, with **no** PII fields present in the logged payload. - Instrumented/E2E coverage that the reader path produces the breadcrumb (and it surfaces in the diagnostics/Problem Report collector). ## Relates to Enables verification of #355/#356/#357. Maintainer DoD: PII-free `AppLog` logging. Filed from the 2026-07-05 Pixel 10 Pro XL perf run.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMail#358