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
Allow observation to have a mutable access to parent #4879
Comments
If the parent context is mutable, one can change the parent context name, tags, etc. For example, in So, when the parent context is modified, what to happen depends on the implementation of Though, there are certain use cases that is benefitial to modify the parent context based on the business logic. In such a case, I think implementing Another way could be implementing a custom public class MyObservationHandler implements MeterObservationHandler<Observation.Context> {
// modify "supportsContext" method to restrict context types to support
@Override
public void onStart(Context context) {
Timer.Sample sample = Timer.start(this.meterRegistry);
context.put(Timer.Sample.class, sample);
...
}
@Override
public void onStop(Context context) {
// retrieve the result determined by the business layer
boolean isFraud = FraudResultHolder.get(); // for example, get from a thread local variable
...
Timer.Sample sample = context.getRequired(Timer.Sample.class);
sample.stop(Timer.builder(context.getName()).tags(tags).register(this.meterRegistry));
...
}
} |
I understand your point completely. |
While re-reading the issue description and code snippet, I misunderstood the intention.
Initially, I thought you wanted to modify the parent context to change the outcome of the parent context (metrics or spans for the parent). But, I realized you are just using the parent context to keep the data accessible to child contexts. Instead of going that way, I think it is more appropriate for each child context/convention to directly access the necessary data, for example via thread local variable. |
Thanks for the suggestion, though it appears a bigger overhead to me than the current inconsistent approach I constructed, cause one has to deal with properly resetting those thread locals, which is out of the box given for us, when relying on the observation contexts. |
Normal Spring boot 3 application with a rest controller, business layer and a spring data repository involving mongodb driver.
This ends up having the following observations auto-configured (among others):
http.server.requests
http.client.requests
spring.data.repository.invocations
mongodb.driver.commands
tasks.scheduled.execution
For all besides the "http.server.requests" the current observation is the "spring.security.http.secured.requests" with parent "spring.security.filterchains" with root parent "http.server.requests"
The "http.server.requests" has no parent.
Now when I customize tags for these metrics, typically some beans are overridden or interfaces implemented and inside we either have access to the observation context (e.g. for the http.server/client.requests) or not (e.g. for the spring.data.repository.invocations), so one can not write nicely a reusable code how to propagate business data from the business layer into the context and read it out inside the customizers to decide on the custom tags.
So my idea was to consistently put my business data into the
ObservationRegistry.getCurrentObservation().getContext().put(...)
and then inside the customizer to read it out, but here is the problem:Inside the customizer for http.server.requests the current observation context is a parent of the one, which was available at the time the business data was propagated into the context.
Well, this can be solved by propagating the business data to the
HttpServletRequest
attributes, which are then available in the observation's context carrier, but this already makes it a different approach compared for example to the spring data repository or mongodb command customizers, where you only have access to some custom event object and not the observation context.So I was thinking, why not propagating the business data always to the root parent, so that no matter which context is available in the customizers, I just need to lookup in their root parents and will find it.
Though this is considered a bad practice and blocked by 3423.
Here is a concrete example, how it can be solved by the current spring and micrometer capabilities:
Though, if I would have had access to the parent observations to be able to put into their contexts, then I could strip down the code to only put into the top parent context and lookup there as well, without these fallbacks.
Btw. why is it so different to customize the tags for the different metrics:
DefaultServerRequestObservationConvention
// works like a charmDefaultClientRequestObservationConvention
// works like a charmDefaultRepositoryTagsProvider
// works like a charm though differs from first two onesDefaultMongoCommandTagsProvider
// works like a charm though differs from first two onesGlobalObservationConvention<ScheduledTaskObservationContext>
// work only after manually adding it as part of a custom bean configuration of theObservationRegistryCustomizer<ObservationRegistry>
...observationRegistry.observationConfig().observationConvention(...)I understand that the question is tightly coupled to the spring framework as well, but it is influenced by the micrometer designs I guess
The text was updated successfully, but these errors were encountered: