From f1f87866315c94b2baa5414d8ca1ad3d9dcfe4a5 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 4 Jun 2015 14:19:17 +0200 Subject: [PATCH] Polish Polish metrics export feature added in 6f4d3f4 Closes gh-96 --- CHANGELOG.adoc | 1 + initializr-service/application-cloud.yml | 3 ++ initializr-service/manifest.yml | 2 + initializr/pom.xml | 6 +-- ...izrMetricsExporterAutoConfiguration.groovy | 30 ++++++++------ .../config/MetricsProperties.groovy | 12 +++--- .../metadata/InitializrProperties.groovy | 4 +- .../metrics/MetricsExportTests.groovy | 38 ++++++++---------- .../OfflineInitializrMetadataProvider.groovy | 40 +++++++++++++++++++ .../initializr/test/RedisRunning.groovy | 11 +++-- ...nitializrControllerIntegrationTests.groovy | 16 +++----- 11 files changed, 101 insertions(+), 62 deletions(-) create mode 100644 initializr-service/application-cloud.yml create mode 100644 initializr/src/test/groovy/io/spring/initializr/test/OfflineInitializrMetadataProvider.groovy diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c8897346..a3912a56 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -7,6 +7,7 @@ order. === Release 1.0.0 (In progress) +* https://github.com/spring-io/initializr/issues/96[#96]: export service metrics to redis * https://github.com/spring-io/initializr/issues/115[#115]: rename /metadata/service to /metadata/config * https://github.com/spring-io/initializr/issues/89[#89]: better describe service capability * https://github.com/spring-io/initializr/issues/105[#105]: support for dependencies group defaults diff --git a/initializr-service/application-cloud.yml b/initializr-service/application-cloud.yml new file mode 100644 index 00000000..089ddd66 --- /dev/null +++ b/initializr-service/application-cloud.yml @@ -0,0 +1,3 @@ +spring: + metrics: + export: enabled \ No newline at end of file diff --git a/initializr-service/manifest.yml b/initializr-service/manifest.yml index bdf58360..631a3a63 100644 --- a/initializr-service/manifest.yml +++ b/initializr-service/manifest.yml @@ -6,3 +6,5 @@ applications: host: start-development domain: cfapps.io path: . + services: + start-redis diff --git a/initializr/pom.xml b/initializr/pom.xml index 525c1417..e80cab89 100644 --- a/initializr/pom.xml +++ b/initializr/pom.xml @@ -25,12 +25,12 @@ org.springframework.boot - spring-boot-starter-redis - true + spring-boot-starter-groovy-templates org.springframework.boot - spring-boot-starter-groovy-templates + spring-boot-starter-redis + true com.fasterxml.jackson.core diff --git a/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy index e369392e..1101d0f2 100644 --- a/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy @@ -39,15 +39,19 @@ import org.springframework.scheduling.annotation.Scheduled import org.springframework.util.ObjectUtils /** - * @author Dave Syer + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} to export the metrics of an initializr instnace. * + * @author Dave Syer + * @since 1.0 */ @Configuration @ConditionalOnBean(RedisConnectionFactory) -@ConditionalOnProperty(value='spring.metrics.export.enabled', matchIfMissing=true) +@ConditionalOnProperty(value = 'spring.metrics.export.enabled') @EnableScheduling @EnableConfigurationProperties(MetricsProperties) -@AutoConfigureAfter(value=RedisAutoConfiguration, name="org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration") +@AutoConfigureAfter(value = RedisAutoConfiguration, + name = "org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration") class InitializrMetricsExporterAutoConfiguration { @Autowired @@ -58,19 +62,19 @@ class InitializrMetricsExporterAutoConfiguration { @Autowired ApplicationContext context - + @Bean // @ExportMetricWriter // Add this when upgrading to Boot 1.3 MetricWriter writer() { new RedisMetricRepository(connectionFactory, metrics.prefix + metrics.getId(context.getId()) + '.' - + ObjectUtils.getIdentityHexString(context) + '.', + + ObjectUtils.getIdentityHexString(context) + '.', metrics.key) } // Remove this when upgrading to Boot 1.3 @Bean - @ConditionalOnMissingClass(name='org.springframework.boot.actuate.autoconfigure.ActuatorMetricWriter') + @ConditionalOnMissingClass(name = 'org.springframework.boot.actuate.autoconfigure.ActuatorMetricWriter') @Primary MetricRepository reader() { new InMemoryMetricRepository() @@ -78,15 +82,15 @@ class InitializrMetricsExporterAutoConfiguration { // Remove this when upgrading to Boot 1.3 @Bean - @ConditionalOnMissingClass(name='org.springframework.boot.actuate.autoconfigure.ActuatorMetricWriter') + @ConditionalOnMissingClass(name = 'org.springframework.boot.actuate.autoconfigure.ActuatorMetricWriter') Exporter exporter(InMemoryMetricRepository reader) { new MetricCopyExporter(reader, writer()) { - @Override - @Scheduled(fixedRateString = '${spring.metrics.export.default.delayMillis:5000}') - void export() { - super.export() - } - } + @Override + @Scheduled(fixedRateString = '${spring.metrics.export.default.delayMillis:5000}') + void export() { + super.export() + } + } } } diff --git a/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy b/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy index 4029b933..54828a15 100644 --- a/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy @@ -16,12 +16,14 @@ package io.spring.initializr.config -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.context.properties.ConfigurationProperties /** - * @author Dave Syer + * Metrics-related configuration. * + * @author Dave Syer + * @since 1.0 */ @ConfigurationProperties('initializr.metrics') class MetricsProperties { @@ -51,10 +53,6 @@ class MetricsProperties { @Value('${spring.metrics.export.default.delayMillis:5000}') long rateMillis = 5000L - boolean isEnabled() { - rateMillis > 0 - } - String getPrefix() { if (prefix.endsWith('.')) { return prefix diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy index 742809e4..f9b9df30 100644 --- a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy @@ -20,15 +20,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore import org.springframework.boot.context.properties.ConfigurationProperties -import com.fasterxml.jackson.annotation.JsonIgnoreProperties - /** * Configuration of the initializr service. * * @author Stephane Nicoll * @since 1.0 */ -@ConfigurationProperties(prefix = 'initializr', ignoreUnknownFields = false) +@ConfigurationProperties(prefix = 'initializr') class InitializrProperties extends InitializrConfiguration { @JsonIgnore diff --git a/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy b/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy index 70c94c02..4e72087c 100644 --- a/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy +++ b/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy @@ -14,21 +14,19 @@ * limitations under the License. */ -package io.spring.initializr.metrics; +package io.spring.initializr.metrics -import static org.junit.Assert.* import io.spring.initializr.generator.ProjectGenerationMetricsListener import io.spring.initializr.generator.ProjectRequest -import io.spring.initializr.metadata.DefaultMetadataElement import io.spring.initializr.metadata.InitializrMetadata import io.spring.initializr.metadata.InitializrMetadataProvider -import io.spring.initializr.support.DefaultInitializrMetadataProvider +import io.spring.initializr.test.OfflineInitializrMetadataProvider import io.spring.initializr.test.RedisRunning - -import org.junit.Before; +import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith + import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.actuate.metrics.repository.redis.RedisMetricRepository @@ -39,41 +37,44 @@ import org.springframework.boot.test.SpringApplicationConfiguration import org.springframework.context.annotation.Bean import org.springframework.test.context.junit4.SpringJUnit4ClassRunner +import static org.junit.Assert.assertTrue + /** * @author Dave Syer - * */ @RunWith(SpringJUnit4ClassRunner) @SpringApplicationConfiguration(classes = Config) -@IntegrationTest(['spring.metrics.export.default.delayMillis:500','initializr.metrics.prefix:test.prefix','initializr.metrics.key:key.test']) +@IntegrationTest(['spring.metrics.export.default.delayMillis:500', + 'spring.metrics.export.enabled:true', + 'initializr.metrics.prefix:test.prefix', 'initializr.metrics.key:key.test']) public class MetricsExportTests { @Rule public RedisRunning running = new RedisRunning() - + @Autowired ProjectGenerationMetricsListener listener - + @Autowired @Qualifier("writer") MetricWriter writer - + RedisMetricRepository repository - + @Before void init() { repository = (RedisMetricRepository) writer repository.findAll().each { repository.reset(it.name) } - assertTrue("Metrics not empty", repository.findAll().size()==0) + assertTrue("Metrics not empty", repository.findAll().size() == 0) } @Test void exportAndCheckMetricsExist() { listener.onGeneratedProject(new ProjectRequest()) - Thread.sleep(1000L) - assertTrue("No metrics exported", repository.findAll().size()>0) + Thread.sleep(1000L) + assertTrue("No metrics exported", repository.findAll().size() > 0) } @EnableAutoConfiguration @@ -81,12 +82,7 @@ public class MetricsExportTests { @Bean InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) { - new DefaultInitializrMetadataProvider(metadata) { - @Override - protected List fetchBootVersions() { - null // Disable metadata fetching from spring.io - } - } + new OfflineInitializrMetadataProvider(metadata) } } } diff --git a/initializr/src/test/groovy/io/spring/initializr/test/OfflineInitializrMetadataProvider.groovy b/initializr/src/test/groovy/io/spring/initializr/test/OfflineInitializrMetadataProvider.groovy new file mode 100644 index 00000000..4497ecec --- /dev/null +++ b/initializr/src/test/groovy/io/spring/initializr/test/OfflineInitializrMetadataProvider.groovy @@ -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 io.spring.initializr.test + +import io.spring.initializr.metadata.DefaultMetadataElement +import io.spring.initializr.metadata.InitializrMetadata +import io.spring.initializr.support.DefaultInitializrMetadataProvider + +/** + * A {@link DefaultInitializrMetadataProvider} that does not attempt to + * use the network to refresh its configuration. + * + * @author Stephane Nicoll + * @since 1.0 + */ +class OfflineInitializrMetadataProvider extends DefaultInitializrMetadataProvider { + + OfflineInitializrMetadataProvider(InitializrMetadata metadata) { + super(metadata) + } + + @Override + protected List fetchBootVersions() { + null // Disable metadata fetching from spring.io + } +} diff --git a/initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy b/initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy index c3224758..978f7020 100644 --- a/initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy +++ b/initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy @@ -20,19 +20,22 @@ import org.junit.Assume import org.junit.rules.TestWatcher import org.junit.runner.Description import org.junit.runners.model.Statement + import org.springframework.data.redis.connection.jedis.JedisConnectionFactory /** - * @author Dave Syer + * A {@link org.junit.rules.TestRule} that validates Redis is available. * + * @author Dave Syer + * @since 1.0 */ class RedisRunning extends TestWatcher { - - JedisConnectionFactory connectionFactory; + + JedisConnectionFactory connectionFactory; @Override Statement apply(Statement base, Description description) { - if (connectionFactory==null) { + if (connectionFactory == null) { connectionFactory = new JedisConnectionFactory() connectionFactory.afterPropertiesSet() } diff --git a/initializr/src/test/groovy/io/spring/initializr/web/AbstractInitializrControllerIntegrationTests.groovy b/initializr/src/test/groovy/io/spring/initializr/web/AbstractInitializrControllerIntegrationTests.groovy index d2bcf146..38f09b49 100644 --- a/initializr/src/test/groovy/io/spring/initializr/web/AbstractInitializrControllerIntegrationTests.groovy +++ b/initializr/src/test/groovy/io/spring/initializr/web/AbstractInitializrControllerIntegrationTests.groovy @@ -19,10 +19,9 @@ package io.spring.initializr.web import java.nio.charset.Charset import io.spring.initializr.mapper.InitializrMetadataVersion -import io.spring.initializr.metadata.DefaultMetadataElement import io.spring.initializr.metadata.InitializrMetadata -import io.spring.initializr.support.DefaultInitializrMetadataProvider import io.spring.initializr.metadata.InitializrMetadataProvider +import io.spring.initializr.test.OfflineInitializrMetadataProvider import io.spring.initializr.test.ProjectAssert import org.json.JSONObject import org.junit.Rule @@ -85,7 +84,7 @@ abstract class AbstractInitializrControllerIntegrationTests { */ protected void validateContentType(ResponseEntity response, MediaType expected) { def actual = response.headers.getContentType() - assertTrue "Non compatible media-type, expected $expected, got $actual" , + assertTrue "Non compatible media-type, expected $expected, got $actual", actual.isCompatibleWith(expected) assertEquals 'All text content should be UTF-8 encoded', 'UTF-8', actual.getParameter('charset') @@ -93,7 +92,7 @@ abstract class AbstractInitializrControllerIntegrationTests { protected void validateMetadata(ResponseEntity response, MediaType mediaType, - String version, JSONCompareMode compareMode) { + String version, JSONCompareMode compareMode) { validateContentType(response, mediaType) def json = new JSONObject(response.body) def expected = readMetadataJson(version) @@ -147,7 +146,7 @@ abstract class AbstractInitializrControllerIntegrationTests { } protected ResponseEntity execute(String contextPath, Class responseType, - String userAgentHeader, String... acceptHeaders) { + String userAgentHeader, String... acceptHeaders) { HttpHeaders headers = new HttpHeaders(); if (userAgentHeader) { headers.set("User-Agent", userAgentHeader); @@ -217,12 +216,7 @@ abstract class AbstractInitializrControllerIntegrationTests { @Bean InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) { - new DefaultInitializrMetadataProvider(metadata) { - @Override - protected List fetchBootVersions() { - null // Disable metadata fetching from spring.io - } - } + new OfflineInitializrMetadataProvider(metadata) } }