/* * Copyright 2012-2017 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.Map; import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader; import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.export.MetricCopyExporter; import org.springframework.boot.actuate.metrics.export.MetricExporters; import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter; import org.springframework.boot.actuate.metrics.writer.GaugeWriter; import org.springframework.boot.actuate.metrics.writer.MetricWriter; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.channel.FixedSubscriberChannel; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.messaging.SubscribableChannel; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.verify; /** * Tests for {@link MetricExportAutoConfiguration}. * * @author Phillip Webb * @author Dave Syer * @author Simon Buettner */ public class MetricExportAutoConfigurationTests { @Rule public ExpectedException thrown = ExpectedException.none(); private AnnotationConfigApplicationContext context; @After public void after() { if (this.context != null) { this.context.close(); } } @Test public void metricsFlushAutomatically() throws Exception { this.context = new AnnotationConfigApplicationContext(WriterConfig.class, MetricRepositoryAutoConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); GaugeService gaugeService = this.context.getBean(GaugeService.class); assertThat(gaugeService).isNotNull(); gaugeService.submit("foo", 2.7); MetricExporters flusher = this.context.getBean(MetricExporters.class); flusher.close(); // this will be called by Spring on shutdown MetricWriter writer = this.context.getBean("writer", MetricWriter.class); verify(writer, atLeastOnce()).set(any(Metric.class)); } @Test public void defaultExporterWhenMessageChannelAvailable() throws Exception { this.context = new AnnotationConfigApplicationContext( MessageChannelConfiguration.class, MetricRepositoryAutoConfiguration.class, MetricsChannelAutoConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); MetricExporters exporter = this.context.getBean(MetricExporters.class); assertThat(exporter).isNotNull(); assertThat(exporter.getExporters()).containsKey("messageChannelMetricWriter"); } @Test public void provideAdditionalWriter() { this.context = new AnnotationConfigApplicationContext(WriterConfig.class, MetricRepositoryAutoConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); GaugeService gaugeService = this.context.getBean(GaugeService.class); assertThat(gaugeService).isNotNull(); gaugeService.submit("foo", 2.7); MetricExporters exporters = this.context.getBean(MetricExporters.class); MetricCopyExporter exporter = (MetricCopyExporter) exporters.getExporters() .get("writer"); exporter.setIgnoreTimestamps(true); exporter.export(); MetricWriter writer = this.context.getBean("writer", MetricWriter.class); Mockito.verify(writer, Mockito.atLeastOnce()).set(any(Metric.class)); } @Test public void exportMetricsEndpoint() { this.context = new AnnotationConfigApplicationContext(WriterConfig.class, MetricEndpointConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); MetricExporters exporters = this.context.getBean(MetricExporters.class); MetricCopyExporter exporter = (MetricCopyExporter) exporters.getExporters() .get("writer"); exporter.setIgnoreTimestamps(true); exporter.export(); MetricsEndpointMetricReader reader = this.context.getBean("endpointReader", MetricsEndpointMetricReader.class); Mockito.verify(reader, Mockito.atLeastOnce()).findAll(); } @Test public void statsdMissingHost() throws Exception { this.context = new AnnotationConfigApplicationContext(); this.context.register(WriterConfig.class, MetricEndpointConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); this.thrown.expect(NoSuchBeanDefinitionException.class); this.context.getBean(StatsdMetricWriter.class); } @SuppressWarnings("unchecked") @Test public void statsdWithHost() throws Exception { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, "spring.metrics.export.statsd.host=localhost"); this.context.register(MetricEndpointConfiguration.class, MetricExportAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); StatsdMetricWriter statsdWriter = this.context.getBean(StatsdMetricWriter.class); assertThat(statsdWriter).isNotNull(); SchedulingConfigurer schedulingConfigurer = this.context .getBean(SchedulingConfigurer.class); Map<String, GaugeWriter> exporters = (Map<String, GaugeWriter>) ReflectionTestUtils .getField(schedulingConfigurer, "writers"); assertThat(exporters).containsValue(statsdWriter); } @Configuration public static class MessageChannelConfiguration { @Bean public SubscribableChannel metricsChannel() { return new FixedSubscriberChannel(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { } }); } } @Configuration public static class WriterConfig { @Bean @ExportMetricWriter public MetricWriter writer() { return Mockito.mock(MetricWriter.class); } } @Configuration public static class MetricEndpointConfiguration { @Bean @ExportMetricReader public MetricsEndpointMetricReader endpointReader() { return Mockito.mock(MetricsEndpointMetricReader.class); } } }