diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/pom.xml b/opentracing-metrics-prometheus-spring-autoconfigure/pom.xml new file mode 100644 index 0000000..b2e2e7d --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + opentracing-metrics-parent + io.opentracing.contrib + 0.1.3-SNAPSHOT + + + opentracing-metrics-prometheus-spring-autoconfigure + + + + io.opentracing.contrib + opentracing-metrics-spring-autoconfigure + ${project.version} + + + + io.opentracing.contrib + opentracing-metrics-prometheus + ${project.version} + + + + io.prometheus + simpleclient + provided + + + io.prometheus + simpleclient_servlet + provided + + + + javax.servlet + javax.servlet-api + ${version.javax.servlet-api} + provided + + + + org.springframework.boot + spring-boot-starter-test + ${version.org.springframework.boot} + test + + + org.springframework.boot + spring-boot-starter-web + ${version.org.springframework.boot} + test + + + diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusConfiguration.java b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusConfiguration.java new file mode 100644 index 0000000..49f2597 --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusConfiguration.java @@ -0,0 +1,30 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.prometheus.spring.autoconfigure; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.prometheus.client.CollectorRegistry; + +@Configuration +public class PrometheusConfiguration { + + @Bean + @ConditionalOnMissingBean + public CollectorRegistry defaultCollectorRegistry() { + return CollectorRegistry.defaultRegistry; + } +} diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfiguration.java b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfiguration.java new file mode 100644 index 0000000..4cd82de --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfiguration.java @@ -0,0 +1,55 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.prometheus.spring.autoconfigure; + +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.opentracing.contrib.metrics.MetricLabel; +import io.opentracing.contrib.metrics.MetricsReporter; +import io.opentracing.contrib.metrics.prometheus.PrometheusMetricsReporter; +import io.prometheus.client.CollectorRegistry; + +@Configuration +public class PrometheusMetricsReporterConfiguration { + + @Autowired + private CollectorRegistry collectorRegistry; + + @Value("${OPENTRACING_METRICS_NAME:}") + private String metricsName; + + @Autowired(required=false) + private Set metricLabels; + + @Bean + public MetricsReporter prometheusMetricsReporter() { + PrometheusMetricsReporter.Builder builder = PrometheusMetricsReporter.newMetricsReporter(); + if (metricsName != null && !metricsName.isEmpty()) { + builder.withName(metricsName); + } + builder.withCollectorRegistry(collectorRegistry); + if (metricLabels != null && !metricLabels.isEmpty()) { + for (MetricLabel label : metricLabels) { + builder.withCustomLabel(label); + } + } + return builder.build(); + } + +} diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusServletConfiguration.java b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusServletConfiguration.java new file mode 100644 index 0000000..f30b3a4 --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusServletConfiguration.java @@ -0,0 +1,39 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.prometheus.spring.autoconfigure; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.exporter.MetricsServlet; + +@Configuration +@ConditionalOnClass(value = {MetricsServlet.class}) +public class PrometheusServletConfiguration { + + @Value("${OPENTRACING_METRICS_EXPORTER_HTTP_PATH:false}") + private String metricsPath; + + @Bean + @ConditionalOnProperty(name="OPENTRACING_METRICS_EXPORTER_HTTP_PATH") + ServletRegistrationBean registerPrometheusExporterServlet(CollectorRegistry metricRegistry) { + return new ServletRegistrationBean(new MetricsServlet(metricRegistry), metricsPath); + } + +} diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/main/resources/META-INF/spring.factories b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..69f8dbe --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +io.opentracing.contrib.metrics.prometheus.spring.autoconfigure.PrometheusConfiguration,\ +io.opentracing.contrib.metrics.prometheus.spring.autoconfigure.PrometheusMetricsReporterConfiguration,\ +io.opentracing.contrib.metrics.prometheus.spring.autoconfigure.PrometheusServletConfiguration diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationTest.java b/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationTest.java new file mode 100644 index 0000000..4299476 --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationTest.java @@ -0,0 +1,73 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.prometheus.spring.autoconfigure; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import io.opentracing.contrib.api.SpanData; +import io.opentracing.contrib.metrics.MetricsReporter; +import io.opentracing.tag.Tags; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; + +@SpringBootTest( + classes = {PrometheusMetricsReporterConfigurationTest.SpringConfiguration.class}) +@RunWith(SpringJUnit4ClassRunner.class) +public class PrometheusMetricsReporterConfigurationTest { + + private static final CollectorRegistry testCollectorRegistry = new CollectorRegistry(); + + @Autowired + private MetricsReporter metricsReporter; + + @Configuration + @EnableAutoConfiguration + public static class SpringConfiguration { + @Bean + public CollectorRegistry testCollectorRegistry() { + return testCollectorRegistry; + } + } + + @Test + public void testMetricsReporter() { + MetricFamilySamples samples = testCollectorRegistry.metricFamilySamples().nextElement(); + assertTrue(samples.samples.isEmpty()); + + SpanData metricSpanData=Mockito.mock(SpanData.class); + Mockito.when(metricSpanData.getOperationName()).thenReturn("testOp"); + Map testTags = new HashMap(); + testTags.put(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT); + Mockito.when(metricSpanData.getTags()).thenReturn(testTags); + Mockito.when(metricSpanData.getDuration()).thenReturn(500L); + metricsReporter.reportSpan(metricSpanData); + + samples = testCollectorRegistry.metricFamilySamples().nextElement(); + assertFalse(samples.samples.isEmpty()); + } + +} diff --git a/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationWithNameTest.java b/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationWithNameTest.java new file mode 100644 index 0000000..96e0771 --- /dev/null +++ b/opentracing-metrics-prometheus-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/prometheus/spring/autoconfigure/PrometheusMetricsReporterConfigurationWithNameTest.java @@ -0,0 +1,72 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.prometheus.spring.autoconfigure; + +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import io.opentracing.contrib.metrics.MetricsReporter; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; + +@SpringBootTest( + classes = {PrometheusMetricsReporterConfigurationWithNameTest.SpringConfiguration.class}) +@RunWith(SpringJUnit4ClassRunner.class) +public class PrometheusMetricsReporterConfigurationWithNameTest { + + private static final String METRICS_NAME = "testmetrics"; + + private static final CollectorRegistry testCollectorRegistry = new CollectorRegistry(); + + @Autowired + private MetricsReporter metricsReporter; + + @Configuration + @EnableAutoConfiguration + public static class SpringConfiguration { + @Bean + public CollectorRegistry testCollectorRegistry() { + return testCollectorRegistry; + } + } + + @BeforeClass + public static void init() { + System.setProperty("OPENTRACING_METRICS_NAME", METRICS_NAME); + } + + @AfterClass + public static void close() { + System.clearProperty("OPENTRACING_METRICS_NAME"); + } + + @Test + public void testMetricsReporterName() { + assertNotNull(metricsReporter); + + MetricFamilySamples samples = testCollectorRegistry.metricFamilySamples().nextElement(); + assertEquals(METRICS_NAME, samples.name); + } + +} diff --git a/opentracing-metrics-spring-autoconfigure/pom.xml b/opentracing-metrics-spring-autoconfigure/pom.xml new file mode 100644 index 0000000..dc601bf --- /dev/null +++ b/opentracing-metrics-spring-autoconfigure/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + opentracing-metrics-parent + io.opentracing.contrib + 0.1.3-SNAPSHOT + + + opentracing-metrics-spring-autoconfigure + + + + io.opentracing.contrib + opentracing-api-extensions-tracer-spring-autoconfigure + + + + io.opentracing.contrib + opentracing-metrics + ${project.version} + + + + org.springframework.boot + spring-boot-autoconfigure + ${version.org.springframework.boot} + + + + io.opentracing.contrib + opentracing-metrics-prometheus + ${project.version} + + + + io.prometheus + simpleclient + provided + + + io.prometheus + simpleclient_servlet + provided + + + + javax.servlet + javax.servlet-api + ${version.javax.servlet-api} + provided + + + + org.springframework.boot + spring-boot-starter-test + ${version.org.springframework.boot} + test + + + org.springframework.boot + spring-boot-starter-web + ${version.org.springframework.boot} + test + + + diff --git a/opentracing-metrics-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfiguration.java b/opentracing-metrics-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfiguration.java new file mode 100644 index 0000000..cb122a0 --- /dev/null +++ b/opentracing-metrics-spring-autoconfigure/src/main/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfiguration.java @@ -0,0 +1,40 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.spring.autoconfigure; + +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.opentracing.contrib.api.TracerObserver; +import io.opentracing.contrib.metrics.MetricsObserver; +import io.opentracing.contrib.metrics.MetricsReporter; + +@Configuration +public class MetricsTracerObserverConfiguration { + + @Autowired(required=false) + private Set metricsReporters; + + @Bean + public TracerObserver metricsTracerObserver() { + if (metricsReporters != null && !metricsReporters.isEmpty()) { + return new MetricsObserver(metricsReporters); + } + return null; + } + +} diff --git a/opentracing-metrics-spring-autoconfigure/src/main/resources/META-INF/spring.factories b/opentracing-metrics-spring-autoconfigure/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..1d80dc4 --- /dev/null +++ b/opentracing-metrics-spring-autoconfigure/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +io.opentracing.contrib.metrics.spring.autoconfigure.MetricsTracerObserverConfiguration diff --git a/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationNoReportersTest.java b/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationNoReportersTest.java new file mode 100644 index 0000000..4569408 --- /dev/null +++ b/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationNoReportersTest.java @@ -0,0 +1,45 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.spring.autoconfigure; + +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import io.opentracing.contrib.api.TracerObserver; + +@SpringBootTest( + classes = {MetricsTracerObserverConfigurationNoReportersTest.SpringConfiguration.class}) +@RunWith(SpringJUnit4ClassRunner.class) +public class MetricsTracerObserverConfigurationNoReportersTest { + + @Configuration + @EnableAutoConfiguration + public static class SpringConfiguration { + } + + @Autowired(required=false) + protected TracerObserver tracerObserver; + + @Test + public void testTracerObserverNoReporters() { + // No tracer observer should be found, as no metrics reporters have been defined + assertNull(tracerObserver); + } +} diff --git a/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationWithReportersTest.java b/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationWithReportersTest.java new file mode 100644 index 0000000..92041f9 --- /dev/null +++ b/opentracing-metrics-spring-autoconfigure/src/test/java/io/opentracing/contrib/metrics/spring/autoconfigure/MetricsTracerObserverConfigurationWithReportersTest.java @@ -0,0 +1,61 @@ +/** + * Copyright 2017 The OpenTracing 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.opentracing.contrib.metrics.spring.autoconfigure; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import io.opentracing.contrib.api.SpanData; +import io.opentracing.contrib.api.TracerObserver; +import io.opentracing.contrib.metrics.MetricsReporter; + +@SpringBootTest( + classes = {MetricsTracerObserverConfigurationWithReportersTest.SpringConfiguration.class}) +@RunWith(SpringJUnit4ClassRunner.class) +public class MetricsTracerObserverConfigurationWithReportersTest { + + private static final MetricsReporter metricsReporter = Mockito.mock(MetricsReporter.class); + + @Configuration + @EnableAutoConfiguration + public static class SpringConfiguration { + @Bean + public MetricsReporter reporter() { + return metricsReporter; + } + } + + @Autowired(required=false) + protected TracerObserver tracerObserver; + + @Test + public void testTracerObserverWithReporters() { + assertNotNull(tracerObserver); + + SpanData spanData = Mockito.mock(SpanData.class); + + tracerObserver.onStart(spanData).onFinish(spanData, System.currentTimeMillis()); + + Mockito.verify(metricsReporter).reportSpan(spanData); + } +} diff --git a/pom.xml b/pom.xml index c06a62f..84b895a 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,9 @@ opentracing-metrics + opentracing-metrics-spring-autoconfigure opentracing-metrics-prometheus + opentracing-metrics-prometheus-spring-autoconfigure @@ -67,10 +69,12 @@ UTF-8 0.30.0 - 0.0.2 + 0.0.3 0.0.23 + 3.1.0 4.12 1.10.19 + 1.4.1.RELEASE 0.3.4 0.1.0 @@ -109,6 +113,11 @@ opentracing-api-extensions-tracer ${version.io.opentracing.contrib.opentracing-api-extensions} + + io.opentracing.contrib + opentracing-api-extensions-tracer-spring-autoconfigure + ${version.io.opentracing.contrib.opentracing-api-extensions} + @@ -199,6 +208,7 @@ mvnw.cmd travis/publish.sh .mvn/wrapper/maven-wrapper.properties + **/*.factories