From 0addec6b68e4a8fd1f2489041fe7555d7ee2d930 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 19 Nov 2025 14:41:35 +0100 Subject: [PATCH] Fix bug in SslMeterBinder when binding without registered bundles Before this commit the meter registries were derived from the created gauges. If the SslMeterBinder has been bound to a MeterRegistry without any bundles, then no gauges are created. If a SslBundle is then dynamically added, onBundleChange is called with the new bundle, but the list of meter registries is empty (because we have no gauges). The effect is that the newly registered bundle has no metrics. Closes gh-48180 --- .../autoconfigure/ssl/SslMeterBinder.java | 27 +++---------------- .../ssl/SslMeterBinderTests.java | 8 ++++++ 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java index d441d893750..2362e5b4315 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinder.java @@ -21,9 +21,7 @@ import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; -import java.util.Collection; import java.util.Comparator; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -58,6 +56,8 @@ class SslMeterBinder implements MeterBinder { private final BundleMetrics bundleMetrics = new BundleMetrics(); + private final Set boundMeterRegistries = ConcurrentHashMap.newKeySet(); + SslMeterBinder(SslInfo sslInfo, SslBundles sslBundles) { this(sslInfo, sslBundles, Clock.systemDefaultZone()); } @@ -77,13 +77,14 @@ class SslMeterBinder implements MeterBinder { private void onBundleChange(String bundleName) { BundleInfo bundle = this.sslInfo.getBundle(bundleName); this.bundleMetrics.updateBundle(bundle); - for (MeterRegistry meterRegistry : this.bundleMetrics.getMeterRegistries()) { + for (MeterRegistry meterRegistry : this.boundMeterRegistries) { createOrUpdateBundleMetrics(meterRegistry, bundle); } } @Override public void bindTo(MeterRegistry meterRegistry) { + this.boundMeterRegistries.add(meterRegistry); for (BundleInfo bundle : this.sslInfo.getBundles()) { createOrUpdateBundleMetrics(meterRegistry, bundle); } @@ -138,18 +139,6 @@ class SslMeterBinder implements MeterBinder { return gauges.getGauge(meterRegistry); } - /** - * Returns all meter registries. - * @return all meter registries - */ - Collection getMeterRegistries() { - Set result = new HashSet<>(); - for (Gauges metrics : this.gauges.values()) { - result.addAll(metrics.getMeterRegistries()); - } - return result; - } - /** * Updates the given bundle. * @param bundle the updated bundle @@ -184,14 +173,6 @@ class SslMeterBinder implements MeterBinder { return new Gauges(bundle, this.multiGauges); } - /** - * Returns all meter registries. - * @return all meter registries - */ - Set getMeterRegistries() { - return this.multiGauges.keySet(); - } - private MultiGauge createGauge(MeterRegistry meterRegistry) { return MultiGauge.builder(CHAIN_EXPIRY_METRIC_NAME) .baseUnit("seconds") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java index 7c864358c84..7c77eaba9c1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/ssl/SslMeterBinderTests.java @@ -88,6 +88,14 @@ class SslMeterBinderTests { .hasDays(36889); } + @Test + void shouldRegisterMetricsIfNoBundleExistsAtBindTime() { + DefaultSslBundleRegistry sslBundleRegistry = new DefaultSslBundleRegistry(); + MeterRegistry meterRegistry = bindToRegistry(sslBundleRegistry); + sslBundleRegistry.registerBundle("dummy", SslBundle.of(createSslStoreBundle("classpath:test.p12"))); + assertThat(meterRegistry.getMeters()).isNotEmpty(); + } + private long findExpiryGauge(MeterRegistry meterRegistry, String chain, String certificateSerialNumber) { return (long) meterRegistry.get("ssl.chain.expiry") .tag("bundle", "test-0")