Instrument Authress login flow with timing logs and a diagnostic overlay - #8
Merged
Merged
Conversation
…overlay Every Authress call now logs its duration (including the anti-abuse proof-of-work search and the network round trip separately), and the proof-of-work hash is dispatched to Dispatchers.Default so it no longer runs on the Main thread just because callers launch it from a Compose rememberCoroutineScope. Onboarding and the login screen now show a cog button that opens a scrollable, color-coded log panel backed by the existing AppLogger, so a slow or stuck sign-in can be diagnosed in place.
…ogging
- CI caught two real compile errors from the previous commit: the
anti-abuse hash's suspend/withContext refactor inferred Unit instead of
String, and DebugLogOverlay was missing the setValue operator import for
its `var expanded by remember {...}`. Both fixed.
- Found and fixed a real bug while adding request timing: AuthressLoginClient
was built from the same OkHttpClient as the Email API, which carries
AuthInterceptor. That interceptor waits on waitForToken() — before a
session exists, every unauthenticated Authress call (including the very
POST /authentication that starts login) blocked for its full 5s timeout
waiting for a session that only that same call could establish. Authress
now gets its own client without AuthInterceptor.
- Logging now covers more than the login path: ApiLoggingInterceptor gives
the Email API the same production-visible request timing Authress calls
already had (HttpLoggingInterceptor is debug-only), and ThreadRepository's
syncPending/SyncForegroundService — previously silent — now log queue
sizes, per-item failures, and tick duration.
- authenticate()/completeAuthenticationRequest() split into more granular
AuthStatus/LoginStep stages (RequestingAuthenticationUrl, OpeningBrowser,
AwaitingRedirect, VerifyingRedirect, ExchangingToken) so the sign-in
checklist shows which specific call is slow instead of one wide phase.
- Diagnosed "authentication request mismatch": tapping "Try again" while an
earlier Custom Tab is still alive starts a second attempt: the old tab can
still redirect back with the old authenticationRequestId after storage has
moved on to the new one. authenticate() now logs when it abandons a live
attempt, and the mismatch log line names both the pending and redirect IDs
so the two can be correlated instead of the mismatch looking unexplained.
…a token AuthInterceptor ran on OkHttp's dispatcher pool for every Email API request and used runBlocking to await AuthressLoginClient.waitForToken() there. That mixes concerns: waiting for a browser-driven login the request has nothing to do with is a foreground/UI concern, not something a background request-attachment interceptor should block a pool thread on. It's also exactly what caused the earlier 5s stall bug (a request racing an in-progress login could block behind an unrelated flow). AuthInterceptor now takes a synchronous, non-suspending token provider and attaches whatever token is cached right now via getToken() — never waits. waitForToken() stays available for a foreground caller that deliberately wants to gate on sign-in (the login screen), which is the only place it should ever be awaited from.
Walking back the previous commit's change to a synchronous, non-waiting AuthInterceptor: waitForToken() belongs exactly there — it's the HTTP call wrapper grabbing a token right before an Email API request goes out, which is the one legitimate caller for it. That's safe (runBlocking inside an OkHttp interceptor never touches the main thread) specifically because Authress's own client (authHttpClient) never carries this interceptor — that split, not removing the wait, is what actually fixed the earlier 5s stall bug (POST /authentication waiting on a session only it could create). No other caller for waitForToken() exists or should; doc comments on it, AuthInterceptor, and AppContainer now say so directly instead of describing a foreground caller that was never wired up.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the "why is Authress login slow" investigation: adds the instrumentation needed to actually see where time goes, plus a way to view it without hooking up logcat.
AuthressLoginClient's sharedexecute()now logs every Authress request/response with elapsed ms (request start, network failure, and success/failure all timed), andauthenticate()/completeAuthenticationRequest()separately log how long the anti-abuse proof-of-work search takes vs. the network round trip.JwtManager.calculateAntiAbuseHashis nowsuspendand dispatches its busy-loop search toDispatchers.Defaultinternally, so it can't block the Main thread just because a caller (e.g.LoginScreen'srememberCoroutineScope) happened to launch it there.LoginScreen's post-sign-in mailbox load is now timed and logged too.DebugLogOverlaycomposable: a persistent cog button in the bottom-right corner during onboarding and the login screen that opens a scrollable, color-coded (info/warn/error) log panel reading from the existing Room-backedAppLogger— the same log store already exposed in Settings > Logs, just reachable before a session exists.Test plan
Generated by Claude Code