Handle placeholders and SpEL in metrics properties
Fix #907 - Placeholders are replaced and expressions are evaluated before on attached properties Add test for default value
This commit is contained in:
committed by
Vinicius Carvalho
parent
d6fe841a63
commit
ab76178b82
@@ -20,6 +20,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.boot.actuate.metrics.export.MetricExportProperties;
|
||||
import org.springframework.boot.actuate.metrics.export.TriggerProperties;
|
||||
import org.springframework.boot.bind.RelaxedNames;
|
||||
@@ -28,8 +30,10 @@ import org.springframework.cloud.stream.metrics.config.BinderMetricsAutoConfigur
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
@@ -49,14 +53,15 @@ public class ApplicationMetricsProperties
|
||||
|
||||
private String[] properties;
|
||||
|
||||
private MetricExportProperties export;
|
||||
private final MetricExportProperties metricExportProperties;
|
||||
|
||||
public TriggerProperties getTrigger() {
|
||||
return export.findTrigger(BinderMetricsAutoConfiguration.APPLICATION_METRICS_EXPORTER_TRIGGER_NAME);
|
||||
return metricExportProperties.findTrigger(BinderMetricsAutoConfiguration.APPLICATION_METRICS_EXPORTER_TRIGGER_NAME);
|
||||
}
|
||||
|
||||
public ApplicationMetricsProperties(MetricExportProperties export) {
|
||||
this.export = export;
|
||||
public ApplicationMetricsProperties(MetricExportProperties metricExportProperties) {
|
||||
Assert.notNull(metricExportProperties, "'metricsExportProperties' cannot be null");
|
||||
this.metricExportProperties = metricExportProperties;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
@@ -114,20 +119,31 @@ public class ApplicationMetricsProperties
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) event
|
||||
.getSource();
|
||||
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) event.getSource();
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
BeanExpressionResolver beanExpressionResolver = ctx.getBeanFactory().getBeanExpressionResolver();
|
||||
BeanExpressionContext expressionContext = new BeanExpressionContext(ctx.getBeanFactory(), null);
|
||||
if (!ObjectUtils.isEmpty(this.properties)) {
|
||||
for (PropertySource<?> source : ctx.getEnvironment().getPropertySources()) {
|
||||
for (PropertySource<?> source : environment.getPropertySources()) {
|
||||
if (source instanceof EnumerablePropertySource) {
|
||||
EnumerablePropertySource<?> e = (EnumerablePropertySource<?>) source;
|
||||
for (String propertyName : e.getPropertyNames()) {
|
||||
RelaxedNames relaxedNames = new RelaxedNames(propertyName);
|
||||
relaxedLoop: for (String relaxedPropertyName : relaxedNames) {
|
||||
if (isMatch(relaxedPropertyName, this.properties, null)) {
|
||||
Object value = source.getProperty(propertyName);
|
||||
String stringValue = ObjectUtils.nullSafeToString(value);
|
||||
Object exportedValue = null;
|
||||
if (value != null) {
|
||||
exportedValue = stringValue.startsWith("#{")
|
||||
? beanExpressionResolver.evaluate(
|
||||
environment.resolvePlaceholders(stringValue), expressionContext)
|
||||
: environment.resolvePlaceholders(stringValue);
|
||||
}
|
||||
this.exportProperties.put(
|
||||
RelaxedPropertiesUtils
|
||||
.findCanonicalFormat(relaxedNames),
|
||||
source.getProperty(propertyName));
|
||||
exportedValue);
|
||||
break relaxedLoop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
@@ -204,6 +204,44 @@ public class ApplicationMetricsExporterTests {
|
||||
applicationContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesWithPlaceholdersAndExpressions() throws Exception {
|
||||
ConfigurableApplicationContext applicationContext = SpringApplication.run(
|
||||
BinderExporterApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--PLATFORM_APP_NAME=123-name-foo",
|
||||
"--PLATFORM_APP_ID=123-id-bar",
|
||||
"--spring.cloud.application.guid=${PLATFORM_APP_NAME}.${PLATFORM_APP_ID}",
|
||||
"--spring.cloud.application.guid.expression=#{'${PLATFORM_APP_NAME}' + '..' + '${PLATFORM_APP_ID}'}",
|
||||
"--spring.cloud.application.guid.default.prop=${app.name.not.found:time-source}",
|
||||
"--spring.cloud.application.guid.default.env=${APP_NAME_NOT_FOUND:time-source}",
|
||||
"--spring.metrics.export.delay-millis=500",
|
||||
"--spring.cloud.stream.bindings." + Emitter.APPLICATION_METRICS + ".destination=foo",
|
||||
"--spring.metrics.export.includes=integration**",
|
||||
"--spring.cloud.stream.metrics.properties=spring**");
|
||||
Emitter emitterSource = applicationContext.getBean(Emitter.class);
|
||||
MessageCollector collector = applicationContext.getBean(MessageCollector.class);
|
||||
Message<?> message = collector.forChannel(emitterSource.applicationMetrics()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid"))
|
||||
.isEqualTo("123-name-foo.123-id-bar");
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid.expression"))
|
||||
.isEqualTo("123-name-foo..123-id-bar");
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid.default.prop"))
|
||||
.isEqualTo("time-source");
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid.default.env"))
|
||||
.isEqualTo("time-source");
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(applicationMetrics.getProperties()));
|
||||
Assert.assertTrue(applicationMetrics.getProperties().get("spring.test.env.syntax").equals("testing"));
|
||||
applicationContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overrideAppName() throws Exception {
|
||||
ConfigurableApplicationContext applicationContext = SpringApplication.run(
|
||||
|
||||
Reference in New Issue
Block a user