diff --git a/micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/HttpHistogramMeterFilterFactory.java b/micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/HttpHistogramMeterFilterFactory.java new file mode 100644 index 000000000..a1d48a253 --- /dev/null +++ b/micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/HttpHistogramMeterFilterFactory.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.configuration.metrics.binder.web; + +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.config.MeterFilter; +import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; +import io.micronaut.configuration.metrics.annotation.RequiresMetrics; +import io.micronaut.context.annotation.*; +import jakarta.inject.Singleton; + +import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS; +import static io.micronaut.core.util.StringUtils.FALSE; + +/** + * Optional filter for adding histograms to HTTP metrics. + * + * @author lcavadas + */ +@Factory +@RequiresMetrics +@Requires(property = WebMetricsPublisher.ENABLED, notEquals = FALSE) +@Primary +public class HttpHistogramMeterFilterFactory { + + /** + * Configure new MeterFilter for http.server.requests metrics. + * + * @param histogram If a histogram should be published + * @return A MeterFilter + */ + @Bean + @Singleton + @Requires(property = MICRONAUT_METRICS_BINDERS + ".web.server.histogram") + MeterFilter addServerPercentileMeterFilter(@Value("${" + MICRONAUT_METRICS_BINDERS + ".web.server.histogram}") Boolean histogram) { + return getMeterFilter(histogram, WebMetricsPublisher.METRIC_HTTP_SERVER_REQUESTS); + } + + /** + * Configure new MeterFilter for http.client.requests metrics. + * + * @param histogram If a histogram should be published + * @return A MeterFilter + */ + @Bean + @Singleton + @Requires(property = MICRONAUT_METRICS_BINDERS + ".web.client.histogram") + MeterFilter addClientPercentileMeterFilter(@Value("${" + MICRONAUT_METRICS_BINDERS + ".web.client.histogram}") Boolean histogram) { + return getMeterFilter(histogram, WebMetricsPublisher.METRIC_HTTP_CLIENT_REQUESTS); + } + + private MeterFilter getMeterFilter(Boolean histogram, String metricNamePrefix) { + return new MeterFilter() { + @Override + public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { + if (id.getName().startsWith(metricNamePrefix)) { + return DistributionStatisticConfig.builder() + .percentilesHistogram(histogram) + .build() + .merge(config); + } + return config; + } + }; + } +} diff --git a/micrometer-core/src/test/groovy/io/micronaut/configuration/metrics/binder/web/HttpMetricsSpec.groovy b/micrometer-core/src/test/groovy/io/micronaut/configuration/metrics/binder/web/HttpMetricsSpec.groovy index b0a135f23..16645a255 100644 --- a/micrometer-core/src/test/groovy/io/micronaut/configuration/metrics/binder/web/HttpMetricsSpec.groovy +++ b/micrometer-core/src/test/groovy/io/micronaut/configuration/metrics/binder/web/HttpMetricsSpec.groovy @@ -55,6 +55,8 @@ class HttpMetricsSpec extends Specification { clientTimer.count() == 1 serverSnapshot.percentileValues().length == serverPercentilesCount clientSnapshot.percentileValues().length == clientPercentilesCount + serverTimer.getMetaPropertyValues().find { it.name.equals('distributionStatisticConfig') }.value.percentileHistogram == serverHistogram + clientTimer.getMetaPropertyValues().find { it.name.equals('distributionStatisticConfig') }.value.percentileHistogram == clientHistogram when: "A request is sent to the root route" @@ -135,9 +137,13 @@ class HttpMetricsSpec extends Specification { embeddedServer.close() where: - cfg | setting | serverPercentilesCount | clientPercentilesCount - MICRONAUT_METRICS_BINDERS + ".web.client.percentiles" | "0.95,0.99" | 0 | 2 - MICRONAUT_METRICS_BINDERS + ".web.server.percentiles" | "0.95,0.99" | 2 | 0 + cfg | setting | serverPercentilesCount | clientPercentilesCount| serverHistogram | clientHistogram + MICRONAUT_METRICS_BINDERS + ".web.client.percentiles" | "0.95,0.99" | 0 | 2 | null | null + MICRONAUT_METRICS_BINDERS + ".web.server.percentiles" | "0.95,0.99" | 2 | 0 | null | null + MICRONAUT_METRICS_BINDERS + ".web.server.histogram" | "true" | 0 | 0 | true | null + MICRONAUT_METRICS_BINDERS + ".web.server.histogram" | "false" | 0 | 0 | false | null + MICRONAUT_METRICS_BINDERS + ".web.client.histogram" | "true" | 0 | 0 | null | true + MICRONAUT_METRICS_BINDERS + ".web.client.histogram" | "false" | 0 | 0 | null | false } void "test client / server metrics ignored uris for client errors"() {