spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.09k stars 40.67k forks source link

Missing functionality or Different behavior of ServerRequestObservationConvention, does not provide a way to add tags to long task timers #41747

Open santoshdahal12 opened 2 months ago

santoshdahal12 commented 2 months ago

With Spring boot 2.7 and earlier, WebMvcTagsProvider had a method that allowed to add custom tags for long task timers. However, after migrating to Spring Boot 3.3 and using recommended migration strategy of extending DefaultServerRequestObservationConvention or implementing ServerRequestObservationConvention from the docs here, the behavior is not the same.

The getLowCardinalityKeyValues method cannot be used to add custom tags to long task timers or handlers annotated with for example @ Timed(value = "aws.scrape", longTask = true)

The migration guide does not speak anything about this missed functionality and I found few developers asking questions in stackoverflow not being answered. So wanted to know if there is any guidance about this ?

mhalbritter commented 2 months ago

DefaultServerRequestObservationConvention or ServerRequestObservationConvention work on observations.

The @Timed annotation you used doesn't create an observation, it creates a metric directly.

To add a tag to a metric, you can use a MeterFilter:

    @Bean
    MeterFilter meterFilter() {
        return new MeterFilter() {
            @Override
            public Meter.Id map(Meter.Id id) {
                if (id.getName().equals("aws.scrape")) {
                    return id.withTag(Tag.of("additional", "tag"));
                }
                return id;
            }
        };
    }

If you want to have an observation instead, use @Observed, but AFAIK, this doesn't use long task timers.

Btw, ServerRequestObservationConvention only works for the observations created by framework itself for the http request (which is by default named http.server.requests) and is not called for your observation created by @Observed.

Does that solve your problem?

santoshdahal12 commented 2 months ago

The problem statement is to add custom tags to long task timers annotated in the handlers of a controller in a centralized way without knowing specific metername

This was exactly solved by WebMvcMetricsFilter before.

The earlier implementation i.e till 2.7.18, WebMvcMetricFilter had a logic to get all Timed annotations from the handler of the controller and allowed to add custom tags for long task timers via WebMvcTagsProvider . For reference, this is the filter . This was nice because we had a centralized way of adding custom tags for handlers with long task timers.

MeterFilter does not know about request context and thus it's not straightforward to differentiate if the metric is from handlers of a controller or it's coming from any scheduled service or from somewhere else.

Any thoughts on how we could achieve the same ? or at least we could mention in migration documentation about this missed fucntionality and guidance on how to achieve the same

mhalbritter commented 2 months ago

@marcingrzejszczak @jonatan-ivanov Do you know any solution to this?