New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add simple ResponseTiming
middleware and test
#2205
Conversation
- Uses implicit `Clock[F]` to time from headers parsed to response started - Adds "X-Response-Time" header to `Response`
resp <- http(req) | ||
after <- clock.monotonic(timeUnit) | ||
header = Header(headerName.value, s"${after - before}") | ||
} yield resp.copy(headers = resp.headers.put(header)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be
} yield resp.copy(headers = resp.headers.put(header)) | |
} yield resp.withHeaders(resp.headers.put(header)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a withHeaders
available. I can do something like this:
} yield resp.putHeaders(resp.headers.put(header).toList:_*)
Do you think that's better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it apparently only is on Request
. Keep it as .copy
, that's fine.
@rossabaker @ChristopherDavenport Why is .withHeaders
only on Request
? The headers field is the same on both Request
and Response
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like an oversight to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like putHeaders
was enough.
Thanks!
I'm busy with blaze and test stability, so I'm relying others to review the code. |
* @param timeUnit the units of measure for this timing | ||
* @param headerName the name to use for the header containing the timing info | ||
*/ | ||
def apply[F[_]: Sync]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency observation: Most of our middlewares are apply(arg1: Blah, arg2: Foo)(http: HttpApp[F])
, so the HttpApp
is in the final argument list. Since most of them take implicit constraints, I also don't know how much that convention actually helps us in terms of partial application.
We also usually don't use context bounds when there are other implicits: I would move Sync
into the list ahead of clock
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I change the arg list, then application looks a bit weird because of the default arguments:
val app = ResponseTiming()(thisService)
So I tried to follow EntityLimiter in this case. But I'm happy to change it to whichever is preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, that's a good point. My convention breaks down when everything else has a default argument. I dislike having two conventions, but I think yours is better in this case. Objection withdrawn.
- Add clarifying language
Clock[F]
to time from headers parsed to response startedResponse
, named "X-Response-Time" by defaultFor #2014