From 4b81548502bb984b1897d18bdba2a287e1c887d0 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 4 Apr 2020 14:57:34 +0200 Subject: [PATCH 01/11] Start building against Micrometer 1.5.0 snapshots See gh-20833 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 5967e2eb44..ea0b1de51b 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1182,7 +1182,7 @@ bom { ] } } - library("Micrometer", "1.3.7") { + library("Micrometer", "1.5.0-SNAPSHOT") { group("io.micrometer") { modules = [ "micrometer-registry-stackdriver" { From 08533c79e07998be64a560969edf500eece0a2c4 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 4 Apr 2020 14:59:06 +0200 Subject: [PATCH 02/11] Update default value for Datadog's default uri See gh-20833 --- .../metrics/export/datadog/DatadogProperties.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogProperties.java index f042358d64..139c16fd98 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -56,7 +56,7 @@ public class DatadogProperties extends StepRegistryProperties { * URI to ship metrics to. If you need to publish metrics to an internal proxy * en-route to Datadog, you can define the location of the proxy with this. */ - private String uri = "https://app.datadoghq.com"; + private String uri = "https://api.datadoghq.com"; public String getApiKey() { return this.apiKey; From 4813606b70139885e3799d8e39cda4270dad5077 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 4 Apr 2020 15:14:35 +0200 Subject: [PATCH 03/11] Expose Graphite's graphiteTagsEnabled property This commit exposes an additional property for Graphite that allows to restore the previous default behaviour with regards to tags, i.e. prefixing the ones defined by the "tagsAsPrefix" property. Close gh-20834 --- .../export/graphite/GraphiteProperties.java | 20 ++++++++++++++++--- .../GraphitePropertiesConfigAdapter.java | 7 ++++++- ...teMetricsExportAutoConfigurationTests.java | 17 ++++++++++++++-- .../graphite/GraphitePropertiesTests.java | 3 ++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteProperties.java index d5eb861b8d..3dec132528 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -70,8 +70,14 @@ public class GraphiteProperties { private GraphiteProtocol protocol = GraphiteProtocol.PICKLED; /** - * For the default naming convention, turn the specified tag keys into part of the - * metric prefix. + * Whether Graphite tags should be used, as opposed to a hierarchical naming + * convention. + */ + private boolean graphiteTagsEnabled = true; + + /** + * For the hierarchical naming convention, turn the specified tag keys into part of + * the metric prefix. Ignored if "graphiteTagsEnabled" is true. */ private String[] tagsAsPrefix = new String[0]; @@ -131,6 +137,14 @@ public class GraphiteProperties { this.protocol = protocol; } + public boolean isGraphiteTagsEnabled() { + return this.graphiteTagsEnabled; + } + + public void setGraphiteTagsEnabled(boolean graphiteTagsEnabled) { + this.graphiteTagsEnabled = graphiteTagsEnabled; + } + public String[] getTagsAsPrefix() { return this.tagsAsPrefix; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesConfigAdapter.java index 7f3067e163..bc89039799 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesConfigAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -76,6 +76,11 @@ class GraphitePropertiesConfigAdapter extends PropertiesConfigAdapter assertThat(context).doesNotHaveBean(GraphiteMeterRegistry.class)); } + @Test + void autoConfiguresUseTagsAsPrefixIsIgnoredByDefault() { + this.contextRunner.withUserConfiguration(BaseConfiguration.class) + .withPropertyValues("management.metrics.export.graphite.tags-as-prefix=ignored").run((context) -> { + assertThat(context).hasSingleBean(GraphiteMeterRegistry.class); + GraphiteMeterRegistry registry = context.getBean(GraphiteMeterRegistry.class); + registry.counter("test.count", Tags.of("app", "myapp")); + assertThat(registry.getDropwizardRegistry().getMeters()).containsOnlyKeys("test.count;app=myapp"); + }); + } + @Test void autoConfiguresUseTagsAsPrefix() { this.contextRunner.withUserConfiguration(BaseConfiguration.class) - .withPropertyValues("management.metrics.export.graphite.tags-as-prefix=app").run((context) -> { + .withPropertyValues("management.metrics.export.graphite.tags-as-prefix=app", + "management.metrics.export.graphite.graphite-tags-enabled=false") + .run((context) -> { assertThat(context).hasSingleBean(GraphiteMeterRegistry.class); GraphiteMeterRegistry registry = context.getBean(GraphiteMeterRegistry.class); registry.counter("test.count", Tags.of("app", "myapp")); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesTests.java index 54aef944a3..5e0ed18fc5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphitePropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -39,6 +39,7 @@ class GraphitePropertiesTests { assertThat(properties.getHost()).isEqualTo(config.host()); assertThat(properties.getPort()).isEqualTo(config.port()); assertThat(properties.getProtocol()).isEqualTo(config.protocol()); + assertThat(properties.isGraphiteTagsEnabled()).isEqualTo(config.graphiteTagsEnabled()); assertThat(properties.getTagsAsPrefix()).isEqualTo(config.tagsAsPrefix()); } From 30201a40e04a46523ac3c2a4d2843cf16d7db331 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 11:44:30 +0200 Subject: [PATCH 04/11] Update SLA boundaries to use double See https://github.com/micrometer-metrics/micrometer/pull/1909 Closes gh-20837 --- .../autoconfigure/metrics/MeterValue.java | 49 +++++++++++++------ .../metrics/PropertiesMeterFilter.java | 10 ++-- .../ServiceLevelAgreementBoundary.java | 12 ++--- .../metrics/MeterValueTests.java | 21 ++++---- .../ServiceLevelAgreementBoundaryTests.java | 21 +++++++- 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java index c6d5fbcd25..b0dc59d0a2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -25,17 +25,18 @@ import org.springframework.boot.convert.DurationStyle; /** * A meter value that is used when configuring micrometer. Can be a String representation - * of either a {@link Long} (applicable to timers and distribution summaries) or a + * of either a {@link Double} (applicable to timers and distribution summaries) or a * {@link Duration} (applicable to only timers). * * @author Phillip Webb + * @author Stephane Nicoll * @since 2.2.0 */ public final class MeterValue { private final Object value; - MeterValue(long value) { + MeterValue(double value) { this.value = value; } @@ -48,26 +49,29 @@ public final class MeterValue { * @param meterType the meter type * @return the value or {@code null} if the value cannot be applied */ - public Long getValue(Type meterType) { + public Double getValue(Type meterType) { if (meterType == Type.DISTRIBUTION_SUMMARY) { return getDistributionSummaryValue(); } if (meterType == Type.TIMER) { - return getTimerValue(); + Long timerValue = getTimerValue(); + if (timerValue != null) { + return timerValue.doubleValue(); + } } return null; } - private Long getDistributionSummaryValue() { - if (this.value instanceof Long) { - return (Long) this.value; + private Double getDistributionSummaryValue() { + if (this.value instanceof Double) { + return (Double) this.value; } return null; } private Long getTimerValue() { - if (this.value instanceof Long) { - return TimeUnit.MILLISECONDS.toNanos((long) this.value); + if (this.value instanceof Double) { + return TimeUnit.MILLISECONDS.toNanos(((Double) this.value).longValue()); } if (this.value instanceof Duration) { return ((Duration) this.value).toNanos(); @@ -82,8 +86,9 @@ public final class MeterValue { * @return a {@link MeterValue} instance */ public static MeterValue valueOf(String value) { - if (isNumber(value)) { - return new MeterValue(Long.parseLong(value)); + Double number = safeParseDouble(value); + if (number != null) { + return new MeterValue(number); } return new MeterValue(DurationStyle.detectAndParse(value)); } @@ -92,13 +97,29 @@ public final class MeterValue { * Return a new {@link MeterValue} instance for the given long value. * @param value the source value * @return a {@link MeterValue} instance + * @deprecated as of 2.3.0 in favor of {@link #valueOf(double)} */ + @Deprecated public static MeterValue valueOf(long value) { return new MeterValue(value); } - private static boolean isNumber(String value) { - return value.chars().allMatch(Character::isDigit); + /** + * Return a new {@link MeterValue} instance for the given double value. + * @param value the source value + * @return a {@link MeterValue} instance + */ + public static MeterValue valueOf(double value) { + return new MeterValue(value); + } + + private static Double safeParseDouble(String value) { + try { + return Double.parseDouble(value); + } + catch (NumberFormatException nfe) { + return null; + } } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java index bf50bb63cc..b5bce1a418 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -91,16 +91,16 @@ public class PropertiesMeterFilter implements MeterFilter { .build().merge(config); } - private long[] convertSla(Meter.Type meterType, ServiceLevelAgreementBoundary[] sla) { + private double[] convertSla(Meter.Type meterType, ServiceLevelAgreementBoundary[] sla) { if (sla == null) { return null; } - long[] converted = Arrays.stream(sla).map((candidate) -> candidate.getValue(meterType)).filter(Objects::nonNull) - .mapToLong(Long::longValue).toArray(); + double[] converted = Arrays.stream(sla).map((candidate) -> candidate.getValue(meterType)) + .filter(Objects::nonNull).mapToDouble(Double::doubleValue).toArray(); return (converted.length != 0) ? converted : null; } - private Long convertMeterValue(Meter.Type meterType, String value) { + private Double convertMeterValue(Meter.Type meterType, String value) { return (value != null) ? MeterValue.valueOf(value).getValue(meterType) : null; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java index 9fa875fc18..dd0f80f770 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -22,8 +22,8 @@ import io.micrometer.core.instrument.Meter; /** * 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 Duration} (applicable to only timers). + * specified as either a {@link Double} (applicable to timers and distribution summaries) + * or a {@link Duration} (applicable to only timers). * * @author Phillip Webb * @since 2.0.0 @@ -42,17 +42,17 @@ public final class ServiceLevelAgreementBoundary { * @param meterType the meter type * @return the value or {@code null} if the value cannot be applied */ - public Long getValue(Meter.Type meterType) { + public Double getValue(Meter.Type meterType) { return this.value.getValue(meterType); } /** - * Return a new {@link ServiceLevelAgreementBoundary} instance for the given long + * Return a new {@link ServiceLevelAgreementBoundary} instance for the given double * value. * @param value the source value * @return a {@link ServiceLevelAgreementBoundary} instance */ - public static ServiceLevelAgreementBoundary valueOf(long value) { + public static ServiceLevelAgreementBoundary valueOf(double value) { return new ServiceLevelAgreementBoundary(MeterValue.valueOf(value)); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java index f63da5faae..1c1572d168 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -30,17 +30,18 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link MeterValue}. * * @author Phillip Webb + * @author Stephane Nicoll */ class MeterValueTests { @Test - void getValueForDistributionSummaryWhenFromLongShouldReturnLongValue() { - MeterValue meterValue = MeterValue.valueOf(123L); - assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); + void getValueForDistributionSummaryWhenFromNumberShouldReturnDoubleValue() { + MeterValue meterValue = MeterValue.valueOf(123.42); + assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123.42); } @Test - void getValueForDistributionSummaryWhenFromNumberStringShouldReturnLongValue() { + void getValueForDistributionSummaryWhenFromNumberStringShouldReturnDoubleValue() { MeterValue meterValue = MeterValue.valueOf("123"); assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); } @@ -52,8 +53,8 @@ class MeterValueTests { } @Test - void getValueForTimerWhenFromLongShouldReturnMsToNanosValue() { - MeterValue meterValue = MeterValue.valueOf(123L); + void getValueForTimerWhenFromNumberShouldReturnMsToNanosValue() { + MeterValue meterValue = MeterValue.valueOf(123d); assertThat(meterValue.getValue(Type.TIMER)).isEqualTo(123000000); } @@ -81,11 +82,11 @@ class MeterValueTests { @Test void valueOfShouldWorkInBinder() { MockEnvironment environment = new MockEnvironment(); - TestPropertyValues.of("duration=10ms", "long=20").applyTo(environment); + TestPropertyValues.of("duration=10ms", "number=20.42").applyTo(environment); assertThat(Binder.get(environment).bind("duration", Bindable.of(MeterValue.class)).get().getValue(Type.TIMER)) .isEqualTo(10000000); - assertThat(Binder.get(environment).bind("long", Bindable.of(MeterValue.class)).get().getValue(Type.TIMER)) - .isEqualTo(20000000); + assertThat(Binder.get(environment).bind("number", Bindable.of(MeterValue.class)).get() + .getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(20.42); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java index d9cb37e7f1..f3250c13ac 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link ServiceLevelAgreementBoundary}. * * @author Phillip Webb + * @author Stephane Nicoll */ class ServiceLevelAgreementBoundaryTests { @@ -46,4 +47,22 @@ class ServiceLevelAgreementBoundaryTests { assertThat(sla.getValue(Type.TIMER)).isEqualTo(123000000); } + @Test + void getValueForDistributionSummaryWhenFromDoubleShouldReturnDoubleValue() { + ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf(123.42); + assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123.42); + } + + @Test + void getValueForDistributionSummaryWhenFromStringShouldReturnDoubleValue() { + ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123.42"); + assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123.42); + } + + @Test + void getValueForDistributionSummaryWhenFromDurationShouldReturnNull() { + ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123ms"); + assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isNull(); + } + } From 333ac279c3a1d91a57e8671ac416ff1c1b82910c Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 11:48:57 +0200 Subject: [PATCH 05/11] Stop auto-configuring a StatsdMetrics bean StatsD no longer publishes metrics about itself and StatsDMetrics is deprecated as a result. This commit removes the auto-configuration of it. Closes gh-20836 --- .../statsd/StatsdMetricsExportAutoConfiguration.java | 8 +------- .../statsd/StatsdMetricsExportAutoConfigurationTests.java | 8 +++----- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfiguration.java index b692e032f6..981d62b000 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -19,7 +19,6 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.statsd; import io.micrometer.core.instrument.Clock; import io.micrometer.statsd.StatsdConfig; import io.micrometer.statsd.StatsdMeterRegistry; -import io.micrometer.statsd.StatsdMetrics; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; @@ -63,9 +62,4 @@ public class StatsdMetricsExportAutoConfiguration { return new StatsdMeterRegistry(statsdConfig, clock); } - @Bean - public StatsdMetrics statsdMetrics() { - return new StatsdMetrics(); - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfigurationTests.java index 30dcdc04ec..e4e37bad73 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdMetricsExportAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -19,7 +19,6 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.statsd; import io.micrometer.core.instrument.Clock; import io.micrometer.statsd.StatsdConfig; import io.micrometer.statsd.StatsdMeterRegistry; -import io.micrometer.statsd.StatsdMetrics; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -47,9 +46,8 @@ class StatsdMetricsExportAutoConfigurationTests { @Test void autoConfiguresItsConfigMeterRegistryAndMetrics() { - this.contextRunner.withUserConfiguration(BaseConfiguration.class) - .run((context) -> assertThat(context).hasSingleBean(StatsdMeterRegistry.class) - .hasSingleBean(StatsdConfig.class).hasSingleBean(StatsdMetrics.class)); + this.contextRunner.withUserConfiguration(BaseConfiguration.class).run((context) -> assertThat(context) + .hasSingleBean(StatsdMeterRegistry.class).hasSingleBean(StatsdConfig.class)); } @Test From 888a81beba23728078337ad91c27ca4abbcb189e Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 12:35:01 +0200 Subject: [PATCH 06/11] Migrate Kafka metrics to KafkaClientMetrics Closes gh-20838 --- .../build.gradle | 1 + .../KafkaMetricsAutoConfiguration.java | 22 ++++++------ .../KafkaMetricsAutoConfigurationTests.java | 34 +++++++++---------- .../asciidoc/production-ready-features.adoc | 2 +- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 41b31ac249..c8166427ee 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -101,6 +101,7 @@ dependencies { optional("org.springframework.data:spring-data-redis") optional("org.springframework.data:spring-data-solr") optional("org.springframework.integration:spring-integration-core") + optional("org.springframework.kafka:spring-kafka") optional("org.springframework.security:spring-security-config") optional("org.springframework.security:spring-security-web") optional("org.springframework.session:spring-session-core") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfiguration.java index f2bbcfe6e1..e026f89006 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -18,37 +18,37 @@ package org.springframework.boot.actuate.autoconfigure.metrics; import java.util.Collections; -import javax.management.MBeanServer; - import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.binder.kafka.KafkaConsumerMetrics; -import org.apache.kafka.clients.consumer.KafkaConsumer; +import io.micrometer.core.instrument.binder.kafka.KafkaClientMetrics; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.ProducerFactory; /** * Auto-configuration for Kafka metrics. * * @author Andy Wilkinson + * @author Stephane Nicoll * @since 2.1.0 */ @Configuration(proxyBeanMethods = false) -@AutoConfigureAfter({ MetricsAutoConfiguration.class, JmxAutoConfiguration.class }) -@ConditionalOnClass({ KafkaConsumerMetrics.class, KafkaConsumer.class }) +@AutoConfigureAfter({ MetricsAutoConfiguration.class, KafkaAutoConfiguration.class }) +@ConditionalOnClass({ KafkaClientMetrics.class, ProducerFactory.class }) @ConditionalOnBean(MeterRegistry.class) public class KafkaMetricsAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnBean(MBeanServer.class) - public KafkaConsumerMetrics kafkaConsumerMetrics(MBeanServer mbeanServer) { - return new KafkaConsumerMetrics(mbeanServer, Collections.emptyList()); + @ConditionalOnSingleCandidate(ProducerFactory.class) + public KafkaClientMetrics kafkaClientMetrics(ProducerFactory producerFactory) { + return new KafkaClientMetrics(producerFactory.createProducer(), Collections.emptyList()); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfigurationTests.java index 1b4450ec47..be1e01efc6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/KafkaMetricsAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,54 +16,54 @@ package org.springframework.boot.actuate.autoconfigure.metrics; -import io.micrometer.core.instrument.binder.kafka.KafkaConsumerMetrics; +import io.micrometer.core.instrument.binder.kafka.KafkaClientMetrics; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; +import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; /** * Tests for {@link KafkaMetricsAutoConfiguration}. * * @author Andy Wilkinson + * @author Stephane Nicoll */ class KafkaMetricsAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple()) - .withPropertyValues("spring.jmx.enabled=true") .withConfiguration(AutoConfigurations.of(KafkaMetricsAutoConfiguration.class)); @Test - void whenThereIsNoMBeanServerAutoConfigurationBacksOff() { - this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(KafkaConsumerMetrics.class)); + void whenThereIsNoProducerFactoryAutoConfigurationBacksOff() { + this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(KafkaClientMetrics.class)); } @Test - void whenThereIsAnMBeanServerKafkaConsumerMetricsIsConfigured() { - this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class)) - .run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class)); + void whenThereIsAnAProducerFactoryKafkaClientMetricsIsConfigured() { + this.contextRunner.withConfiguration(AutoConfigurations.of(KafkaAutoConfiguration.class)) + .run((context) -> assertThat(context).hasSingleBean(KafkaClientMetrics.class)); } @Test - void allowsCustomKafkaConsumerMetricsToBeUsed() { - this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class)) - .withUserConfiguration(CustomKafkaConsumerMetricsConfiguration.class) - .run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class) - .hasBean("customKafkaConsumerMetrics")); + void allowsCustomKafkaClientMetricsToBeUsed() { + this.contextRunner.withConfiguration(AutoConfigurations.of(KafkaAutoConfiguration.class)) + .withUserConfiguration(CustomKafkaClientMetricsConfiguration.class).run((context) -> assertThat(context) + .hasSingleBean(KafkaClientMetrics.class).hasBean("customKafkaClientMetrics")); } @Configuration(proxyBeanMethods = false) - static class CustomKafkaConsumerMetricsConfiguration { + static class CustomKafkaClientMetricsConfiguration { @Bean - KafkaConsumerMetrics customKafkaConsumerMetrics() { - return new KafkaConsumerMetrics(); + KafkaClientMetrics customKafkaClientMetrics() { + return mock(KafkaClientMetrics.class); } } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/production-ready-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/production-ready-features.adoc index 78a269b984..a4ee216687 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/production-ready-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/production-ready-features.adoc @@ -1791,7 +1791,7 @@ Spring Boot registers the following core metrics when applicable: ** Number of classes loaded/unloaded * CPU metrics * File descriptor metrics -* Kafka consumer metrics (<> should be enabled) +* Kafka consumer metrics * Log4j2 metrics: record the number of events logged to Log4j2 at each level * Logback metrics: record the number of events logged to Logback at each level * Uptime metrics: report a gauge for uptime and a fixed gauge representing the application's absolute start time From f293f6ad9b66347f0b2eec552f601109406feb33 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 15:27:57 +0200 Subject: [PATCH 07/11] Expose AppOptics's floorTimes property Closes gh-20850 --- .../export/appoptics/AppOpticsProperties.java | 16 +++++++++++++++- .../AppOpticsPropertiesConfigAdapter.java | 7 ++++++- .../AppOpticsPropertiesConfigAdapterTests.java | 9 ++++++++- .../appoptics/AppOpticsPropertiesTests.java | 3 ++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsProperties.java index b50a50c42c..991e733d9c 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -46,6 +46,12 @@ public class AppOpticsProperties extends StepRegistryProperties { */ private String hostTag = "instance"; + /** + * Whether to ship a floored time, useful when sending measurements from multiple + * hosts to align them on a given time boundary. + */ + private boolean floorTimes; + /** * Number of measurements per request to use for this backend. If more measurements * are found, then multiple requests will be made. @@ -81,6 +87,14 @@ public class AppOpticsProperties extends StepRegistryProperties { this.hostTag = hostTag; } + public boolean isFloorTimes() { + return this.floorTimes; + } + + public void setFloorTimes(boolean floorTimes) { + this.floorTimes = floorTimes; + } + @Override public Integer getBatchSize() { return this.batchSize; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapter.java index 88ebb38e8f..7a959fb7bc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -47,4 +47,9 @@ class AppOpticsPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapt return get(AppOpticsProperties::getHostTag, AppOpticsConfig.super::hostTag); } + @Override + public boolean floorTimes() { + return get(AppOpticsProperties::isFloorTimes, AppOpticsConfig.super::floorTimes); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapterTests.java index ff619497c5..ff0f57f379 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapterTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesConfigAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -61,4 +61,11 @@ class AppOpticsPropertiesConfigAdapterTests assertThat(createConfigAdapter(properties).hostTag()).isEqualTo("node"); } + @Test + void whenPropertiesFloorTimesIsSetAdapterHostTagReturnsIt() { + AppOpticsProperties properties = createProperties(); + properties.setFloorTimes(true); + assertThat(createConfigAdapter(properties).floorTimes()).isTrue(); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesTests.java index 2ca99cf87a..5e3f4b6cec 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/appoptics/AppOpticsPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -37,6 +37,7 @@ class AppOpticsPropertiesTests extends StepRegistryPropertiesTests { assertStepRegistryDefaultValues(properties, config); assertThat(properties.getUri()).isEqualToIgnoringWhitespace(config.uri()); assertThat(properties.getHostTag()).isEqualToIgnoringWhitespace(config.hostTag()); + assertThat(properties.isFloorTimes()).isEqualTo(config.floorTimes()); } } From f64f5a0f557d47df93ef6aae7457ec2a69e9e977 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 17:01:16 +0200 Subject: [PATCH 08/11] Expose Elastic's pipeline and indexDateSeparator properties Closes gh-20852 --- .../export/elastic/ElasticProperties.java | 31 +++++++++++++++++-- .../ElasticPropertiesConfigAdapter.java | 12 ++++++- .../ElasticPropertiesConfigAdapterTests.java | 16 +++++++++- .../elastic/ElasticPropertiesTests.java | 4 ++- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticProperties.java index 5af408d5d9..2a94556cda 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -40,11 +40,15 @@ public class ElasticProperties extends StepRegistryProperties { private String index = "metrics"; /** - * Index date format used for rolling indices. Appended to the index name, preceded by - * a '-'. + * Index date format used for rolling indices. Appended to the index name. */ private String indexDateFormat = "yyyy-MM"; + /** + * Prefix to separate the index name from the date format used for rolling indices. + */ + private String indexDateSeparator = "-"; + /** * Name of the timestamp field. */ @@ -65,6 +69,11 @@ public class ElasticProperties extends StepRegistryProperties { */ private String password = ""; + /** + * Ingest pipeline name. By default, events are not pre-processed. + */ + private String pipeline = ""; + public String getHost() { return this.host; } @@ -89,6 +98,14 @@ public class ElasticProperties extends StepRegistryProperties { this.indexDateFormat = indexDateFormat; } + public String getIndexDateSeparator() { + return this.indexDateSeparator; + } + + public void setIndexDateSeparator(String indexDateSeparator) { + this.indexDateSeparator = indexDateSeparator; + } + public String getTimestampFieldName() { return this.timestampFieldName; } @@ -121,4 +138,12 @@ public class ElasticProperties extends StepRegistryProperties { this.password = password; } + public String getPipeline() { + return this.pipeline; + } + + public void setPipeline(String pipeline) { + this.pipeline = pipeline; + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapter.java index 8d41ebe252..06a507b506 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -47,6 +47,11 @@ class ElasticPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter return get(ElasticProperties::getIndexDateFormat, ElasticConfig.super::indexDateFormat); } + @Override + public String indexDateSeparator() { + return get(ElasticProperties::getIndexDateSeparator, ElasticConfig.super::indexDateSeparator); + } + @Override public String timestampFieldName() { return get(ElasticProperties::getTimestampFieldName, ElasticConfig.super::timestampFieldName); @@ -67,4 +72,9 @@ class ElasticPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter return get(ElasticProperties::getPassword, ElasticConfig.super::password); } + @Override + public String pipeline() { + return get(ElasticProperties::getPipeline, ElasticConfig.super::pipeline); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapterTests.java index f3a27b724a..23e840531c 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapterTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesConfigAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -48,6 +48,13 @@ class ElasticPropertiesConfigAdapterTests { assertThat(new ElasticPropertiesConfigAdapter(properties).indexDateFormat()).isEqualTo("yyyy"); } + @Test + void whenPropertiesIndexDateSeparatorIsSetAdapterIndexDateFormatReturnsIt() { + ElasticProperties properties = new ElasticProperties(); + properties.setIndexDateSeparator("*"); + assertThat(new ElasticPropertiesConfigAdapter(properties).indexDateSeparator()).isEqualTo("*"); + } + @Test void whenPropertiesTimestampFieldNameIsSetAdapterTimestampFieldNameReturnsIt() { ElasticProperties properties = new ElasticProperties(); @@ -76,4 +83,11 @@ class ElasticPropertiesConfigAdapterTests { assertThat(new ElasticPropertiesConfigAdapter(properties).password()).isEqualTo("secret"); } + @Test + void whenPropertiesPipelineIsSetAdapterPasswordReturnsIt() { + ElasticProperties properties = new ElasticProperties(); + properties.setPipeline("testPipeline"); + assertThat(new ElasticPropertiesConfigAdapter(properties).pipeline()).isEqualTo("testPipeline"); + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesTests.java index 407c968c14..7e692f0a7f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -38,10 +38,12 @@ class ElasticPropertiesTests extends StepRegistryPropertiesTests { assertThat(properties.getHost()).isEqualTo(config.host()); assertThat(properties.getIndex()).isEqualTo(config.index()); assertThat(properties.getIndexDateFormat()).isEqualTo(config.indexDateFormat()); + assertThat(properties.getIndexDateSeparator()).isEqualTo(config.indexDateSeparator()); assertThat(properties.getPassword()).isEqualTo(config.password()); assertThat(properties.getTimestampFieldName()).isEqualTo(config.timestampFieldName()); assertThat(properties.getUserName()).isEqualTo(config.userName()); assertThat(properties.isAutoCreateIndex()).isEqualTo(config.autoCreateIndex()); + assertThat(properties.getPipeline()).isEqualTo(config.pipeline()); } } From a8c026a558f0187a9b35ce60f4207205824a7e88 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Apr 2020 18:05:08 +0200 Subject: [PATCH 09/11] Expose Prometheus#histogramFlavor property Closes gh-20853 --- .../export/prometheus/PrometheusProperties.java | 17 ++++++++++++++++- .../PrometheusPropertiesConfigAdapter.java | 8 +++++++- ...dditional-spring-configuration-metadata.json | 4 ++++ .../prometheus/PrometheusPropertiesTests.java | 3 ++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java index e530ea9002..74023c8f0d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -20,6 +20,8 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import io.micrometer.prometheus.HistogramFlavor; + import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -46,6 +48,11 @@ public class PrometheusProperties { */ private final Pushgateway pushgateway = new Pushgateway(); + /** + * Histogram type for backing DistributionSummary and Timer. + */ + private HistogramFlavor histogramFlavor = HistogramFlavor.Prometheus; + /** * Step size (i.e. reporting frequency) to use. */ @@ -59,6 +66,14 @@ public class PrometheusProperties { this.descriptions = descriptions; } + public HistogramFlavor getHistogramFlavor() { + return this.histogramFlavor; + } + + public void setHistogramFlavor(HistogramFlavor histogramFlavor) { + this.histogramFlavor = histogramFlavor; + } + public Duration getStep() { return this.step; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java index 0a4ff1204e..d95fab896f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -18,6 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus import java.time.Duration; +import io.micrometer.prometheus.HistogramFlavor; import io.micrometer.prometheus.PrometheusConfig; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PropertiesConfigAdapter; @@ -45,6 +46,11 @@ class PrometheusPropertiesConfigAdapter extends PropertiesConfigAdapter Date: Sat, 4 Apr 2020 15:15:16 +0200 Subject: [PATCH 10/11] Update default value for Wavefront's step size See gh-20833 --- .../export/wavefront/WavefrontProperties.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java index 3546d20ccf..0c4f09ded9 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -17,7 +17,6 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; import java.net.URI; -import java.time.Duration; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -32,11 +31,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("management.metrics.export.wavefront") public class WavefrontProperties extends PushRegistryProperties { - /** - * Step size (i.e. reporting frequency) to use. - */ - private Duration step = Duration.ofSeconds(10); - /** * URI to ship metrics to. */ @@ -68,16 +62,6 @@ public class WavefrontProperties extends PushRegistryProperties { this.uri = uri; } - @Override - public Duration getStep() { - return this.step; - } - - @Override - public void setStep(Duration step) { - this.step = step; - } - public String getSource() { return this.source; } From 6764e5e2d0ea4bceef84eecfb9bf012fd5bc442a Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 2 Apr 2020 11:26:24 +0200 Subject: [PATCH 11/11] Export metrics to Wavefront using WavefrontSender This commit upgrades the Wavefront metrics export auto-configuration to provide a `WavefrontSender` if necessary and use that to export metrics rather than the http client Micrometer used previously. As a result, the "read-timeout" and "connect-timeout" properties are no longer honoured. Closes gh-20810 --- ...vefrontMetricsExportAutoConfiguration.java | 51 +++++++++++++++--- .../export/wavefront/WavefrontProperties.java | 53 +++++++++++++++++++ ...itional-spring-configuration-metadata.json | 12 +++++ ...ntMetricsExportAutoConfigurationTests.java | 52 ++++++++++++++++-- 4 files changed, 156 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java index 3137dc2ed6..b9c74ec9db 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,14 +16,19 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; +import java.time.Duration; + +import com.wavefront.sdk.common.WavefrontSender; +import com.wavefront.sdk.direct.ingestion.WavefrontDirectIngestionClient.Builder; import io.micrometer.core.instrument.Clock; -import io.micrometer.core.ipc.http.HttpUrlConnectionSender; +import io.micrometer.core.instrument.config.MissingRequiredConfigurationException; import io.micrometer.wavefront.WavefrontConfig; import io.micrometer.wavefront.WavefrontMeterRegistry; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontProperties.Sender; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -32,21 +37,25 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; +import org.springframework.util.unit.DataSize; /** * {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Wavefront. * * @author Jon Schneider * @author Artsiom Yudovin + * @author Stephane Nicoll * @since 2.0.0 */ @Configuration(proxyBeanMethods = false) @AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class }) @AutoConfigureAfter(MetricsAutoConfiguration.class) @ConditionalOnBean(Clock.class) -@ConditionalOnClass(WavefrontMeterRegistry.class) +@ConditionalOnClass({ WavefrontMeterRegistry.class, WavefrontSender.class }) @ConditionalOnProperty(prefix = "management.metrics.export.wavefront", name = "enabled", havingValue = "true", matchIfMissing = true) @EnableConfigurationProperties(WavefrontProperties.class) @@ -66,10 +75,38 @@ public class WavefrontMetricsExportAutoConfiguration { @Bean @ConditionalOnMissingBean - public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig wavefrontConfig, Clock clock) { - return WavefrontMeterRegistry.builder(wavefrontConfig).clock(clock).httpClient( - new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout())) - .build(); + public WavefrontSender wavefrontSender(WavefrontConfig wavefrontConfig) { + if (!StringUtils.hasText(wavefrontConfig.apiToken())) { + throw new MissingRequiredConfigurationException( + "apiToken must be set whenever publishing directly to the Wavefront API"); + } + return createWavefrontSender(wavefrontConfig); + } + + @Bean + @ConditionalOnMissingBean + public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig wavefrontConfig, Clock clock, + WavefrontSender wavefrontSender) { + return WavefrontMeterRegistry.builder(wavefrontConfig).clock(clock).wavefrontSender(wavefrontSender).build(); + } + + private WavefrontSender createWavefrontSender(WavefrontConfig wavefrontConfig) { + Builder builder = new Builder(getWavefrontReportingUri(wavefrontConfig.uri()), wavefrontConfig.apiToken()); + PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); + Sender sender = this.properties.getSender(); + mapper.from(sender.getMaxQueueSize()).to(builder::maxQueueSize); + mapper.from(sender.getBatchSize()).to(builder::batchSize); + mapper.from(sender.getFlushInterval()).asInt(Duration::getSeconds).to(builder::flushIntervalSeconds); + mapper.from(sender.getMessageSize()).asInt(DataSize::toBytes).to(builder::messageSizeBytes); + return builder.build(); + } + + private String getWavefrontReportingUri(String uri) { + // proxy reporting is now http reporting on newer wavefront proxies. + if (uri.startsWith("proxy")) { + return "http" + uri.substring(5); + } + return uri; } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java index 0c4f09ded9..2254d42f12 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java @@ -17,15 +17,18 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; import java.net.URI; +import java.time.Duration; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PushRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.unit.DataSize; /** * {@link ConfigurationProperties @ConfigurationProperties} for configuring Wavefront * metrics export. * * @author Jon Schneider + * @author Stephane Nicoll * @since 2.0.0 */ @ConfigurationProperties("management.metrics.export.wavefront") @@ -54,6 +57,8 @@ public class WavefrontProperties extends PushRegistryProperties { */ private String globalPrefix; + private final Sender sender = new Sender(); + public URI getUri() { return this.uri; } @@ -86,4 +91,52 @@ public class WavefrontProperties extends PushRegistryProperties { this.globalPrefix = globalPrefix; } + public Sender getSender() { + return this.sender; + } + + public static class Sender { + + private int maxQueueSize = 50000; + + private int batchSize = 10000; + + private Duration flushInterval = Duration.ofSeconds(1); + + private DataSize messageSize = DataSize.ofBytes(Integer.MAX_VALUE); + + public int getMaxQueueSize() { + return this.maxQueueSize; + } + + public void setMaxQueueSize(int maxQueueSize) { + this.maxQueueSize = maxQueueSize; + } + + public int getBatchSize() { + return this.batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public Duration getFlushInterval() { + return this.flushInterval; + } + + public void setFlushInterval(Duration flushInterval) { + this.flushInterval = flushInterval; + } + + public DataSize getMessageSize() { + return this.messageSize; + } + + public void setMessageSize(DataSize messageSize) { + this.messageSize = messageSize; + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index f6c362f578..2b55eef4dc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -380,6 +380,18 @@ "level": "error" } }, + { + "name": "management.metrics.export.wavefront.connect-timeout", + "deprecation": { + "level": "error" + } + }, + { + "name": "management.metrics.export.wavefront.read-timeout", + "deprecation": { + "level": "error" + } + }, { "name": "management.metrics.web.client.request.autotime.enabled", "description": "Whether to automatically time web client requests.", diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java index 50c04b9c4a..62281d9e5f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront; +import com.wavefront.sdk.common.WavefrontSender; import io.micrometer.core.instrument.Clock; import io.micrometer.wavefront.WavefrontConfig; import io.micrometer.wavefront.WavefrontMeterRegistry; @@ -28,6 +29,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; /** * Tests for {@link WavefrontMetricsExportAutoConfiguration}. @@ -53,9 +55,10 @@ class WavefrontMetricsExportAutoConfigurationTests { @Test void autoConfigurationCanBeDisabled() { this.contextRunner.withUserConfiguration(BaseConfiguration.class) - .withPropertyValues("management.metrics.export.wavefront.enabled=false") + .withPropertyValues("management.metrics.export.wavefront.api-token=abcde", + "management.metrics.export.wavefront.enabled=false") .run((context) -> assertThat(context).doesNotHaveBean(WavefrontMeterRegistry.class) - .doesNotHaveBean(WavefrontConfig.class)); + .doesNotHaveBean(WavefrontConfig.class).doesNotHaveBean(WavefrontSender.class)); } @Test @@ -63,7 +66,30 @@ class WavefrontMetricsExportAutoConfigurationTests { this.contextRunner.withUserConfiguration(CustomConfigConfiguration.class) .run((context) -> assertThat(context).hasSingleBean(Clock.class) .hasSingleBean(WavefrontMeterRegistry.class).hasSingleBean(WavefrontConfig.class) - .hasBean("customConfig")); + .hasSingleBean(WavefrontSender.class).hasBean("customConfig")); + } + + @Test + void configureWavefrontSender() { + this.contextRunner.withUserConfiguration(BaseConfiguration.class) + .withPropertyValues("management.metrics.export.wavefront.api-token=abcde", + "management.metrics.export.wavefront.sender.max-queue-size=100", + "management.metrics.export.wavefront.sender.batch-size=200", + "management.metrics.export.wavefront.sender.message-size=1KB") + .run((context) -> { + WavefrontSender sender = context.getBean(WavefrontSender.class); + assertThat(sender).extracting("metricsBuffer").hasFieldOrPropertyWithValue("capacity", 100); + assertThat(sender).hasFieldOrPropertyWithValue("batchSize", 200); + assertThat(sender).hasFieldOrPropertyWithValue("messageSizeBytes", 1024); + }); + } + + @Test + void allowsWavefrontSenderToBeCustomized() { + this.contextRunner.withUserConfiguration(CustomSenderConfiguration.class) + .run((context) -> assertThat(context).hasSingleBean(Clock.class) + .hasSingleBean(WavefrontMeterRegistry.class).hasSingleBean(WavefrontConfig.class) + .hasSingleBean(WavefrontSender.class).hasBean("customSender")); } @Test @@ -109,13 +135,29 @@ class WavefrontMetricsExportAutoConfigurationTests { @Override public String uri() { - return WavefrontConfig.DEFAULT_PROXY.uri(); + return WavefrontConfig.DEFAULT_DIRECT.uri(); + } + + @Override + public String apiToken() { + return "abc-def"; } }; } } + @Configuration(proxyBeanMethods = false) + @Import(BaseConfiguration.class) + static class CustomSenderConfiguration { + + @Bean + WavefrontSender customSender() { + return mock(WavefrontSender.class); + } + + } + @Configuration(proxyBeanMethods = false) @Import(BaseConfiguration.class) static class CustomRegistryConfiguration {