Skip to content

Commit

Permalink
Extract metric export into a separate autoconfig class
Browse files Browse the repository at this point in the history
This avoids a potential problems with ordering between Dropwizard and
normal repository configuration. A Dropwizard sample has been added to
verify the behaviour.
  • Loading branch information
dsyer authored and wilkinsona committed May 13, 2015
1 parent 7be13b2 commit 64af327
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 46 deletions.
1 change: 0 additions & 1 deletion spring-boot-actuator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
</organization>
<properties>
<main.basedir>${basedir}/..</main.basedir>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Compile -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2012-2015 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;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.export.MetricExportProperties;
import org.springframework.boot.actuate.metrics.export.MetricExporters;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
* @author Dave Syer
*/
@Configuration
@EnableScheduling
@ConditionalOnProperty(value = "spring.metrics.export.enabled", matchIfMissing = true)
public class MetricExportAutoConfiguration {

@Autowired(required = false)
private Map<String, MetricWriter> writers = Collections.emptyMap();

@Autowired
private MetricExportProperties metrics;

@Autowired(required = false)
@ActuatorMetricRepository
private MetricWriter actuatorMetricRepository;

@Autowired(required = false)
@ActuatorMetricRepository
private MetricReader reader;

@Bean
@ConditionalOnMissingBean
public SchedulingConfigurer metricWritersMetricExporter() {
Map<String, MetricWriter> writers = new HashMap<String, MetricWriter>();
if (this.reader != null) {
writers.putAll(this.writers);
if (this.actuatorMetricRepository != null
&& writers.containsValue(this.actuatorMetricRepository)) {
for (String name : this.writers.keySet()) {
if (writers.get(name).equals(this.actuatorMetricRepository)) {
writers.remove(name);
}
}
}
MetricExporters exporters = new MetricExporters(this.reader, writers,
this.metrics);
return exporters;
}
return new SchedulingConfigurer() {

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@

package org.springframework.boot.actuate.autoconfigure;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.boot.actuate.metrics.GaugeService;
Expand All @@ -31,8 +27,6 @@
import org.springframework.boot.actuate.metrics.export.Exporter;
import org.springframework.boot.actuate.metrics.export.MetricCopyExporter;
import org.springframework.boot.actuate.metrics.export.MetricExportProperties;
import org.springframework.boot.actuate.metrics.export.MetricExporters;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository;
import org.springframework.boot.actuate.metrics.repository.MetricRepository;
import org.springframework.boot.actuate.metrics.writer.DefaultCounterService;
Expand All @@ -43,12 +37,10 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.JavaVersion;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.Range;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.MessageChannel;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.codahale.metrics.MetricRegistry;

Expand Down Expand Up @@ -166,38 +158,4 @@ public InMemoryMetricRepository actuatorMetricRepository() {

}

@Configuration
@EnableScheduling
@ConditionalOnProperty(value = "spring.metrics.export.enabled", matchIfMissing = true)
static class DefaultMetricsExporterConfiguration {

@Autowired(required = false)
private Map<String, MetricWriter> writers = Collections.emptyMap();

@Autowired
private MetricExportProperties metrics;

@Autowired(required = false)
@ActuatorMetricRepository
private MetricWriter actuatorMetricRepository;

@Bean
@ConditionalOnMissingBean
public MetricExporters metricWritersMetricExporter(
@ActuatorMetricRepository MetricReader reader) {
Map<String, MetricWriter> writers = new HashMap<String, MetricWriter>(
this.writers);
if (this.actuatorMetricRepository != null
&& writers.containsValue(this.actuatorMetricRepository)) {
for (String name : this.writers.keySet()) {
if (writers.get(name).equals(this.actuatorMetricRepository)) {
writers.remove(name);
}
}
}
MetricExporters exporters = new MetricExporters(reader, writers, this.metrics);
return exporters;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.MetricsDropwizardAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.MetricsChannelAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ public void createServices() throws Exception {
@Test
public void defaultExporterWhenMessageChannelAvailable() throws Exception {
this.context = new AnnotationConfigApplicationContext(
MessageChannelConfiguration.class, MetricsChannelAutoConfiguration.class,
MessageChannelConfiguration.class,
MetricRepositoryAutoConfiguration.class,
MetricsChannelAutoConfiguration.class,
MetricExportAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
MetricExporters exporter = this.context.getBean(MetricExporters.class);
assertNotNull(exporter);
Expand All @@ -95,6 +97,7 @@ public void defaultExporterWhenMessageChannelAvailable() throws Exception {
public void provideAdditionalWriter() {
this.context = new AnnotationConfigApplicationContext(WriterConfig.class,
MetricRepositoryAutoConfiguration.class,
MetricExportAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
GaugeService gaugeService = this.context.getBean(GaugeService.class);
assertNotNull(gaugeService);
Expand Down
1 change: 1 addition & 0 deletions spring-boot-samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<module>spring-boot-sample-jta-bitronix</module>
<module>spring-boot-sample-jta-jndi</module>
<module>spring-boot-sample-liquibase</module>
<module>spring-boot-sample-metrics-dropwizard</module>
<module>spring-boot-sample-metrics-opentsdb</module>
<module>spring-boot-sample-metrics-redis</module>
<module>spring-boot-sample-parent-context</module>
Expand Down
48 changes: 48 additions & 0 deletions spring-boot-samples/spring-boot-sample-metrics-dropwizard/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-metrics-dropwizard</artifactId>
<name>spring-boot-sample-metrics-dropwizard</name>
<description>Spring Boot Metrics Redis Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2012-2015 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 sample.metrics.dropwizard;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "service", ignoreUnknownFields = false)
public class HelloWorldService {

private String name = "World";

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getHelloMessage() {
return "Hello " + this.name;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2012-2015 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 sample.metrics.dropwizard;

import java.util.Collections;
import java.util.Map;

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@Description("A controller for handling requests for hello messages")
public class SampleController {

@Autowired
private HelloWorldService helloWorldService;

@Autowired
private GaugeService gauges;

@RequestMapping(value = "/", method = RequestMethod.GET)
@ResponseBody
public Map<String, String> hello() {
this.gauges.submit("timer.test.value", Math.random() * 1000 + 1000);
return Collections.singletonMap("message",
this.helloWorldService.getHelloMessage());
}

protected static class Message {

@NotBlank(message = "Message value cannot be empty")
private String value;

public String getValue() {
return this.value;
}

public void setValue(String value) {
this.value = value;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2012-2015 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 sample.metrics.dropwizard;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleDropwizardMetricsApplication {

public static void main(String[] args) throws Exception {
SpringApplication.run(SampleDropwizardMetricsApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
service.name: Phil
Loading

0 comments on commit 64af327

Please sign in to comment.