micrometer icon indicating copy to clipboard operation
micrometer copied to clipboard

Cannot configure UCUM units on Timer

Open brianrodecap opened this issue 3 weeks ago • 8 comments

When calling methods that use newTime (e.g., timer registration) in MeterRegistry, MeterFilter.configure() is invoked every time, even for existing meters. This results in MeterFilter values for units being reset, which is not the expected behavior. MeterFilter configuration—especially for units—should only be applied during meter creation, not on repeated lookups or reuse.

Steps to Reproduce:

  1. Register a timer and configure a MeterFilter to set unit values, such as with the following code:
@Bean
MeterRegistryCustomizer<OtlpMeterRegistry> otlpMeterIdCustomizer() {
    return (registry) -> registry.config().meterFilter(new MeterFilter() {
        @Override
        public Meter.Id map(Meter.Id id) {
            if ("http.server.request.duration".equals(id.getName())) {
                // Force base unit to 's' so OTLP exports the unit exactly as 's'.
                return id.withBaseUnit("s");
            }
            return id;
        }
    });
}
  1. Access the same timer again.

  2. Observe that unit values reset due to newTime invocation.

Suggested Fix: Configuration logic from MeterFilter (e.g., for units) should only apply during meter creation, not on retrieval. Cache the configuration on initial creation and reuse it on subsequent lookups. The goal is to support the export of UCUM units ("s" instead of "seconds").

Related code reference: https://github.com/micrometer-metrics/micrometer/blob/main/micrometer-core/src/main/java/io/micrometer/core/instrument/MeterRegistry.java#L375

brianrodecap avatar Dec 16 '25 20:12 brianrodecap

What version of Micrometer are you using? Could you provide a unit test that fails demonstrating the issue?

Since 1.13.0, we do not apply MeterFilters when retrieving existing meters - see https://github.com/micrometer-metrics/micrometer/issues/4856. I'm not following what you mean when you say the "unit values reset". Could you elaborate?

shakuzen avatar Dec 17 '25 02:12 shakuzen

OtlpConfig also lets you set you the unit, I guess you might want it to set it for every time-based meter not only for a single Timer.

jonatan-ivanov avatar Dec 17 '25 18:12 jonatan-ivanov

Adding a reproducer which logs the output of http.server.request.duration as "seconds" instead of "s" from the MetricFilter in OtlpConfiguration. This project is setup using Spring Boot 4/Java 25/Micrometer 1.16.0.

To generate metrics, execute the following curl or via Swagger

curl -X 'POST' \
  'http://localhost:8080/echo' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '"Hello World"'

otlp.zip

brianrodecap avatar Dec 17 '25 22:12 brianrodecap

I cleaned your project up and if you set management.otlp.metrics.export.baseTimeUnit: seconds (or OtlpConfig#baseTimeUnit), the unit is seconds:

[...]
    metrics {
      name: "http.server.request.duration"
      unit: "seconds"
[...]

This is because in Java TimeUnit.SECONDS will convert to seconds instead of s (and because time-based meters uses the base-unit of the registry). Form purely OTLP perspective, this is ok since OTLP does not specify if time units must be seconds, s, or something else. Is this causing issues to you? If so where do you send the OTLP data to?

If your goal is using UCUM time units I guess we can add a config flag to support that so that you can do something like this: otlpConfig#useUcumTimeUnit(true), (could be something like management.otlp.metrics.export.useUcumTimeUnit: true in Boot) but we need to discuss this first internally.

jonatan-ivanov avatar Dec 18 '25 00:12 jonatan-ivanov

Correct, we are using OTLP to export to a system which requires UCUM and follows the standard spec here: https://opentelemetry.io/docs/specs/semconv/http/http-metrics/

FYI - I did not include in my reproducer, but the standard buckets can be achieved using “slo” configuration. It would be advantageous to have a pre-defined option available.

brianrodecap avatar Dec 18 '25 01:12 brianrodecap

OTLP does not require UCUM, what you linked is semantic conventions (which does not require it either) but I think we should make it configurable anyways and enable you to use UCUM. Is this causing issues to you? If so where do you send the OTLP data to?

jonatan-ivanov avatar Dec 18 '25 02:12 jonatan-ivanov

Correct, the vendor is New Relic, and their direction is to strictly follow the semantic conventions linked above. Their platform digests the HTTP duration metric to produce their apm.service.transaction.duration metric.

https://docs.newrelic.com/docs/opentelemetry/get-started/apm-monitoring/opentelemetry-apm-ui/#metric-apmservicetransactionduration

brianrodecap avatar Dec 18 '25 02:12 brianrodecap

Thanks for the additional info. I think we understand now the need is support for UCUM units. We'll figure out where it makes sense for that to be configurable and to which units it should apply.

shakuzen avatar Dec 18 '25 07:12 shakuzen