From bb89ba52bd78832f679d513d0b972e1b5bd7326e Mon Sep 17 00:00:00 2001 From: Pedro Ruivo Date: Mon, 28 Nov 2022 18:18:45 +0000 Subject: [PATCH] ISPN-14341 Allow injecting a MeterRegistry instance --- ...eterMeterRegisterConfigurationBuilder.java | 70 +++++++++++++++++++ .../MicrometerMeterRegistryConfiguration.java | 51 ++++++++++++++ ...rMeterRegistryConfigurationSerializer.java | 18 +++++ .../metrics/impl/MetricsCollector.java | 17 +++-- .../rest/resources/MetricsResource.java | 8 ++- 5 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegisterConfigurationBuilder.java create mode 100644 core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfiguration.java create mode 100644 core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfigurationSerializer.java diff --git a/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegisterConfigurationBuilder.java b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegisterConfigurationBuilder.java new file mode 100644 index 000000000000..4257f9b3a60b --- /dev/null +++ b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegisterConfigurationBuilder.java @@ -0,0 +1,70 @@ +package org.infinispan.metrics.config; + +import java.util.Objects; + +import org.infinispan.commons.configuration.Builder; +import org.infinispan.configuration.global.GlobalConfigurationBuilder; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.prometheus.PrometheusMeterRegistry; + +/** + * Builder to inject an instance of {@link MeterRegistry}. + *

+ * If not configured, Infinispan will create a new instance of {@link PrometheusMeterRegistry}. + * + * @since 15.0 + */ +public class MicrometerMeterRegisterConfigurationBuilder implements Builder { + + private MeterRegistry meterRegistry; + + public MicrometerMeterRegisterConfigurationBuilder(GlobalConfigurationBuilder builder) { + //required because GlobalConfigurationBuilder#addModule uses reflection + } + + /** + * Set the {@link MeterRegistry} instance to use by Infinispan. + *

+ * If set to {@code null}, Infinispan will create a new instance of {@link PrometheusMeterRegistry}. + * + * @param registry The {@link MeterRegistry} to use or {@code null}. + */ + public MicrometerMeterRegisterConfigurationBuilder meterRegistry(MeterRegistry registry) { + meterRegistry = registry; + return this; + } + + @Override + public MicrometerMeterRegistryConfiguration create() { + return new MicrometerMeterRegistryConfiguration(meterRegistry); + } + + @Override + public MicrometerMeterRegisterConfigurationBuilder read(MicrometerMeterRegistryConfiguration template) { + meterRegistry(template.meterRegistry()); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MicrometerMeterRegisterConfigurationBuilder)) return false; + + MicrometerMeterRegisterConfigurationBuilder that = (MicrometerMeterRegisterConfigurationBuilder) o; + + return Objects.equals(meterRegistry, that.meterRegistry); + } + + @Override + public int hashCode() { + return meterRegistry != null ? meterRegistry.hashCode() : 0; + } + + @Override + public String toString() { + return "MicrometerMeterRegisterConfigurationBuilder{" + + "meterRegistry=" + meterRegistry + + '}'; + } +} diff --git a/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfiguration.java b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfiguration.java new file mode 100644 index 000000000000..0e61e129705c --- /dev/null +++ b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfiguration.java @@ -0,0 +1,51 @@ +package org.infinispan.metrics.config; + +import java.util.Objects; + +import org.infinispan.configuration.serializing.SerializedWith; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * A configuration class to inject a custom {@link MeterRegistry} instance. + * + * @since 15.0 + */ +@SerializedWith(MicrometerMeterRegistryConfigurationSerializer.class) +public class MicrometerMeterRegistryConfiguration { + + private final MeterRegistry registry; + + public MicrometerMeterRegistryConfiguration(MeterRegistry registry) { + this.registry = registry; + } + + /** + * @return The {@link MeterRegistry} instance injected or {@code null} if not configured. + */ + public MeterRegistry meterRegistry() { + return registry; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MicrometerMeterRegistryConfiguration)) return false; + + MicrometerMeterRegistryConfiguration that = (MicrometerMeterRegistryConfiguration) o; + + return Objects.equals(registry, that.registry); + } + + @Override + public int hashCode() { + return registry != null ? registry.hashCode() : 0; + } + + @Override + public String toString() { + return "MicrometerMeterRegistryConfiguration{" + + "registry=" + registry + + '}'; + } +} diff --git a/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfigurationSerializer.java b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfigurationSerializer.java new file mode 100644 index 000000000000..a5e11c80d77e --- /dev/null +++ b/core/src/main/java/org/infinispan/metrics/config/MicrometerMeterRegistryConfigurationSerializer.java @@ -0,0 +1,18 @@ +package org.infinispan.metrics.config; + +import org.infinispan.commons.configuration.io.ConfigurationWriter; +import org.infinispan.configuration.serializing.ConfigurationSerializer; + +/** + * A {@link ConfigurationSerializer} implementation to serialize {@link MicrometerMeterRegistryConfiguration}. + *

+ * This class is a no-op. + * + * @since 15.0 + */ +public class MicrometerMeterRegistryConfigurationSerializer implements ConfigurationSerializer { + @Override + public void serialize(ConfigurationWriter writer, MicrometerMeterRegistryConfiguration configuration) { + //no-op + } +} diff --git a/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java b/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java index e4744d68326e..964e6df321c9 100644 --- a/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java +++ b/core/src/main/java/org/infinispan/metrics/impl/MetricsCollector.java @@ -24,12 +24,14 @@ import org.infinispan.factories.scopes.Scope; import org.infinispan.factories.scopes.Scopes; import org.infinispan.metrics.Constants; +import org.infinispan.metrics.config.MicrometerMeterRegistryConfiguration; import org.infinispan.remoting.transport.Transport; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Timer; import io.micrometer.prometheus.PrometheusConfig; @@ -48,7 +50,7 @@ public class MetricsCollector implements Constants { private static final Log log = LogFactory.getLog(MetricsCollector.class); - private PrometheusMeterRegistry registry; + private MeterRegistry registry; private Tag nodeTag; @@ -64,12 +66,12 @@ protected MetricsCollector() { } public PrometheusMeterRegistry registry() { - return registry; + return registry instanceof PrometheusMeterRegistry ? (PrometheusMeterRegistry) registry : null; } @Start protected void start() { - registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + createMeterRegistry(); new BaseAdditionalMetrics().bindTo(registry); new VendorAdditionalMetrics().bindTo(registry); @@ -122,7 +124,6 @@ private static String generateRandomName() { return hostName + '-' + rand; } - @SuppressWarnings("unchecked") public Set registerMetrics(Object instance, Collection attributes, String namePrefix, String cacheName) { return registerMetrics(instance, attributes, namePrefix, asTag(CACHE_TAG_NAME, cacheName), nodeTag); } @@ -215,4 +216,12 @@ public void unregisterMetric(Object metricId) { } } } + + private void createMeterRegistry() { + MicrometerMeterRegistryConfiguration configuration = globalConfig.module(MicrometerMeterRegistryConfiguration.class); + registry = configuration == null ? null : configuration.meterRegistry(); + if (registry == null) { + registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + } + } } diff --git a/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java b/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java index 550ccd462ca8..b9f50f40142a 100644 --- a/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java +++ b/server/rest/src/main/java/org/infinispan/rest/resources/MetricsResource.java @@ -1,6 +1,7 @@ package org.infinispan.rest.resources; import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR; +import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND; import static org.infinispan.rest.framework.Method.GET; import static org.infinispan.rest.framework.Method.OPTIONS; @@ -17,6 +18,7 @@ import org.infinispan.rest.framework.impl.Invocations; import org.infinispan.rest.framework.impl.RestResponseBuilder; +import io.micrometer.prometheus.PrometheusMeterRegistry; import io.prometheus.client.exporter.common.TextFormat; /** @@ -52,9 +54,13 @@ private CompletionStage metrics(RestRequest restRequest) { RestResponseBuilder builder = new NettyRestResponse.Builder(); try { + PrometheusMeterRegistry registry = metricsCollector.registry(); + if (registry == null) { + return builder.status(NOT_FOUND.code()).build(); + } String contentType = TextFormat.chooseContentType(restRequest.getAcceptHeader()); builder.header("Content-Type", contentType); - builder.entity(metricsCollector.registry().scrape(contentType)); + builder.entity(registry.scrape(contentType)); return builder.build(); } catch (Exception e) {