Skip to content
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 custom ScheduledTaskObservationConvention in ScheduledMethodRunnable #32563

Closed
hadjiski opened this issue Apr 2, 2024 · 4 comments
Closed
Assignees
Labels
status: invalid An issue that we don't feel is valid theme: observability An issue related to observability and tracing

Comments

@hadjiski
Copy link

hadjiski commented Apr 2, 2024

Currently a custom convention can be achieved only by going through the micrometer global conventions: SomeCustom implementes GlobalObservationConvention<ScheduledTaskObservationContext>
which need to be extra registered in a ObservationRegistryCustomizer bean

@Bean
    public ObservationRegistryCustomizer<ObservationRegistry> observationRegistryCustomizer() {
        return registry -> 
            registry.observationConfig()
                    .observationConvention(new SomeCustom());
    }

This though is making it impossible to re-use the default code from the DefaultScheduledTaskObservationConvention because the observation registry -> observationConfig -> observationConvention method is expecting a GlobalObservationConvention<?> whereas a DefaultScheduledTaskObservationConvention is in a slight different chain of the ObservationConvention inheritance.

Would it be feasible/possible to let the ScheduledMethodRunnable arrange its convention similar to the RestClientObservationConfiguration for example, where a simple component or a bean extending the DefaultClientRequestObservationConvention is enough to be used as a custom convention for the http.client.requests metrics.

Not sure what is the reason, but these customizations of conventions seem to not follow a consistent approach in general, see the recently fixed situation for the DefaultMongoHandlerObservationConvention, also in general:

  • extending DefaultServerRequestObservationConvention // works like a charm for the http.server.requests metrics
  • extending DefaultClientRequestObservationConvention // works like a charm for the http.client.requests metrics
  • extending DefaultRepositoryTagsProvider // works like a charm for the spring.data.repository.invocations metrics though differs from first two ones
  • extending DefaultMongoCommandTagsProvider // works like a charm for the mongodb.driver.commands metrics though differs from first two ones
  • implementing GlobalObservationConvention<ScheduledTaskObservationContext> // works for the tasks.scheduled.execution metrics, but as described above - only after manually adding it as part of a custom bean configuration of the ObservationRegistryCustomizer<ObservationRegistry>...observationRegistry.observationConfig().observationConvention(...)
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 2, 2024
@bclozel bclozel added the theme: observability An issue related to observability and tracing label Apr 2, 2024
@bclozel bclozel self-assigned this Apr 2, 2024
@bclozel
Copy link
Member

bclozel commented Apr 2, 2024

Thanks for the report @hadjiski - I will look into this.

I agree that we are not consistent with allowing custom conventions locally, but this can be harder to achieve depending on how deep the integration is and how is it is to surface such an option into the configuration.

This though is making it impossible to re-use the default code from the DefaultScheduledTaskObservationConvention because the observation registry -> observationConfig -> observationConvention method is expecting a GlobalObservationConvention<?> whereas a DefaultScheduledTaskObservationConvention is in a slight different chain of the ObservationConvention inheritance.

To me the GlobalObservationConvention setup on the registry is meant for this - overriding a default convention configured by the Framework. I'm not sure why you think this is impossible, have you tried the following?

package io.spring.sample

import io.micrometer.common.KeyValue;
import io.micrometer.observation.GlobalObservationConvention;
import org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention;
import org.springframework.scheduling.support.ScheduledTaskObservationContext;

public class CustomScheduledTaskObservationConvention extends DefaultScheduledTaskObservationConvention 
		implements GlobalObservationConvention<ScheduledTaskObservationContext> {

	@Override
	protected KeyValue codeFunction(ScheduledTaskObservationContext context) {
		return super.codeFunction(context);
	}
	
}

@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Apr 2, 2024
@hadjiski
Copy link
Author

hadjiski commented Apr 2, 2024

Thank you @bclozel for the fast reply, I was so back and forth between all the ways to utilize the observations and their customizations, that I mixed it with the situation around the DefaultMongoHandlerObservationConvention which is defined as package private class and somehow it stayed in my mind.
Yes, extends DefaultScheduledTaskObservationConvention implements GlobalObservationConvention<ScheduledTaskObservationContext> would work.

Btw. how am I supposed to propagate business data from outside to the current observation resp. the provided context, so I can use it in the above overridden customized method to take some decisions.
Looking at this description I am trying to propagate it via the ObservationRegistry.getCurrentObservation() -> getContext() -> put to map, which almost always works, just for the http.server.requests it does not, but there we can fallback to using the HttpServletRequest and its attributes.
Now doing the same, does not appear to work for the observation for the scheduled tasks. Calling getCurrentObservation() returns null, also accessing the provided ScheduledTaskObservationContext is not the one, which was available outside as the business data was propagated to the current observation context, which at that time was spring.security.http.secured.requests one (I am using a regular Spring boot 3.2.3 rest controller application).

Explaining the solution for http.server.requests in more details:
Somewhere in the rest controller I am putting business data to the HttpServletRequest attributes, cause I know that they will be later available as context.getCarrier().getAttribute(...), so in a customizer like this I could access the business data

@Component
public class ServerRequestMetricsCustomizer extends DefaultServerRequestObservationConvention {
...
    @Override
    public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
        return super.getLowCardinalityKeyValues(context)
                 // context has to be passed as the only way to access the propagated business data
                .and(someMethodToExtractKeyValuesFromCarrierAttributes(context));
    }
}

Though the ScheduledTaskObservationContext does not appear to have such a carrier or other element, which is available in the outside area.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 2, 2024
@bclozel
Copy link
Member

bclozel commented Apr 2, 2024

@hadjiski getting the current observation from within the scheduled method should work, we have an integration test that verifies that. If you can reproduce the problem in a minimal sample application, please create a new issue and share that application.

@hadjiski
Copy link
Author

hadjiski commented Apr 2, 2024

@bclozel my bad, I had multiple scheduled methods and only for one of them setup the propagation.
After a closer look, I can confirm it working same like the example ServerRequestObservationContext just that not the carrier's attributes are to be used, rather the map of the context itself, thanks for the clarification

@hadjiski hadjiski closed this as completed Apr 2, 2024
@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2024
@snicoll snicoll added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid theme: observability An issue related to observability and tracing
Projects
None yet
Development

No branches or pull requests

4 participants