From 6f4d3f4e035fdc5295565653aa99c3f41f786954 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 24 Mar 2015 11:38:00 +0000 Subject: [PATCH 1/2] Add metrics exporter for initializr service If a RedisConnectionFactory is detected the system will now export metrics to redis every 5s (initializr.metrics.rateMillis). Metric names are prefixed with .. where defaults to the application name (initializr.metrics.id) and is unique. An aggregator app can then pick up the values and (for instance) continue counters across restarts. The code is meant to be easier to upgrade Spring Boot 1.3 There are 2 beans that we can simply remove when we upgrade to 1.3. Meanwhile, the app will run with 1.3 (or 1.2) for testing if you uncomment the @ExportMetricWriter. --- .gitignore | 3 +- initializr-service/app.groovy | 1 + initializr/pom.xml | 7 +- ...izrMetricsExporterAutoConfiguration.groovy | 92 +++++++++++++++++++ .../config/MetricsProperties.groovy | 69 ++++++++++++++ .../metadata/InitializrConfiguration.groovy | 2 +- .../metadata/InitializrProperties.groovy | 2 + .../main/resources/META-INF/spring.factories | 4 +- .../metrics/MetricsExportTests.groovy | 92 +++++++++++++++++++ .../initializr/test/RedisRunning.groovy | 47 ++++++++++ 10 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy create mode 100644 initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy create mode 100644 initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy create mode 100644 initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy diff --git a/.gitignore b/.gitignore index fb3644ab..084817f7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ tmp* initializer-service/spring grapes spring.zip +*.jar repository/ .idea -*.iml \ No newline at end of file +*.iml diff --git a/initializr-service/app.groovy b/initializr-service/app.groovy index fe88e7e2..8de70715 100644 --- a/initializr-service/app.groovy +++ b/initializr-service/app.groovy @@ -3,6 +3,7 @@ package app import io.spring.initializr.web.LegacyStsController @Grab('io.spring.initalizr:initializr:1.0.0.BUILD-SNAPSHOT') +@Grab('spring-boot-starter-redis') class InitializerService { @Bean diff --git a/initializr/pom.xml b/initializr/pom.xml index a98df6d7..525c1417 100644 --- a/initializr/pom.xml +++ b/initializr/pom.xml @@ -23,6 +23,11 @@ org.springframework spring-webmvc + + org.springframework.boot + spring-boot-starter-redis + true + org.springframework.boot spring-boot-starter-groovy-templates @@ -234,4 +239,4 @@ - \ No newline at end of file + diff --git a/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy new file mode 100644 index 00000000..e369392e --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/config/InitializrMetricsExporterAutoConfiguration.groovy @@ -0,0 +1,92 @@ +/* + * Copyright 2014-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.config + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.actuate.metrics.export.Exporter +import org.springframework.boot.actuate.metrics.export.MetricCopyExporter +import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository +import org.springframework.boot.actuate.metrics.repository.MetricRepository +import org.springframework.boot.actuate.metrics.repository.redis.RedisMetricRepository +import org.springframework.boot.actuate.metrics.writer.MetricWriter +import org.springframework.boot.autoconfigure.AutoConfigureAfter +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.ApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Primary +import org.springframework.data.redis.connection.RedisConnectionFactory +import org.springframework.scheduling.annotation.EnableScheduling +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.util.ObjectUtils + +/** + * @author Dave Syer + * + */ +@Configuration +@ConditionalOnBean(RedisConnectionFactory) +@ConditionalOnProperty(value='spring.metrics.export.enabled', matchIfMissing=true) +@EnableScheduling +@EnableConfigurationProperties(MetricsProperties) +@AutoConfigureAfter(value=RedisAutoConfiguration, name="org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration") +class InitializrMetricsExporterAutoConfiguration { + + @Autowired + RedisConnectionFactory connectionFactory + + @Autowired + MetricsProperties metrics + + @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) + '.', + metrics.key) + } + + // Remove this when upgrading to Boot 1.3 + @Bean + @ConditionalOnMissingClass(name='org.springframework.boot.actuate.autoconfigure.ActuatorMetricWriter') + @Primary + MetricRepository reader() { + new InMemoryMetricRepository() + } + + // Remove this when upgrading to Boot 1.3 + @Bean + @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() + } + } + } + +} diff --git a/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy b/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy new file mode 100644 index 00000000..4029b933 --- /dev/null +++ b/initializr/src/main/groovy/io/spring/initializr/config/MetricsProperties.groovy @@ -0,0 +1,69 @@ +/* + * Copyright 2014-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.config + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author Dave Syer + * + */ +@ConfigurationProperties('initializr.metrics') +class MetricsProperties { + + /** + * Prefix for redis keys holding metrics in data store. + */ + String prefix = 'spring.metrics.collector.' + + /** + * Redis key holding index to metrics keys in data store. + */ + String key = 'keys.spring.metrics.collector' + + /** + * Identifier for application in metrics keys. Keys will be exported in the form + * '[id].[hex].[name]' (where '[id]' is this value, '[hex]' is unique per application + * context, and '[name]' is the "natural" name for the metric. + */ + @Value('${spring.application.name:${vcap.application.name:application}}') + String id + + /** + * The rate (in milliseconds) at which metrics are exported to Redis. If the value is + * <=0 then the export is disabled. + */ + @Value('${spring.metrics.export.default.delayMillis:5000}') + long rateMillis = 5000L + + boolean isEnabled() { + rateMillis > 0 + } + + String getPrefix() { + if (prefix.endsWith('.')) { + return prefix + } + prefix + '.' + } + + String getId(String defaultValue) { + if (id) return id + defaultValue + } +} diff --git a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy index 94300fa0..3d0acbdb 100644 --- a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrConfiguration.groovy @@ -30,7 +30,7 @@ class InitializrConfiguration { } /** - * Generate a suitable application mame based on the specified name. If no suitable + * Generate a suitable application name based on the specified name. If no suitable * application name can be generated from the specified {@code name}, the * {@link Env#fallbackApplicationName} is used instead. *

