Skip to content

MeterBinder that uses Health infrastructure causes Rabbit metrics to be bound before meter registry customization has completed #15483

@tde-desc

Description

@tde-desc

Spring Boot version: 2.1.1
Micrometer version: 1.1.1

While defining a custom micrometer MeterRegistryCustomizer I had to face the following issue: The dependency chain of Spring Boot-HealthIndicator seems to interrupt the MeterRegistry bean creation at runtime. I will try to explain with the following setup. Given:

@Bean
public MicrometerConfiguration micrometerConfiguration() {
    return new MicrometerConfiguration();
}

@Bean
public HealthEndpointMeterBinder healthEndpointMetricRegistry(HealthEndpoint healthEndpoint) {
    return new HealthEndpointMeterBinder(healthEndpoint);
}

Are being defined as follows:

@RequiredArgsConstructor
public class MicrometerConfiguration implements MeterRegistryCustomizer {

    @Override
    public void customize(MeterRegistry registry) {
        // do something ...
    }
}

@RequiredArgsConstructor
public class HealthEndpointMeterBinder implements MeterBinder {
    private final HealthEndpoint healthEndpoint;

    @Override
    public void bindTo(MeterRegistry meterRegistry) {
        Gauge.builder("unhealthy", healthEndpoint,
                e -> e.health().getStatus() == Status.UP ? 0.0 : 1.0
        ).register(meterRegistry);
    }
}

In org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryPostProcessor#getConfigurer you can observe the process being interrupted which for example leads to org.springframework.boot.actuate.metrics.amqp.RabbitMetrics#bindTo being called before MicrometerConfiguration#customize. This results to not being able to register custom common tags for example.

I could solve this issue by defining the HealthIndicator dependency as ObjectProvider:

@RequiredArgsConstructor
public class HealthEndpointMeterBinder implements MeterBinder {
    private final ObjectProvider<HealthEndpoint> healthEndpoint;

    @Override
    public void bindTo(MeterRegistry meterRegistry) {
        Gauge.builder("unhealthy", healthEndpoint,
                e -> e.getIfAvailable().health().getStatus() == Status.UP ? 0.0 : 1.0
        ).register(meterRegistry);
    }
}

In my mind, injecting the HealthIndicator bean should not lead to the interruption of the MeterRegistry bean creation. I hope i could make myself clear ...

Regards
Dennis

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions