Merge pull request #3719 from sbuettner/master

* pr/3719:
  Add statsd metric export auto-configuration
This commit is contained in:
Phillip Webb 2015-09-24 00:21:58 -07:00
commit bf34dc5013
5 changed files with 123 additions and 13 deletions

View File

@ -29,6 +29,7 @@ import org.springframework.boot.actuate.metrics.export.MetricExportProperties;
import org.springframework.boot.actuate.metrics.export.MetricExporters; import org.springframework.boot.actuate.metrics.export.MetricExporters;
import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader; import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader;
import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter;
import org.springframework.boot.actuate.metrics.writer.MetricWriter; import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -45,6 +46,7 @@ import org.springframework.util.CollectionUtils;
* {@link EnableAutoConfiguration Auto-configuration} for metrics export. * {@link EnableAutoConfiguration Auto-configuration} for metrics export.
* *
* @author Dave Syer * @author Dave Syer
* @author Simon Buettner
* @since 1.3.0 * @since 1.3.0
*/ */
@Configuration @Configuration
@ -92,6 +94,16 @@ public class MetricExportAutoConfiguration {
return exporters; return exporters;
} }
@Bean
@ExportMetricWriter
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.metrics.export.statsd", name = "host")
public StatsdMetricWriter statsdMetricWriter() {
MetricExportProperties.Statsd statsdProperties = this.properties.getStatsd();
return new StatsdMetricWriter(statsdProperties.getPrefix(),
statsdProperties.getHost(), statsdProperties.getPort());
}
@Configuration @Configuration
protected static class MetricExportPropertiesConfiguration { protected static class MetricExportPropertiesConfiguration {

View File

@ -29,6 +29,7 @@ import org.springframework.util.PatternMatchUtils;
* Configuration properties for metrics export. * Configuration properties for metrics export.
* *
* @author Dave Syer * @author Dave Syer
* @author Simon Buettner
* @since 1.3.0 * @since 1.3.0
*/ */
@ConfigurationProperties("spring.metrics.export") @ConfigurationProperties("spring.metrics.export")
@ -43,6 +44,8 @@ public class MetricExportProperties extends TriggerProperties {
private Redis redis = new Redis(); private Redis redis = new Redis();
private Statsd statsd = new Statsd();
@PostConstruct @PostConstruct
public void setUpDefaults() { public void setUpDefaults() {
TriggerProperties defaults = this; TriggerProperties defaults = this;
@ -79,10 +82,6 @@ public class MetricExportProperties extends TriggerProperties {
return this.triggers; return this.triggers;
} }
public Redis getRedis() {
return this.redis;
}
public Aggregate getAggregate() { public Aggregate getAggregate() {
return this.aggregate; return this.aggregate;
} }
@ -91,10 +90,22 @@ public class MetricExportProperties extends TriggerProperties {
this.aggregate = aggregate; this.aggregate = aggregate;
} }
public Redis getRedis() {
return this.redis;
}
public void setRedis(Redis redis) { public void setRedis(Redis redis) {
this.redis = redis; this.redis = redis;
} }
public Statsd getStatsd() {
return this.statsd;
}
public void setStatsd(Statsd statsd) {
this.statsd = statsd;
}
/** /**
* Find a matching trigger configuration. * Find a matching trigger configuration.
* @param name the bean name to match * @param name the bean name to match
@ -205,4 +216,50 @@ public class MetricExportProperties extends TriggerProperties {
} }
/**
* Statsd properties.
*/
public static class Statsd {
/**
* Host of a statsd server to receive exported metrics.
*/
private String host;
/**
* Port of a statsd server to receive exported metrics.
*/
private int port = 8125;
/**
* Prefix for statsd exported metrics.
*/
private String prefix;
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public String getPrefix() {
return this.prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
} }

View File

@ -17,16 +17,21 @@
package org.springframework.boot.actuate.autoconfigure; package org.springframework.boot.actuate.autoconfigure;
import org.junit.After; import org.junit.After;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Matchers; import org.mockito.Matchers;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader; import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader;
import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.export.MetricCopyExporter; import org.springframework.boot.actuate.metrics.export.MetricCopyExporter;
import org.springframework.boot.actuate.metrics.export.MetricExporters; import org.springframework.boot.actuate.metrics.export.MetricExporters;
import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter;
import org.springframework.boot.actuate.metrics.writer.MetricWriter; import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -36,16 +41,22 @@ import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException; import org.springframework.messaging.MessagingException;
import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.SubscribableChannel;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
/** /**
* Tests for {@link MetricExportAutoConfiguration}. * Tests for {@link MetricExportAutoConfiguration}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Simon Buettner
*/ */
public class MetricExportAutoConfigurationTests { public class MetricExportAutoConfigurationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context; private AnnotationConfigApplicationContext context;
@After @After
@ -100,16 +111,43 @@ public class MetricExportAutoConfigurationTests {
Mockito.verify(reader, Mockito.atLeastOnce()).findAll(); Mockito.verify(reader, Mockito.atLeastOnce()).findAll();
} }
@Test
public void statsdMissingHost() throws Exception {
this.context = new AnnotationConfigApplicationContext();
this.context.register(WriterConfig.class, MetricEndpointConfiguration.class,
MetricExportAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
this.thrown.expect(NoSuchBeanDefinitionException.class);
this.context.getBean(StatsdMetricWriter.class);
}
@Test
public void statsdWithHost() throws Exception {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.metrics.export.statsd.host=localhost");
this.context.register(WriterConfig.class, MetricEndpointConfiguration.class,
MetricExportAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(StatsdMetricWriter.class), notNullValue());
}
@Configuration @Configuration
public static class MessageChannelConfiguration { public static class MessageChannelConfiguration {
@Bean @Bean
public SubscribableChannel metricsChannel() { public SubscribableChannel metricsChannel() {
return new FixedSubscriberChannel(new MessageHandler() { return new FixedSubscriberChannel(new MessageHandler() {
@Override @Override
public void handleMessage(Message<?> message) throws MessagingException { public void handleMessage(Message<?> message) throws MessagingException {
} }
}); });
} }
} }
@Configuration @Configuration

View File

@ -790,6 +790,9 @@ content into your application; rather pick only the properties that you need.
spring.metrics.export.excludes= # list of patterns for metric names to exclude. Applied after the includes spring.metrics.export.excludes= # list of patterns for metric names to exclude. Applied after the includes
spring.metrics.export.redis.prefix=spring.metrics # prefix for redis repository if active spring.metrics.export.redis.prefix=spring.metrics # prefix for redis repository if active
spring.metrics.export.redis.key=keys.spring.metrics # key for redis repository export (if active) spring.metrics.export.redis.key=keys.spring.metrics # key for redis repository export (if active)
spring.metrics.export.statsd.host= # host of the statsd server
spring.metrics.export.statsd.port=8125 # port of the statsd server
spring.metrics.export.statsd.prefix= # prefix for exported metrics
spring.metrics.export.triggers.*= # specific trigger properties per MetricWriter bean name spring.metrics.export.triggers.*= # specific trigger properties per MetricWriter bean name
# SENDGRID ({sc-spring-boot-autoconfigure}/sendgrid/SendGridAutoConfiguration.{sc-ext}[SendGridAutoConfiguration]) # SENDGRID ({sc-spring-boot-autoconfigure}/sendgrid/SendGridAutoConfiguration.{sc-ext}[SendGridAutoConfiguration])

View File

@ -1142,28 +1142,28 @@ curl localhost:4242/api/query?start=1h-ago&m=max:counter.status.200.root
[[production-ready-metric-writers-export-to-statsd]] [[production-ready-metric-writers-export-to-statsd]]
==== Example: Export to Statsd ==== Example: Export to Statsd
If you provide a `@Bean` of type `StatsdMetricWriter` and mark it `@ExportMetricWriter` the metrics are exported to a To export metrics to Statsd add a `spring.metrics.export.statsd.host` value to your
statsd server: `application.properties` file. Connections will be opened to port `8125` unless a
`spring.metrics.export.statsd.port` override is provided. You can use
`spring.metrics.export.statsd.prefix` if you want a custom prefix.
Alternatively, you can provide a `@Bean` of type `StatsdMetricWriter` and mark it
`@ExportMetricWriter`:
[source,java,indent=0] [source,java,indent=0]
---- ----
@Value("${spring.application.name:application}.${random.value:0000}") @Value("${spring.application.name:application}.${random.value:0000}")
private String prefix = "metrics"; private String prefix = "metrics";
@Value("${statsd.host:localhost}")
private String host = "localhost";
@Value("${statsd.port:8125}")
private int port;
@Bean @Bean
@ExportMetricWriter @ExportMetricWriter
MetricWriter metricWriter() { MetricWriter metricWriter() {
return new StatsdMetricWriter(prefix, host, port); return new StatsdMetricWriter(prefix, "localhost", "8125");
} }
---- ----
[[production-ready-metric-writers-export-to-jmx]] [[production-ready-metric-writers-export-to-jmx]]
==== Example: Export to JMX ==== Example: Export to JMX
If you provide a `@Bean` of type `JmxMetricWriter` marked `@ExportMetricWriter` the metrics are exported as MBeans to If you provide a `@Bean` of type `JmxMetricWriter` marked `@ExportMetricWriter` the metrics are exported as MBeans to