Support property based MeterFilters
Add per-meter property support for `enabled`, `percentiles-histogram`, `percentiles` and `sla`. Fixes gh-11800pull/11932/merge
parent
6b70c96e37
commit
6889ad59b8
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or 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
|
||||
*
|
||||
* http://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 org.springframework.boot.actuate.autoconfigure.metrics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Meter.Id;
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
import io.micrometer.core.instrument.config.MeterFilterReply;
|
||||
import io.micrometer.core.instrument.histogram.HistogramConfig;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Distribution;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link MeterFilter} to apply settings from {@link MetricsProperties}.
|
||||
*
|
||||
* @author Jon Schneider
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class PropertiesMeterFilter implements MeterFilter {
|
||||
|
||||
private static final ServiceLevelAgreementBoundary[] EMPTY_SLA = {};
|
||||
|
||||
private MetricsProperties properties;
|
||||
|
||||
public PropertiesMeterFilter(MetricsProperties properties) {
|
||||
Assert.notNull(properties, "Properties must not be null");
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterFilterReply accept(Meter.Id id) {
|
||||
boolean enabled = lookup(this.properties.getEnable(), id, true);
|
||||
return (enabled ? MeterFilterReply.NEUTRAL : MeterFilterReply.DENY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistogramConfig configure(Meter.Id id, HistogramConfig config) {
|
||||
HistogramConfig.Builder builder = HistogramConfig.builder();
|
||||
Distribution distribution = this.properties.getDistribution();
|
||||
builder.percentilesHistogram(lookup(distribution.getPercentilesHistogram(), id, null));
|
||||
builder.percentiles(lookup(distribution.getPercentiles(), id, null));
|
||||
builder.sla(convertSla(id.getType(), lookup(distribution.getSla(), id, null)));
|
||||
return builder.build().merge(config);
|
||||
}
|
||||
|
||||
private long[] convertSla(Meter.Type meterType, ServiceLevelAgreementBoundary[] sla) {
|
||||
long[] converted = Arrays.stream(sla == null ? EMPTY_SLA : sla)
|
||||
.map((candidate) -> candidate.getValue(meterType))
|
||||
.filter(Objects::nonNull).mapToLong(Long::longValue).toArray();
|
||||
return (converted.length == 0 ? null : converted);
|
||||
}
|
||||
|
||||
private <T> T lookup(Map<String, T> values, Id id, T defaultValue) {
|
||||
String name = id.getName();
|
||||
while (StringUtils.hasLength(name)) {
|
||||
T result = values.get(name);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
name = lastDot == -1 ? "" : name.substring(0, lastDot);
|
||||
}
|
||||
return values.getOrDefault("all", defaultValue);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or 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
|
||||
*
|
||||
* http://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 org.springframework.boot.actuate.autoconfigure.metrics;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Meter.Type;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.convert.DurationConverter;
|
||||
|
||||
/**
|
||||
* A service level agreement boundary for use when configuring micrometer. Can be
|
||||
* specified as either a {@link Long} (applicable to timers and distribution summaries) or
|
||||
* a {@link Long} (applicable to only timers).
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public final class ServiceLevelAgreementBoundary {
|
||||
|
||||
private final Object value;
|
||||
|
||||
ServiceLevelAgreementBoundary(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
ServiceLevelAgreementBoundary(Duration value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying value of the SLA in form suitable to apply to the given meter
|
||||
* type.
|
||||
* @param meterType the meter type
|
||||
* @return the value or {@code null} if the value cannot be applied
|
||||
*/
|
||||
public Long getValue(Meter.Type meterType) {
|
||||
if (meterType == Type.DISTRIBUTION_SUMMARY) {
|
||||
return getDistributionSummaryValue();
|
||||
}
|
||||
if (meterType == Type.TIMER) {
|
||||
return getTimerValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Long getDistributionSummaryValue() {
|
||||
if (this.value instanceof Long) {
|
||||
return (Long) this.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Long getTimerValue() {
|
||||
if (this.value instanceof Long) {
|
||||
return TimeUnit.MILLISECONDS.toNanos((long) this.value);
|
||||
}
|
||||
if (this.value instanceof Duration) {
|
||||
return ((Duration) this.value).toNanos();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ServiceLevelAgreementBoundary valueOf(String value) {
|
||||
if (isNumber(value)) {
|
||||
return new ServiceLevelAgreementBoundary(Long.parseLong(value));
|
||||
}
|
||||
return new ServiceLevelAgreementBoundary(
|
||||
DurationConverter.toDuration(value, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link ServiceLevelAgreementBoundary} instance for the given long
|
||||
* value.
|
||||
* @param value the source value
|
||||
* @return a {@link ServiceLevelAgreementBoundary} instance
|
||||
*/
|
||||
public static ServiceLevelAgreementBoundary valueOf(long value) {
|
||||
return new ServiceLevelAgreementBoundary(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link ServiceLevelAgreementBoundary} instance for the given String
|
||||
* value. The value may contain a simple number, or a {@link DurationConverter
|
||||
* duration formatted value}
|
||||
* @param value the source value
|
||||
* @return a {@link ServiceLevelAgreementBoundary} instance
|
||||
*/
|
||||
private static boolean isNumber(String value) {
|
||||
return value.chars().allMatch(Character::isDigit);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or 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
|
||||
*
|
||||
* http://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 org.springframework.boot.actuate.autoconfigure.metrics;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Meter.Id;
|
||||
import io.micrometer.core.instrument.Meter.Type;
|
||||
import io.micrometer.core.instrument.config.MeterFilterReply;
|
||||
import io.micrometer.core.instrument.histogram.HistogramConfig;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests fir {@link PropertiesMeterFilter}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Jon Schneider
|
||||
*/
|
||||
public class PropertiesMeterFilterTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private HistogramConfig config;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenPropertiesIsNullShouldThrowException() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Properties must not be null");
|
||||
new PropertiesMeterFilter(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasNoEnabledPropertiesShouldReturnNeutral() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties());
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasEnableFalseShouldReturnDeny() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring.boot=false"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.DENY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasEnableTrueShouldReturnNeutral() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring.boot=true"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasHigherEnableFalseShouldReturnDeny() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring=false"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.DENY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasHigherEnableTrueShouldReturnNeutral() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring=true"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasHigherEnableFalseExactEnableTrueShouldReturnNeutral() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring=false", "enable.spring.boot=true"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasHigherEnableTrueExactEnableFalseShouldReturnDeny() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.spring=true", "enable.spring.boot=false"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.DENY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasAllEnableFalseShouldReturnDeny() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.all=false"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.DENY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptWhenHasAllEnableFalseButHigherEnableTrueShouldReturnNeutral() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("enable.all=false", "enable.spring=true"));
|
||||
assertThat(filter.accept(createMeterId("spring.boot")))
|
||||
.isEqualTo(MeterFilterReply.NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHistogramTrueShouldSetPercentilesHistogramToTrue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring.boot=true"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHistogramFalseShouldSetPercentilesHistogramToFalse() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring.boot=false"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherHistogramTrueShouldSetPercentilesHistogramToTrue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring=true"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherHistogramFalseShouldSetPercentilesHistogramToFalse() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring=false"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherHistogramTrueAndLowerFalseShouldSetPercentilesHistogramToFalse() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring=true",
|
||||
"distribution.percentiles-histogram.spring.boot=false"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherHistogramFalseAndLowerTrueShouldSetPercentilesHistogramToFalse() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.spring=false",
|
||||
"distribution.percentiles-histogram.spring.boot=true"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenAllHistogramTrueSetPercentilesHistogramToTrue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles-histogram.all=true"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.isPercentileHistogram()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasPercentilesShouldSetPercentilesToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles.spring.boot=1,1.5,2"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getPercentiles()).containsExactly(1, 1.5, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherPercentilesShouldSetPercentilesToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles.spring=1,1.5,2"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getPercentiles()).containsExactly(1, 1.5, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherPercentilesAndLowerShouldSetPercentilesToHigher() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles.spring=1,1.5,2",
|
||||
"distribution.percentiles.spring.boot=3,3.5,4"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getPercentiles()).containsExactly(3, 3.5, 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenAllPercentilesSetShouldSetPercentilesToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.percentiles.all=1,1.5,2"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getPercentiles()).containsExactly(1, 1.5, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasSlaShouldSetSlaToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.sla.spring.boot=1,2,3"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getSlaBoundaries()).containsExactly(1000000, 2000000, 3000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherSlaShouldSetPercentilesToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.sla.spring=1,2,3"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getSlaBoundaries()).containsExactly(1000000, 2000000, 3000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenHasHigherSlaAndLowerShouldSetSlaToHigher() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties(
|
||||
"distribution.sla.spring=1,2,3", "distribution.sla.spring.boot=4,5,6"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getSlaBoundaries()).containsExactly(4000000, 5000000, 6000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenAllSlaSetShouldSetSlaToValue() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.sla.all=1,2,3"));
|
||||
assertThat(filter.configure(createMeterId("spring.boot"), HistogramConfig.DEFAULT)
|
||||
.getSlaBoundaries()).containsExactly(1000000, 2000000, 3000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenSlaDurationShouldOnlyApplyToTimer() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.sla.all=1ms,2ms,3ms"));
|
||||
Meter.Id timer = createMeterId("spring.boot", Meter.Type.TIMER);
|
||||
Meter.Id summary = createMeterId("spring.boot", Meter.Type.DISTRIBUTION_SUMMARY);
|
||||
Meter.Id counter = createMeterId("spring.boot", Meter.Type.COUNTER);
|
||||
assertThat(filter.configure(timer, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.containsExactly(1000000, 2000000, 3000000);
|
||||
assertThat(filter.configure(summary, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.isEmpty();
|
||||
assertThat(filter.configure(counter, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenSlaLongShouldOnlyApplyToTimerAndDistributionSummary() {
|
||||
PropertiesMeterFilter filter = new PropertiesMeterFilter(
|
||||
createProperties("distribution.sla.all=1,2,3"));
|
||||
Meter.Id timer = createMeterId("spring.boot", Meter.Type.TIMER);
|
||||
Meter.Id summary = createMeterId("spring.boot", Meter.Type.DISTRIBUTION_SUMMARY);
|
||||
Meter.Id counter = createMeterId("spring.boot", Meter.Type.COUNTER);
|
||||
assertThat(filter.configure(timer, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.containsExactly(1000000, 2000000, 3000000);
|
||||
assertThat(filter.configure(summary, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.containsExactly(1, 2, 3);
|
||||
assertThat(filter.configure(counter, HistogramConfig.DEFAULT).getSlaBoundaries())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private Id createMeterId(String name) {
|
||||
Meter.Type meterType = Type.TIMER;
|
||||
return createMeterId(name, meterType);
|
||||
}
|
||||
|
||||
private Id createMeterId(String name, Meter.Type meterType) {
|
||||
TestMeterRegistry registry = new TestMeterRegistry();
|
||||
return Meter.builder(name, meterType, Collections.emptyList()).register(registry)
|
||||
.getId();
|
||||
}
|
||||
|
||||
private MetricsProperties createProperties(String... properties) {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
TestPropertyValues.of(properties).applyTo(environment);
|
||||
Binder binder = Binder.get(environment);
|
||||
return binder.bind("", Bindable.of(MetricsProperties.class))
|
||||
.orElseGet(MetricsProperties::new);
|
||||
}
|
||||
|
||||
private static class TestMeterRegistry extends SimpleMeterRegistry {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or 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
|
||||
*
|
||||
* http://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 org.springframework.boot.actuate.autoconfigure.metrics;
|
||||
|
||||
import io.micrometer.core.instrument.Meter.Type;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServiceLevelAgreementBoundary}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ServiceLevelAgreementBoundaryTests {
|
||||
|
||||
@Test
|
||||
public void getValueForDistributionSummaryWhenFromLongShouldReturnLongValue() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf(123L);
|
||||
assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForDistributionSummaryWhenFromNumberStringShouldReturnLongValue() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123");
|
||||
assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForDistributionSummaryWhenFromDurationStringShouldReturnNull() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary
|
||||
.valueOf("123ms");
|
||||
assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForTimerWhenFromLongShouldReturnMsToNanosValue() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf(123L);
|
||||
assertThat(sla.getValue(Type.TIMER)).isEqualTo(123000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForTimerWhenFromNumberStringShouldMsToNanosValue() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123");
|
||||
assertThat(sla.getValue(Type.TIMER)).isEqualTo(123000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForTimerWhenFromDurationStringShouldReturnDrationNanos() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary
|
||||
.valueOf("123ms");
|
||||
assertThat(sla.getValue(Type.TIMER)).isEqualTo(123000000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueForOthersShouldReturnNull() {
|
||||
ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123");
|
||||
assertThat(sla.getValue(Type.COUNTER)).isNull();
|
||||
assertThat(sla.getValue(Type.GAUGE)).isNull();
|
||||
assertThat(sla.getValue(Type.LONG_TASK_TIMER)).isNull();
|
||||
assertThat(sla.getValue(Type.OTHER)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueOfShouldWorkInBinder() {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
TestPropertyValues.of("duration=10ms", "long=20").applyTo(environment);
|
||||
assertThat(Binder.get(environment)
|
||||
.bind("duration", Bindable.of(ServiceLevelAgreementBoundary.class)).get()
|
||||
.getValue(Type.TIMER)).isEqualTo(10000000);
|
||||
assertThat(Binder.get(environment)
|
||||
.bind("long", Bindable.of(ServiceLevelAgreementBoundary.class)).get()
|
||||
.getValue(Type.TIMER)).isEqualTo(20000000);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or 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
|
||||
*
|
||||
* http://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 org.springframework.boot.actuate.metrics;
|
||||
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Example to show a {@link MeterFilter}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class MetricsFilterBeanExample {
|
||||
|
||||
@Configuration
|
||||
static class MetricsFilterExampleConfiguration {
|
||||
|
||||
// tag::configuration[]
|
||||
@Bean
|
||||
public MeterFilter renameRegionTagMeterFilter() {
|
||||
return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
|
||||
}
|
||||
// end::configuration[]
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue