-
Notifications
You must be signed in to change notification settings - Fork 38.3k
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
Current Observation.Context missing from WebClient request #31609
Comments
Thanks for reaching out. I realize that this provides less flexibility than the former Now we could consider moving the instrumentation after the
This instrumentation is similar to the current arrangement in In short, I don't know how to make this work without breaking those assumptions or somehow going back to a more complex setup where the observation belongs to a separate filter function that you need to configure and order yourself relative to other filters. Am I missing something? |
@bclozel I agree with the above points, but the limitation here is that observation context for the request is immutable and, as result, it's impossible to use changes made by filters in reported metrics. I'm still trying to understand the new observation lifecycle but here are several scenarios from our system that are not working after migration:
From what I see Line 96 in e12269e
is called after filters ( observation.stop() ) but it relies on the request that was initialized before. Probably we can update request in the ObservationFilterFunction together with response in ClientRequestObservationConvention .
|
Reading the use cases you've described, I think it would make more sense to get the current observation from your filter function and then add keyvalues directly to it. You should get it from the reactor Context or better, from a request attribute. I see we're not exposing the current observation right now to the filter functions and I would consider this a bug. Ideally, something like this: class CustomFilterFunction implements ExchangeFilterFunction {
@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
ClientRequestObservationContext.findCurrent(request)
.ifPresent(context -> context.addLowCardinalityKeyValue(KeyValue.of("key", "value")));
return return next.exchange(request);
}
}
It's not entirely true. The lifecycle is a bit more complex. Micrometer uses Let me know what you think about this. |
Getting access to the current observation context from the filter is a good idea and definitely make sense, but adding metrics directly to the context will create unnecessary coupling. Currently context is just request/response holder and has no knowledge on the underlining metrics. In addition, in our case, we adding an additional tag to the built-in metric
Basically we just need to pass some addition context from the filter to the
and then access Another option is to update the request in the
|
There is no
I think we should eliminate this solution completely. We've seen how this can lead to inconsistent observations, leading to metrics being very different from traces. Implementations can do that through the context if they chose so, but I don't think we should make this easier and lead developers to this situation. At this stage, I'm considering putting the |
I know that
This is exactly the issue.
|
Right, I forgot that the attributes map was also made immutable. We'll add the client Observation.Context as a request attribute then, this is the most sensible and straightforward solution. |
@bclozel thx for the update but still not sure how to pass additional state to |
No this change should be enough - you can add key values like this: #31609 (comment) |
let me check what is the lifecycle of the |
I have described the lifecycle in #31609 (comment) Adding low cardinality KeyValues to the observation will add tags to the metric. |
Unfortunately we had to remove this feature in #32198 because it was linked with reported memory leaks. |
Prior to this commit, gh-31609 added the current observation context as a request attribute for `WebClient` calls. While it was not confirmed as the main cause, this feature was linked to several reports of memory leaks. This would indeed attach more memory to the request object graph at runtime - although it shouldn't prevent its collection by the GC. This commit removes this feature and instead developers should get the current observation from the reactor context if they wish to interact with it. Closes gh-32198
Spring Boot: 3.1.5
Spring Framework: 6.0.13
In Spring 3 micrometer integration has been reworked to use Micrometer 1.10 Observation. It works in the default setup but in case there is a
filter
(ExchangeFilterFunction
) that changes the underlining request, metric is reported with incorrect tags.It happens because current implementation is initializing
ClientRequestObservationContext
using the originalClientRequest
spring-framework/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java
Line 455 in e12269e
and any changes to the request after this point are not visible to the observation context
spring-framework/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestObservationConvention.java
Line 92 in e12269e
Similar scenario was supported in the previous version by adding custom filters before
MetricsWebClientFilterFunction
that reported the same metric before.Here is a test to reproduce the above issue. In this test original request uses
POST
http method but filter is changing is toGET
. The metric is still reported with the originalPOST
method.The text was updated successfully, but these errors were encountered: