fix(server): Measure request duration end-to-end - #555
Merged
Conversation
The server.requests.duration metric previously stopped as soon as the handler produced the response headers, excluding the time spent streaming the response body. This under-measured GET, batch, and multipart:complete responses, whose bodies are streamed after the middleware returns. Move the timing guard into a MetricsBody wrapper around the response body so it is dropped only once the body has finished streaming. When the body does not stream to completion (client disconnect or a server-side stream error, folded together), the metric is tagged status:499 instead of the header status.
This comment has been minimized.
This comment has been minimized.
Distinguish a server-side body stream error from a client disconnect: an error frame while streaming the response body is now tagged status:500, while a client disconnecting mid-stream remains status:499.
Member
Changing |
jan-auer
reviewed
Jul 15, 2026
lcian
marked this pull request as ready for review
July 15, 2026 12:00
lcian
marked this pull request as draft
July 15, 2026 17:50
Classify empty, buffered, streamed, and trailers-only responses as completed so request duration metrics retain the response status. Keep stream errors and interrupted bodies distinguishable, and simplify body wrapping with Response::map. Co-Authored-By: Claude <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c1d2a36. Configure here.
Keep response-body outcome coverage next to the MetricsBody state machine while retaining middleware timing coverage with its middleware tests. Co-Authored-By: Claude <noreply@anthropic.com>
lcian
marked this pull request as ready for review
July 16, 2026 13:35
lcian
commented
Jul 16, 2026
jan-auer
reviewed
Jul 23, 2026
lcian
force-pushed
the
fix/request-duration-end-to-end
branch
from
July 24, 2026 12:23
7603c6f to
88bf634
Compare
jan-auer
approved these changes
Jul 27, 2026
lcian
force-pushed
the
fix/request-duration-end-to-end
branch
from
July 27, 2026 09:24
ccabebb to
88bf634
Compare
lcian
enabled auto-merge (squash)
July 27, 2026 09:24
lcian
pushed a commit
that referenced
this pull request
Jul 28, 2026
Streaming responses that declare a `content-length` were recorded as client disconnects (499) in `server.requests.duration`, a regression from #555. Hyper stops polling a response body once the declared number of bytes has been written, so the wrapper never saw an end-of-stream poll and its guard fell back to 499 when dropped. `MetricsBody` now counts the bytes it forwards and completes the request once the declared length is reached, alongside the existing end-of-stream and trailers cases. Responses whose body hyper never polls at all are completed up front when they are wrapped. The tests were reworked around a helper that serves a real axum handler through the middleware and returns the tracked status and duration, which made room for a paused-clock test asserting the duration spans body streaming rather than ending at the response headers. Capturing metrics across await points needs a new `with_capturing_test_client_async` in `objectstore-metrics`.
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.
server.requests.durationnow measures the request through response-body completion rather than stopping when a handler produces headers. This includes time spent streaming GET payloads, batch responses, and multipart-complete responses.The middleware moves its timing guard into
MetricsBody, which emits the metric only after Hyper has completed or dropped the response body. The wrapper preserves response metadata and existingContent-Lengthbehavior.Status tagging reflects how streaming ended:
499;500.Completion handling is verified against Hyper 1.10.1 for empty/no-body responses, buffered bodies, ordinary streamed bodies, and terminal trailers. Regression tests cover each completion path, plus stream errors and interrupted streams.
Close FS-555