Commit 602f52ff authored by Stephane Nicoll's avatar Stephane Nicoll

Add support for configuring common tags declaratively

Closes gh-12933
parent 8e4f4317
...@@ -44,6 +44,11 @@ public class MetricsProperties { ...@@ -44,6 +44,11 @@ public class MetricsProperties {
*/ */
private Map<String, Boolean> enable = new LinkedHashMap<>(); private Map<String, Boolean> enable = new LinkedHashMap<>();
/**
* Common tags that are applied to every meter.
*/
private final Map<String, String> tags = new LinkedHashMap<>();
private final Web web = new Web(); private final Web web = new Web();
private final Distribution distribution = new Distribution(); private final Distribution distribution = new Distribution();
...@@ -65,6 +70,10 @@ public class MetricsProperties { ...@@ -65,6 +70,10 @@ public class MetricsProperties {
this.enable = enable; this.enable = enable;
} }
public Map<String, String> getTags() {
return this.tags;
}
public Web getWeb() { public Web getWeb() {
return this.web; return this.web;
} }
......
...@@ -19,9 +19,12 @@ package org.springframework.boot.actuate.autoconfigure.metrics; ...@@ -19,9 +19,12 @@ package org.springframework.boot.actuate.autoconfigure.metrics;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Meter.Id; import io.micrometer.core.instrument.Meter.Id;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.config.MeterFilter; import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.config.MeterFilterReply; import io.micrometer.core.instrument.config.MeterFilterReply;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig; import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
...@@ -35,17 +38,30 @@ import org.springframework.util.StringUtils; ...@@ -35,17 +38,30 @@ import org.springframework.util.StringUtils;
* *
* @author Jon Schneider * @author Jon Schneider
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
*/ */
public class PropertiesMeterFilter implements MeterFilter { public class PropertiesMeterFilter implements MeterFilter {
private static final ServiceLevelAgreementBoundary[] EMPTY_SLA = {}; private static final ServiceLevelAgreementBoundary[] EMPTY_SLA = {};
private MetricsProperties properties; private final MetricsProperties properties;
private final MeterFilter mapFilter;
public PropertiesMeterFilter(MetricsProperties properties) { public PropertiesMeterFilter(MetricsProperties properties) {
Assert.notNull(properties, "Properties must not be null"); Assert.notNull(properties, "Properties must not be null");
this.properties = properties; this.properties = properties;
this.mapFilter = createMapFilter(properties.getTags());
}
private static MeterFilter createMapFilter(Map<String, String> tags) {
if (tags.isEmpty()) {
return new MeterFilter() { };
}
Tags commonTags = Tags.of(tags.entrySet().stream().map((entry) ->
Tag.of(entry.getKey(), entry.getValue())).collect(Collectors.toList()));
return MeterFilter.commonTags(commonTags);
} }
@Override @Override
...@@ -54,6 +70,11 @@ public class PropertiesMeterFilter implements MeterFilter { ...@@ -54,6 +70,11 @@ public class PropertiesMeterFilter implements MeterFilter {
return (enabled ? MeterFilterReply.NEUTRAL : MeterFilterReply.DENY); return (enabled ? MeterFilterReply.NEUTRAL : MeterFilterReply.DENY);
} }
@Override
public Id map(Id id) {
return this.mapFilter.map(id);
}
@Override @Override
public DistributionStatisticConfig configure(Meter.Id id, public DistributionStatisticConfig configure(Meter.Id id,
DistributionStatisticConfig config) { DistributionStatisticConfig config) {
......
...@@ -55,6 +55,19 @@ public class MetricsAutoConfigurationIntegrationTests { ...@@ -55,6 +55,19 @@ public class MetricsAutoConfigurationIntegrationTests {
}); });
} }
@Test
public void propertyBasedCommonTagsIsAutoConfigured() {
this.contextRunner.withPropertyValues("management.metrics.tags.region=test",
"management.metrics.tags.origin=local")
.run((context) -> {
MeterRegistry registry = context.getBean(MeterRegistry.class);
registry.counter("my.counter", "env", "qa");
assertThat(registry.find("my.counter").tags("env", "qa")
.tags("region", "test").tags("origin", "local").counter())
.isNotNull();
});
}
@Test @Test
public void simpleMeterRegistryIsUsedAsAFallback() { public void simpleMeterRegistryIsUsedAsAFallback() {
this.contextRunner this.contextRunner
......
...@@ -1432,6 +1432,7 @@ content into your application. Rather, pick only the properties that you need. ...@@ -1432,6 +1432,7 @@ content into your application. Rather, pick only the properties that you need.
management.metrics.export.wavefront.step=10s # Step size (i.e. reporting frequency) to use. management.metrics.export.wavefront.step=10s # Step size (i.e. reporting frequency) to use.
management.metrics.export.wavefront.uri=https://longboard.wavefront.com # URI to ship metrics to. management.metrics.export.wavefront.uri=https://longboard.wavefront.com # URI to ship metrics to.
management.metrics.use-global-registry=true # Whether auto-configured MeterRegistry implementations should be bound to the global static registry on Metrics. management.metrics.use-global-registry=true # Whether auto-configured MeterRegistry implementations should be bound to the global static registry on Metrics.
management.metrics.tags.*= # Common tags that are applied to every meter.
management.metrics.web.client.max-uri-tags=100 # Maximum number of unique URI tag values allowed. After the max number of tag values is reached, metrics with additional tag values are denied by filter. management.metrics.web.client.max-uri-tags=100 # Maximum number of unique URI tag values allowed. After the max number of tag values is reached, metrics with additional tag values are denied by filter.
management.metrics.web.client.requests-metric-name=http.client.requests # Name of the metric for sent requests. management.metrics.web.client.requests-metric-name=http.client.requests # Name of the metric for sent requests.
management.metrics.web.server.auto-time-requests=true # Whether requests handled by Spring MVC or WebFlux should be automatically timed. management.metrics.web.server.auto-time-requests=true # Whether requests handled by Spring MVC or WebFlux should be automatically timed.
......
...@@ -1846,6 +1846,21 @@ all meter IDs beginning with `com.example`, you can do the following: ...@@ -1846,6 +1846,21 @@ all meter IDs beginning with `com.example`, you can do the following:
include::{code-examples}/actuate/metrics/MetricsFilterBeanExample.java[tag=configuration] include::{code-examples}/actuate/metrics/MetricsFilterBeanExample.java[tag=configuration]
---- ----
[[production-ready-metrics-common-tags]]
==== Common tags
Common tag are generally used for dimensional drill-down on the operating environment like
host, instance, region, stack, etc. Commons tags applied to all meters and can be
configured as shown in the following example:
[source,properties,indent=0]
----
management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod
----
The example above adds a `region` and `stack` tags to all meters with a value of
`us-east-1` and `prod` respectively.
==== Per-meter properties ==== Per-meter properties
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment