Skip to content

Commit 67a4086

Browse files
authored
Improvements to the HttpMeterFilterFactory (#766)
* Improvements to the HttpMeterFilterFactory - Added support for specifying service level objectives (allows the creation of apdex widgets). - Added support for specifying the expected max duration. - Added support for specifying the expected min duration. - Added support for histogram directly on the HttpMeterFilterFactory. - Removed the redundant HttpHistogramMeterFilterFactory. - Added tests for validating that the values are set correctly.
1 parent 9bc9f23 commit 67a4086

File tree

7 files changed

+238
-107
lines changed

7 files changed

+238
-107
lines changed

micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/HttpHistogramMeterFilterFactory.java

-79
This file was deleted.

micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/HttpMeterFilterFactory.java

+31-17
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@
1919
import io.micrometer.core.instrument.config.MeterFilter;
2020
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2121
import io.micronaut.configuration.metrics.annotation.RequiresMetrics;
22+
import io.micronaut.configuration.metrics.binder.web.config.HttpClientMeterConfig;
23+
import io.micronaut.configuration.metrics.binder.web.config.HttpMeterConfig;
24+
import io.micronaut.configuration.metrics.binder.web.config.HttpServerMeterConfig;
2225
import io.micronaut.context.annotation.Bean;
2326
import io.micronaut.context.annotation.Factory;
2427
import io.micronaut.context.annotation.Requires;
25-
import io.micronaut.context.annotation.Value;
26-
import io.micronaut.core.util.ArrayUtils;
2728
import jakarta.inject.Singleton;
2829

29-
import static io.micronaut.configuration.metrics.binder.web.WebMetricsPublisher.METRIC_HTTP_CLIENT_REQUESTS;
30-
import static io.micronaut.configuration.metrics.binder.web.WebMetricsPublisher.METRIC_HTTP_SERVER_REQUESTS;
30+
import java.util.Arrays;
31+
3132
import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS;
3233
import static io.micronaut.core.util.StringUtils.FALSE;
3334

@@ -41,41 +42,54 @@
4142
@Requires(property = WebMetricsPublisher.ENABLED, notEquals = FALSE)
4243
public class HttpMeterFilterFactory {
4344

45+
public static final double SECONDS_TO_NANOS = 1_000_000_000d;
46+
4447
/**
4548
* Configure new MeterFilter for http.server.requests metrics.
4649
*
47-
* @param percentiles The percentiles
50+
* @param serverMeterConfig The HttpMeter configuration
4851
* @return A MeterFilter
4952
*/
5053
@Bean
5154
@Singleton
52-
@Requires(property = MICRONAUT_METRICS_BINDERS + ".web.server.percentiles")
53-
MeterFilter addServerPercentileMeterFilter(@Value("${" + MICRONAUT_METRICS_BINDERS + ".web.server.percentiles}") Double[] percentiles) {
54-
return getMeterFilter(percentiles, METRIC_HTTP_SERVER_REQUESTS);
55+
@Requires(property = MICRONAUT_METRICS_BINDERS + ".web.server")
56+
MeterFilter addServerPercentileMeterFilter(HttpServerMeterConfig serverMeterConfig) {
57+
return getMeterFilter(serverMeterConfig, WebMetricsPublisher.METRIC_HTTP_SERVER_REQUESTS);
5558
}
5659

5760
/**
5861
* Configure new MeterFilter for http.client.requests metrics.
5962
*
60-
* @param percentiles The percentiles
63+
* @param clientMeterConfig The HttpMeter configuration
6164
* @return A MeterFilter
6265
*/
6366
@Bean
6467
@Singleton
65-
@Requires(property = MICRONAUT_METRICS_BINDERS + ".web.client.percentiles")
66-
MeterFilter addClientPercentileMeterFilter(@Value("${" + MICRONAUT_METRICS_BINDERS + ".web.client.percentiles}") Double[] percentiles) {
67-
return getMeterFilter(percentiles, METRIC_HTTP_CLIENT_REQUESTS);
68+
@Requires(property = MICRONAUT_METRICS_BINDERS + ".web.client")
69+
MeterFilter addClientPercentileMeterFilter(HttpClientMeterConfig clientMeterConfig) {
70+
return getMeterFilter(clientMeterConfig, WebMetricsPublisher.METRIC_HTTP_CLIENT_REQUESTS);
6871
}
6972

70-
private MeterFilter getMeterFilter(Double[] percentiles, String metricNamePrefix) {
73+
private MeterFilter getMeterFilter(HttpMeterConfig meterConfig, String metricNamePrefix) {
7174
return new MeterFilter() {
7275
@Override
7376
public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
7477
if (id.getName().startsWith(metricNamePrefix)) {
75-
return DistributionStatisticConfig.builder()
76-
.percentiles((double[]) ArrayUtils.toPrimitiveArray(percentiles))
77-
.build()
78-
.merge(config);
78+
var builder = DistributionStatisticConfig.builder()
79+
.percentiles()
80+
.percentiles(Arrays.stream(meterConfig.getPercentiles()).mapToDouble(Double::doubleValue).toArray())
81+
.serviceLevelObjectives(Arrays.stream(meterConfig.getSlos()).mapToDouble(d -> d * SECONDS_TO_NANOS).toArray())
82+
.percentilesHistogram(meterConfig.getHistogram());
83+
84+
if (meterConfig.getMin() != null) {
85+
builder.minimumExpectedValue(meterConfig.getMin() * SECONDS_TO_NANOS);
86+
}
87+
88+
if (meterConfig.getMax() != null) {
89+
builder.maximumExpectedValue(meterConfig.getMax() * SECONDS_TO_NANOS);
90+
}
91+
92+
return builder.build().merge(config);
7993
}
8094
return config;
8195
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2017-2024 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.configuration.metrics.binder.web.config;
17+
18+
import io.micronaut.context.annotation.ConfigurationProperties;
19+
20+
import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS;
21+
22+
/**
23+
* Http client meter configuration.
24+
* @since 5.6.0
25+
*/
26+
@ConfigurationProperties(MICRONAUT_METRICS_BINDERS + ".web.client")
27+
public class HttpClientMeterConfig extends HttpMeterConfig { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2017-2024 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.configuration.metrics.binder.web.config;
17+
18+
/**
19+
* Http meter configuration.
20+
* @since 5.6.0
21+
*/
22+
public abstract class HttpMeterConfig {
23+
24+
private Double[] percentiles = new Double[]{};
25+
private Boolean histogram = false;
26+
private Double min = null;
27+
private Double max = null;
28+
private Double[] slos = new Double[]{};
29+
30+
/**
31+
* Default is empty.
32+
* @return The percentiles. Specify in CSV format, ex: "0.95,0.99".
33+
*/
34+
public Double[] getPercentiles() {
35+
return percentiles;
36+
}
37+
38+
/**
39+
* Default is empty.
40+
* @param percentiles The percentiles. Specify in CSV format, ex: "0.95,0.99".
41+
*/
42+
public void setPercentiles(Double[] percentiles) {
43+
this.percentiles = percentiles;
44+
}
45+
46+
/**
47+
* Default: false.
48+
* @return If a histogram should be published.
49+
*/
50+
public Boolean getHistogram() {
51+
return histogram;
52+
}
53+
54+
/**
55+
* Default: false.
56+
* @param histogram If a histogram should be published.
57+
*/
58+
public void setHistogram(Boolean histogram) {
59+
this.histogram = histogram;
60+
}
61+
62+
/**
63+
* Default: Micrometer default value (0.001).
64+
* @return The minimum time (in s) value expected.
65+
*/
66+
public Double getMin() {
67+
return min;
68+
}
69+
70+
/**
71+
* Default: Micrometer default value (0.001).
72+
* @param min The minimum time (in s) value expected.
73+
*/
74+
public void setMin(Double min) {
75+
this.min = min;
76+
}
77+
78+
/**
79+
* Default: Micrometer default value (30).
80+
* @return The maximum time (in s) value expected.
81+
*/
82+
public Double getMax() {
83+
return max;
84+
}
85+
86+
/**
87+
* Default: Micrometer default value (30).
88+
* @param max The maximum time (in s) value expected.
89+
*/
90+
public void setMax(Double max) {
91+
this.max = max;
92+
}
93+
94+
/**
95+
* Default is empty.
96+
* @return The user-defined service levels objectives (in s) to create. Specify in CSV format, ex: "0.1,0.4".
97+
*/
98+
public Double[] getSlos() {
99+
return slos;
100+
}
101+
102+
/**
103+
* Default is empty.
104+
* @param slos The user-defined service levels objectives (in s) to create. Specify in CSV format, ex: "0.1,0.4".
105+
*/
106+
public void setSlos(Double[] slos) {
107+
this.slos = slos;
108+
}
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2017-2024 original authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micronaut.configuration.metrics.binder.web.config;
17+
18+
import io.micronaut.context.annotation.ConfigurationProperties;
19+
20+
import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS;
21+
22+
/**
23+
* Http server meter configuration.
24+
* @since 5.6.0
25+
*/
26+
@ConfigurationProperties(MICRONAUT_METRICS_BINDERS + ".web.server")
27+
public class HttpServerMeterConfig extends HttpMeterConfig { }

0 commit comments

Comments
 (0)