Skip to content

fix(logging): name the request in failed-call summaries - #381

Merged
mohamede1945 merged 2 commits into
mainfrom
fix/http-failed-log-url
Nov 5, 2026
Merged

mohamede1945 merged 2 commits into
mainfrom
fix/http-failed-log-url

Conversation

@mohamede1945

Copy link
Copy Markdown
Collaborator

Summary

A failed call's summary line (info or warn) didn't name the call that failed. Ktor's OkHttp format logs <-- HTTP FAILED: <cause> with no method or URL. Darwin errors also span several lines, so the summary was cut at the first newline and the URL appeared only on the DEBUG line. In an iOS diagnostics log, that meant a sync failure could only be matched to its request by hand, and not at all without debug logs or with several calls in flight.

  • installHttpLogging now also installs a small client plugin at HttpSendPipeline.Monitoring, nested inside Ktor's Logging. It sees the same failures and has the request in hand. It logs <-- HTTP FAILED GET https://… (60012ms): <cause> through the same redact → summary → debug path, and Ktor's own unnamed failure line is dropped, so each failure is logged once.
  • Timeouts now log at warn. HttpTimeout cancels the call with an HttpRequestTimeoutException as the cause, which the old check (and the old string match) took for the caller's own cancellation and logged at info. The cause is now unwrapped with Ktor's unwrapCancellationException, so a real cancellation stays at info and a timeout reads HttpRequestTimeoutException: … at warn.
  • Header sanitizing, detailedHttpLogs, and the request/response lines are unchanged. AuthHttp and SyncHttp both go through installHttpLogging.

Before / after, for a Darwin connection loss:

<-- HTTP FAILED: io.ktor.client.engine.darwin.DarwinHttpRequestException: Exception in http request: Error Domain=NSURLErrorDomain Code=-1005 … UserInfo={…
<-- HTTP FAILED GET https://apis-prelive.quran.foundation/auth/v1/sync?mutationsSince=…&page=1&limit=1000 (60012ms): io.ktor.client.engine.darwin.DarwinHttpRequestException: Exception in http request: Error Domain=NSURLErrorDomain Code=-1005 …

Tests

HttpLoggingTest, using a real Ktor client with MockEngine:

  • a failed call logs one warning that names its method and URL
  • a multi-line cause gives a one-line summary at warn with the full text at debug
  • redaction applies to the URL
  • two concurrent failing calls each name their own URL
  • a cancelled call stays at info
  • a timed-out call warns

Six of these fail on the old code.

  • ./gradlew jvmTest testAndroidHostTest :logging:iosSimulatorArm64Test :logging:compileKotlinIosArm64
  • ./gradlew :logging:jvmTest :logging:iosSimulatorArm64Test (11/11 each), ./gradlew :auth:jvmTest :auth:testAndroidHostTest (422)

🤖 Generated with Claude Code

mohamede1945 and others added 2 commits November 5, 2026 15:00
Ktor's OkHttp log format logs a failed call as "<-- HTTP FAILED: <cause>",
with no method or URL. A multi-line cause (Darwin's NSError) also cuts the
summary before the URL it may carry, so without debug logs a failure
could not be tied to its request, and ordering does not help when calls
overlap.

A small client plugin now intercepts the send pipeline's Monitoring phase
(the phase Ktor 3.6.0's Logging uses), inside Logging's interceptor, and
logs each failure with the request it has in hand:
"<-- HTTP FAILED GET https://... (60012ms): <cause>". Ktor's own
failure line is dropped so a failure is logged once. Cancellations stay
at info (now by type), redaction covers the URL, and the full cause still
goes to debug when it spans several lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HttpTimeout fails a call that runs past requestTimeoutMillis by cancelling
it with an HttpRequestTimeoutException as the cause, so in the send
pipeline a timeout arrives as a CancellationException. The failure line
took it for the caller's own cancellation and logged it at info, as
"CancellationException: Request timeout has expired"; the auth client
sets a 30 s request timeout, so its timeouts were logged that way.

The failure line now unwraps the cancellation with Ktor's
unwrapCancellationException: it warns unless the unwrapped cause is still
a cancellation (one the caller made) and logs the unwrapped cause, so a
timeout reads "HttpRequestTimeoutException: ...". The KDoc on
installHttpLogging also says to install it once per client, since a
second install logs failures with the first install's logger and redact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mohamede1945
mohamede1945 merged commit b1d7421 into main Nov 5, 2026
2 checks passed
@mohamede1945
mohamede1945 deleted the fix/http-failed-log-url branch November 5, 2026 20:17
mohamede1945 added a commit to quran/quran-ios that referenced this pull request Nov 5, 2026
mobile-sync 0.1.54 (quran/mobile-sync#381) names the request in the
summary line of a failed HTTP call, so it now reads
"<-- HTTP FAILED GET https://... (Nms): <cause>", and logs request
timeouts at warn as HttpRequestTimeoutException instead of at info as a
CancellationException. mobile-sync-spm 0.4.10 also updates the doc
comment on updateReadingSession.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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