No suitable application name can be generated if the name is {@code null} or 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 47b09946..742809e4 100644 --- a/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy +++ b/initializr/src/main/groovy/io/spring/initializr/metadata/InitializrProperties.groovy @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore import org.springframework.boot.context.properties.ConfigurationProperties +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + /** * Configuration of the initializr service. * diff --git a/initializr/src/main/resources/META-INF/spring.factories b/initializr/src/main/resources/META-INF/spring.factories index a6629e17..6c786bad 100644 --- a/initializr/src/main/resources/META-INF/spring.factories +++ b/initializr/src/main/resources/META-INF/spring.factories @@ -1 +1,3 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.spring.initializr.config.InitializrAutoConfiguration \ No newline at end of file +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +io.spring.initializr.config.InitializrAutoConfiguration,\ +io.spring.initializr.config.InitializrMetricsExporterAutoConfiguration \ No newline at end of file diff --git a/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy b/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy new file mode 100644 index 00000000..70c94c02 --- /dev/null +++ b/initializr/src/test/groovy/io/spring/initializr/metrics/MetricsExportTests.groovy @@ -0,0 +1,92 @@ +/* + * Copyright 2014-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.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.RedisRunning + +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 +import org.springframework.boot.actuate.metrics.writer.MetricWriter +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.test.IntegrationTest +import org.springframework.boot.test.SpringApplicationConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner + +/** + * @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']) +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) + } + + @Test + void exportAndCheckMetricsExist() { + listener.onGeneratedProject(new ProjectRequest()) + Thread.sleep(1000L) + assertTrue("No metrics exported", repository.findAll().size()>0) + } + + @EnableAutoConfiguration + static class Config { + + @Bean + InitializrMetadataProvider initializrMetadataProvider(InitializrMetadata metadata) { + new DefaultInitializrMetadataProvider(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 new file mode 100644 index 00000000..c3224758 --- /dev/null +++ b/initializr/src/test/groovy/io/spring/initializr/test/RedisRunning.groovy @@ -0,0 +1,47 @@ +/* + * Copyright 2014-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 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 + * + */ +class RedisRunning extends TestWatcher { + + JedisConnectionFactory connectionFactory; + + @Override + Statement apply(Statement base, Description description) { + if (connectionFactory==null) { + connectionFactory = new JedisConnectionFactory() + connectionFactory.afterPropertiesSet() + } + try { + connectionFactory.connection + } catch (Exception e) { + Assume.assumeNoException('Cannot connect to Redis (so skipping tests)', e) + } + super.apply(base, description) + } + +} From f1f87866315c94b2baa5414d8ca1ad3d9dcfe4a5 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 4 Jun 2015 14:19:17 +0200 Subject: [PATCH 2/2] 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) } }