From cae634a56d54a09e022ce775c8a5ad171eb74144 Mon Sep 17 00:00:00 2001 From: Jon Schneider Date: Sun, 10 Sep 2017 22:59:45 -0500 Subject: [PATCH 1/2] Remove old metrics code and dependencies --- spring-boot-actuator/pom.xml | 35 -- .../CacheStatisticsAutoConfiguration.java | 150 ----- .../autoconfigure/cache/package-info.java | 20 - .../endpoint/EndpointAutoConfiguration.java | 52 +- .../metrics/ActuatorMetricWriter.java | 43 -- .../metrics/ExportMetricReader.java | 43 -- .../metrics/ExportMetricWriter.java | 43 -- .../MetricExportAutoConfiguration.java | 147 ----- .../MetricFilterAutoConfiguration.java | 75 --- .../metrics/MetricFilterProperties.java | 69 --- .../MetricRepositoryAutoConfiguration.java | 114 ---- .../MetricsChannelAutoConfiguration.java | 51 -- .../MetricsDropwizardAutoConfiguration.java | 80 --- .../PublicMetricsAutoConfiguration.java | 170 ------ .../autoconfigure/metrics/package-info.java | 20 - .../AbstractJmxCacheStatisticsProvider.java | 133 ----- .../boot/actuate/cache/CacheStatistics.java | 66 --- .../cache/CacheStatisticsProvider.java | 42 -- .../CaffeineCacheStatisticsProvider.java | 46 -- .../ConcurrentMapCacheStatisticsProvider.java | 39 -- .../actuate/cache/DefaultCacheStatistics.java | 90 --- .../cache/EhCacheStatisticsProvider.java | 55 -- .../HazelcastCacheStatisticsProvider.java | 46 -- .../InfinispanCacheStatisticsProvider.java | 73 --- .../cache/JCacheCacheStatisticsProvider.java | 63 -- .../boot/actuate/cache/package-info.java | 20 - .../actuate/endpoint/CachePublicMetrics.java | 161 ----- .../endpoint/DataSourcePublicMetrics.java | 128 ---- .../endpoint/MetricReaderPublicMetrics.java | 53 -- .../actuate/endpoint/MetricsEndpoint.java | 108 ---- .../endpoint/MetricsEndpointMetricReader.java | 72 --- .../boot/actuate/endpoint/PublicMetrics.java | 41 -- .../RichGaugeReaderPublicMetrics.java | 63 -- .../actuate/endpoint/SystemPublicMetrics.java | 194 ------ .../actuate/endpoint/TomcatPublicMetrics.java | 97 --- .../boot/actuate/metrics/CounterService.java | 44 -- .../boot/actuate/metrics/GaugeService.java | 40 -- .../boot/actuate/metrics/Metric.java | 137 ----- .../aggregate/AggregateMetricReader.java | 158 ----- .../metrics/aggregate/package-info.java | 20 - .../boot/actuate/metrics/buffer/Buffer.java | 48 -- .../metrics/buffer/BufferCounterService.java | 71 --- .../metrics/buffer/BufferGaugeService.java | 62 -- .../metrics/buffer/BufferMetricReader.java | 90 --- .../boot/actuate/metrics/buffer/Buffers.java | 62 -- .../actuate/metrics/buffer/CounterBuffer.java | 49 -- .../metrics/buffer/CounterBuffers.java | 46 -- .../actuate/metrics/buffer/GaugeBuffer.java | 43 -- .../actuate/metrics/buffer/GaugeBuffers.java | 39 -- .../actuate/metrics/buffer/package-info.java | 20 - .../dropwizard/DropwizardMetricServices.java | 279 --------- .../metrics/dropwizard/ReservoirFactory.java | 45 -- .../metrics/dropwizard/package-info.java | 20 - .../export/AbstractMetricExporter.java | 184 ------ .../boot/actuate/metrics/export/Exporter.java | 38 -- .../metrics/export/MetricCopyExporter.java | 244 -------- .../export/MetricExportProperties.java | 265 --------- .../metrics/export/MetricExporters.java | 134 ----- .../export/PrefixMetricGroupExporter.java | 118 ---- .../metrics/export/RichGaugeExporter.java | 98 --- .../export/SpecificTriggerProperties.java | 40 -- .../metrics/export/TriggerProperties.java | 94 --- .../actuate/metrics/export/package-info.java | 20 - .../SpringIntegrationMetricReader.java | 131 ---- .../metrics/integration/package-info.java | 20 - .../jmx/DefaultMetricNamingStrategy.java | 65 -- .../actuate/metrics/jmx/JmxMetricWriter.java | 169 ------ .../actuate/metrics/jmx/package-info.java | 20 - .../DefaultOpenTsdbNamingStrategy.java | 79 --- .../metrics/opentsdb/OpenTsdbData.java | 85 --- .../metrics/opentsdb/OpenTsdbGaugeWriter.java | 169 ------ .../metrics/opentsdb/OpenTsdbName.java | 61 -- .../opentsdb/OpenTsdbNamingStrategy.java | 35 -- .../metrics/opentsdb/package-info.java | 20 - .../boot/actuate/metrics/package-info.java | 20 - .../metrics/reader/CompositeMetricReader.java | 71 --- .../actuate/metrics/reader/MetricReader.java | 48 -- .../reader/MetricRegistryMetricReader.java | 254 -------- .../metrics/reader/PrefixMetricReader.java | 36 -- .../actuate/metrics/reader/package-info.java | 22 - .../repository/InMemoryMetricRepository.java | 83 --- .../InMemoryMultiMetricRepository.java | 111 ---- .../metrics/repository/MetricRepository.java | 29 - .../repository/MultiMetricRepository.java | 42 -- .../metrics/repository/package-info.java | 22 - .../redis/RedisMetricRepository.java | 198 ------- .../redis/RedisMultiMetricRepository.java | 169 ------ .../metrics/repository/redis/RedisUtils.java | 55 -- .../repository/redis/package-info.java | 22 - .../rich/InMemoryRichGaugeRepository.java | 82 --- .../rich/MultiMetricRichGaugeReader.java | 88 --- .../boot/actuate/metrics/rich/RichGauge.java | 238 -------- .../actuate/metrics/rich/RichGaugeReader.java | 45 -- .../metrics/rich/RichGaugeRepository.java | 28 - .../actuate/metrics/rich/package-info.java | 22 - .../metrics/statsd/StatsdMetricWriter.java | 142 ----- .../actuate/metrics/statsd/package-info.java | 20 - .../util/SimpleInMemoryRepository.java | 117 ---- .../actuate/metrics/util/package-info.java | 22 - .../metrics/web/servlet/MetricsFilter.java | 271 --------- .../web/servlet/MetricsFilterSubmission.java | 37 -- .../metrics/web/servlet/package-info.java | 20 - .../metrics/writer/CompositeMetricWriter.java | 70 --- .../actuate/metrics/writer/CounterWriter.java | 43 -- .../metrics/writer/DefaultCounterService.java | 70 --- .../metrics/writer/DefaultGaugeService.java | 62 -- .../boot/actuate/metrics/writer/Delta.java | 39 -- .../actuate/metrics/writer/GaugeWriter.java | 36 -- .../writer/MessageChannelMetricWriter.java | 53 -- .../actuate/metrics/writer/MetricMessage.java | 70 --- .../actuate/metrics/writer/MetricWriter.java | 30 - .../writer/MetricWriterMessageHandler.java | 70 --- .../metrics/writer/PrefixMetricWriter.java | 54 -- .../actuate/metrics/writer/package-info.java | 20 - ...CacheStatisticsAutoConfigurationTests.java | 314 ---------- .../MetricExportAutoConfigurationTests.java | 197 ------ .../MetricFilterAutoConfigurationTests.java | 561 ------------------ ...etricRepositoryAutoConfigurationTests.java | 108 ---- ...tricsDropwizardAutoConfigurationTests.java | 91 --- .../PublicMetricsAutoConfigurationTests.java | 382 ------------ .../endpoint/CachePublicMetricsTests.java | 113 ---- .../MetricReaderPublicMetricsTests.java | 49 -- .../endpoint/MetricsEndpointTests.java | 127 ---- .../RichGaugeReaderPublicMetricsTests.java | 70 --- .../endpoint/SystemPublicMetricsTests.java | 64 -- .../endpoint/TomcatPublicMetricsTests.java | 67 --- .../MetricsEndpointMvcIntegrationTests.java | 111 ---- .../boot/actuate/metrics/Iterables.java | 38 -- .../aggregate/AggregateMetricReaderTests.java | 114 ---- .../buffer/BufferGaugeServiceSpeedTests.java | 141 ----- .../buffer/BufferMetricReaderTests.java | 58 -- .../metrics/buffer/CounterBuffersTests.java | 54 -- .../buffer/CounterServiceSpeedTests.java | 140 ----- .../DefaultCounterServiceSpeedTests.java | 113 ---- .../buffer/DefaultGaugeServiceSpeedTests.java | 113 ---- .../DropwizardCounterServiceSpeedTests.java | 115 ---- .../metrics/buffer/NullPrintWriter.java | 39 -- .../DropwizardMetricServicesTests.java | 196 ------ .../export/MetricCopyExporterTests.java | 135 ----- .../metrics/export/MetricExportersTests.java | 83 --- .../PrefixMetricGroupExporterTests.java | 94 --- .../export/RichGaugeExporterTests.java | 49 -- ...ringIntegrationMetricReaderNoJmxTests.java | 60 -- .../SpringIntegrationMetricReaderTests.java | 66 --- .../jmx/DefaultMetricNamingStrategyTests.java | 71 --- .../opentsdb/OpenTsdbGaugeWriterTests.java | 81 --- .../MetricRegistryMetricReaderTests.java | 60 -- .../InMemoryMetricRepositoryTests.java | 52 -- .../InMemoryMultiMetricRepositoryTests.java | 101 ---- .../redis/RedisMetricRepositoryTests.java | 108 ---- .../RedisMultiMetricRepositoryTests.java | 146 ----- .../InMemoryRichGaugeRepositoryTests.java | 60 -- .../rich/MultiMetricRichGaugeReaderTests.java | 68 --- .../statsd/StatsdMetricWriterTests.java | 167 ------ .../util/SimpleInMemoryRepositoryTests.java | 116 ---- .../writer/DefaultCounterServiceTests.java | 87 --- .../writer/DefaultGaugeServiceTests.java | 49 -- .../MessageChannelMetricWriterTests.java | 82 --- 158 files changed, 11 insertions(+), 14094 deletions(-) delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ActuatorMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterProperties.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsChannelAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfiguration.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/AbstractJmxCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatistics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CaffeineCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/ConcurrentMapCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/DefaultCacheStatistics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/EhCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/HazelcastCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/InfinispanCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/JCacheCacheStatisticsProvider.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/CachePublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DataSourcePublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpointMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/PublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SystemPublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetrics.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/CounterService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/GaugeService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/Metric.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffer.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferCounterService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffers.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffer.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffers.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffer.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffers.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/ReservoirFactory.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/Exporter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExportProperties.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/SpecificTriggerProperties.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/TriggerProperties.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategy.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/JmxMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/DefaultOpenTsdbNamingStrategy.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbData.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbName.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbNamingStrategy.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/CompositeMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/PrefixMetricReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisUtils.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGauge.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeReader.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepository.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilterSubmission.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/package-info.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CompositeMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CounterWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeService.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/Delta.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/GaugeWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricMessage.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriterMessageHandler.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/PrefixMetricWriter.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/package-info.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfigurationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/CachePublicMetricsTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetricsTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetricsTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SystemPublicMetricsTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetricsTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/MetricsEndpointMvcIntegrationTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/Iterables.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReaderTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeServiceSpeedTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReaderTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffersTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterServiceSpeedTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultCounterServiceSpeedTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultGaugeServiceSpeedTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DropwizardCounterServiceSpeedTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/NullPrintWriter.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporterTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricExportersTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategyTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriterTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriterTests.java delete mode 100755 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepositoryTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterServiceTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeServiceTests.java delete mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriterTests.java diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index ad91aba54100..37f4d6f366a2 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -47,41 +47,16 @@ jackson-dataformat-xml true - - com.github.ben-manes.caffeine - caffeine - true - - - com.hazelcast - hazelcast - true - - - com.hazelcast - hazelcast-spring - true - com.sun.mail javax.mail true - - com.timgroup - java-statsd-client - true - com.zaxxer HikariCP true - - io.dropwizard.metrics - metrics-core - true - io.lettuce lettuce-core @@ -92,11 +67,6 @@ jest true - - javax.cache - cache-api - true - javax.jms javax.jms-api @@ -107,11 +77,6 @@ javax.servlet-api true - - net.sf.ehcache - ehcache - true - org.apache.activemq activemq-broker diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfiguration.java deleted file mode 100644 index af59da37f6d3..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfiguration.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.cache; - -import javax.cache.Caching; - -import com.github.benmanes.caffeine.cache.Caffeine; -import com.hazelcast.core.IMap; -import com.hazelcast.spring.cache.HazelcastCache; -import net.sf.ehcache.Ehcache; -import net.sf.ehcache.statistics.StatisticsGateway; -import org.infinispan.spring.provider.SpringCache; - -import org.springframework.boot.actuate.cache.CacheStatistics; -import org.springframework.boot.actuate.cache.CacheStatisticsProvider; -import org.springframework.boot.actuate.cache.CaffeineCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.ConcurrentMapCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.DefaultCacheStatistics; -import org.springframework.boot.actuate.cache.EhCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.HazelcastCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.InfinispanCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.JCacheCacheStatisticsProvider; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.cache.caffeine.CaffeineCacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCache; -import org.springframework.cache.ehcache.EhCacheCache; -import org.springframework.cache.jcache.JCacheCache; -import org.springframework.cache.support.NoOpCacheManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for {@link CacheStatisticsProvider} - * beans. - * - * @author Stephane Nicoll - * @author Phillip Webb - * @author EddĂș MelĂ©ndez - * @since 2.0.0 - */ -@Configuration -@AutoConfigureAfter(CacheAutoConfiguration.class) -@ConditionalOnBean(CacheManager.class) -public class CacheStatisticsAutoConfiguration { - - @Configuration - @ConditionalOnClass({ Caching.class, JCacheCache.class }) - static class JCacheCacheStatisticsProviderConfiguration { - - @Bean - public JCacheCacheStatisticsProvider jCacheCacheStatisticsProvider() { - return new JCacheCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass({ EhCacheCache.class, Ehcache.class, StatisticsGateway.class }) - static class EhCacheCacheStatisticsProviderConfiguration { - - @Bean - public EhCacheStatisticsProvider ehCacheCacheStatisticsProvider() { - return new EhCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass({ IMap.class, HazelcastCache.class }) - static class HazelcastCacheStatisticsConfiguration { - - @Bean - public HazelcastCacheStatisticsProvider hazelcastCacheStatisticsProvider() { - return new HazelcastCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass({ SpringCache.class }) - static class InfinispanCacheStatisticsProviderConfiguration { - - @Bean - public InfinispanCacheStatisticsProvider infinispanCacheStatisticsProvider() { - return new InfinispanCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class }) - static class CaffeineCacheStatisticsProviderConfiguration { - - @Bean - public CaffeineCacheStatisticsProvider caffeineCacheStatisticsProvider() { - return new CaffeineCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass(ConcurrentMapCache.class) - static class ConcurrentMapCacheStatisticsConfiguration { - - @Bean - public ConcurrentMapCacheStatisticsProvider concurrentMapCacheStatisticsProvider() { - return new ConcurrentMapCacheStatisticsProvider(); - } - - } - - @Configuration - @ConditionalOnClass(NoOpCacheManager.class) - static class NoOpCacheStatisticsConfiguration { - - private static final CacheStatistics NO_OP_STATS = new DefaultCacheStatistics(); - - @Bean - public CacheStatisticsProvider noOpCacheStatisticsProvider() { - return (cacheManager, cache) -> { - if (cacheManager instanceof NoOpCacheManager) { - return NO_OP_STATS; - } - return null; - }; - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/package-info.java deleted file mode 100644 index cac6f73cc5e4..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Auto-configuration for cache statistics. - */ -package org.springframework.boot.actuate.autoconfigure.cache; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java index 40b3a0f3fcf1..e5398a1e7c97 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java @@ -22,44 +22,17 @@ import java.util.Map; import java.util.function.Supplier; -import liquibase.integration.spring.SpringLiquibase; import org.flywaydb.core.Flyway; - import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.audit.AuditEventRepository; -import org.springframework.boot.actuate.endpoint.AuditEventsEndpoint; -import org.springframework.boot.actuate.endpoint.AutoConfigurationReportEndpoint; -import org.springframework.boot.actuate.endpoint.BeansEndpoint; -import org.springframework.boot.actuate.endpoint.ConfigurationPropertiesReportEndpoint; -import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint; -import org.springframework.boot.actuate.endpoint.FlywayEndpoint; -import org.springframework.boot.actuate.endpoint.HealthEndpoint; -import org.springframework.boot.actuate.endpoint.InfoEndpoint; -import org.springframework.boot.actuate.endpoint.LiquibaseEndpoint; -import org.springframework.boot.actuate.endpoint.LoggersEndpoint; -import org.springframework.boot.actuate.endpoint.MetricsEndpoint; -import org.springframework.boot.actuate.endpoint.PublicMetrics; -import org.springframework.boot.actuate.endpoint.RequestMappingEndpoint; -import org.springframework.boot.actuate.endpoint.ShutdownEndpoint; -import org.springframework.boot.actuate.endpoint.StatusEndpoint; -import org.springframework.boot.actuate.endpoint.ThreadDumpEndpoint; -import org.springframework.boot.actuate.endpoint.TraceEndpoint; -import org.springframework.boot.actuate.health.CompositeHealthIndicatorFactory; -import org.springframework.boot.actuate.health.HealthAggregator; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.OrderedHealthAggregator; -import org.springframework.boot.actuate.health.ReactiveHealthIndicator; +import org.springframework.boot.actuate.endpoint.*; +import org.springframework.boot.actuate.health.*; import org.springframework.boot.actuate.info.InfoContributor; import org.springframework.boot.actuate.trace.InMemoryTraceRepository; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; -import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.autoconfigure.condition.*; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; import org.springframework.boot.endpoint.Endpoint; @@ -68,11 +41,12 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.env.Environment; import org.springframework.util.ObjectUtils; import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping; +import liquibase.integration.spring.SpringLiquibase; + /** * {@link EnableAutoConfiguration Auto-configuration} for common management * {@link Endpoint}s. @@ -123,16 +97,12 @@ public LoggersEndpoint loggersEndpoint(LoggingSystem loggingSystem) { return new LoggersEndpoint(loggingSystem); } - @Bean - @ConditionalOnMissingBean - @ConditionalOnEnabledEndpoint - public MetricsEndpoint metricsEndpoint( - ObjectProvider> publicMetrics) { - List sortedPublicMetrics = publicMetrics - .getIfAvailable(Collections::emptyList); - Collections.sort(sortedPublicMetrics, AnnotationAwareOrderComparator.INSTANCE); - return new MetricsEndpoint(sortedPublicMetrics); - } + // FIXME replace with micrometer metrics endpoint +// @Bean +// @ConditionalOnMissingBean +// @ConditionalOnEnabledEndpoint +// public MetricsEndpoint metricsEndpoint() { +// } @Bean @ConditionalOnMissingBean diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ActuatorMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ActuatorMetricWriter.java deleted file mode 100644 index 052f5a01dcc8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ActuatorMetricWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.metrics; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.beans.factory.annotation.Qualifier; - -/** - * Qualifier annotation for a metric repository that is used by the actuator (to - * distinguish it from others that might be installed by the user). - * - * @author Dave Syer - * @since 2.0.0 - */ -@Qualifier -@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, - ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -@Documented -public @interface ActuatorMetricWriter { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricReader.java deleted file mode 100644 index 71138f0a0576..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricReader.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.metrics; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.beans.factory.annotation.Qualifier; - -/** - * Qualifier annotation for a metric reader that can be exported (to distinguish it from - * others that might be installed by the user for other purposes). - * - * @author Dave Syer - * @since 2.0.0 - */ -@Qualifier -@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, - ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -@Documented -public @interface ExportMetricReader { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricWriter.java deleted file mode 100644 index a5079b9c19c6..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ExportMetricWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.metrics; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.beans.factory.annotation.Qualifier; - -/** - * Qualifier annotation for a metric repository that is to be used to export metrics from - * the {@link ExportMetricReader} readers. - * - * @author Dave Syer - * @since 2.0.0 - */ -@Qualifier -@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, - ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -@Documented -public @interface ExportMetricWriter { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfiguration.java deleted file mode 100644 index 07e5fe8741af..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfiguration.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.metrics; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader; -import org.springframework.boot.actuate.metrics.export.Exporter; -import org.springframework.boot.actuate.metrics.export.MetricExportProperties; -import org.springframework.boot.actuate.metrics.export.MetricExporters; -import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; -import org.springframework.util.CollectionUtils; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for metrics export. - * - * @author Dave Syer - * @author Simon Buettner - * @since 2.0.0 - */ -@Configuration -@EnableScheduling -@ConditionalOnProperty(value = "spring.metrics.export.enabled", matchIfMissing = true) -@EnableConfigurationProperties -public class MetricExportAutoConfiguration { - - private final MetricsEndpointMetricReader endpointReader; - - private final List readers; - - private final Map writers; - - private final Map exporters; - - public MetricExportAutoConfiguration(MetricExportProperties properties, - ObjectProvider endpointReader, - @ExportMetricReader ObjectProvider> readers, - @ExportMetricWriter ObjectProvider> writers, - ObjectProvider> exporters) { - this.endpointReader = endpointReader.getIfAvailable(); - this.readers = readers.getIfAvailable(); - this.writers = writers.getIfAvailable(); - this.exporters = exporters.getIfAvailable(); - } - - @Bean - @ConditionalOnMissingBean(name = "metricWritersMetricExporter") - public SchedulingConfigurer metricWritersMetricExporter( - MetricExportProperties properties) { - Map writers = new HashMap<>(); - MetricReader reader = this.endpointReader; - if (reader == null && !CollectionUtils.isEmpty(this.readers)) { - reader = new CompositeMetricReader( - this.readers.toArray(new MetricReader[this.readers.size()])); - } - if (reader == null && CollectionUtils.isEmpty(this.exporters)) { - return new NoOpSchedulingConfigurer(); - } - MetricExporters exporters = new MetricExporters(properties); - if (reader != null) { - if (!CollectionUtils.isEmpty(this.writers)) { - writers.putAll(this.writers); - } - exporters.setReader(reader); - exporters.setWriters(writers); - } - exporters.setExporters(this.exporters == null - ? Collections.emptyMap() : this.exporters); - return exporters; - } - - @Configuration - static class StatsdConfiguration { - - @Bean - @ExportMetricWriter - @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = "spring.metrics.export.statsd", name = "host") - public StatsdMetricWriter statsdMetricWriter(MetricExportProperties properties) { - MetricExportProperties.Statsd statsdProperties = properties.getStatsd(); - return new StatsdMetricWriter(statsdProperties.getPrefix(), - statsdProperties.getHost(), statsdProperties.getPort()); - } - - } - - @Configuration - protected static class MetricExportPropertiesConfiguration { - - @Value("${spring.application.name:application}.${random.value:0000}") - private String prefix = ""; - - private String aggregateKeyPattern = "k.d"; - - @Bean(name = "spring.metrics.export-org.springframework.boot.actuate.metrics.export.MetricExportProperties") - @ConditionalOnMissingBean - public MetricExportProperties metricExportProperties() { - MetricExportProperties export = new MetricExportProperties(); - export.getRedis().setPrefix("spring.metrics" - + (this.prefix.length() > 0 ? "." : "") + this.prefix); - export.getAggregate().setPrefix(this.prefix); - export.getAggregate().setKeyPattern(this.aggregateKeyPattern); - return export; - } - - } - - private static class NoOpSchedulingConfigurer implements SchedulingConfigurer { - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfiguration.java deleted file mode 100644 index 236b70edd050..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfiguration.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.metrics; - -import javax.servlet.Servlet; -import javax.servlet.ServletRegistration; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilter; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.servlet.HandlerMapping; - -/** - * {@link EnableAutoConfiguration Auto-configuration} that records Servlet interactions - * with a {@link CounterService} and {@link GaugeService}. - * - * @author Dave Syer - * @author Phillip Webb - * @author Andy Wilkinson - * @author Sebastian Kirsch - * @since 2.0.0 - */ -@Configuration -@ConditionalOnBean({ CounterService.class, GaugeService.class }) -@ConditionalOnClass({ Servlet.class, ServletRegistration.class, - OncePerRequestFilter.class, HandlerMapping.class }) -@AutoConfigureAfter(MetricRepositoryAutoConfiguration.class) -@ConditionalOnProperty(prefix = "management.metrics.filter", name = "enabled", matchIfMissing = true) -@EnableConfigurationProperties({ MetricFilterProperties.class }) -public class MetricFilterAutoConfiguration { - - private final CounterService counterService; - - private final GaugeService gaugeService; - - private final MetricFilterProperties properties; - - public MetricFilterAutoConfiguration(CounterService counterService, - GaugeService gaugeService, MetricFilterProperties properties) { - this.counterService = counterService; - this.gaugeService = gaugeService; - this.properties = properties; - } - - @Bean - public MetricsFilter metricsFilter() { - return new MetricsFilter(this.counterService, this.gaugeService, - this.properties.getCounterSubmissions(), - this.properties.getGaugeSubmissions()); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterProperties.java deleted file mode 100644 index ad9244c75cd9..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterProperties.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.metrics; - -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilter; -import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilterSubmission; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Configuration properties for the {@link MetricsFilter}. - * - * @author Sebastian Kirsch - * @author Phillip Webb - * @since 2.0.0 - */ -@ConfigurationProperties(prefix = "management.metrics.filter") -public class MetricFilterProperties { - - /** - * Submissions that should be made to the gauge. - */ - private Set gaugeSubmissions; - - /** - * Submissions that should be made to the counter. - */ - private Set counterSubmissions; - - public MetricFilterProperties() { - this.gaugeSubmissions = new HashSet<>(EnumSet.of(MetricsFilterSubmission.MERGED)); - this.counterSubmissions = new HashSet<>( - EnumSet.of(MetricsFilterSubmission.MERGED)); - } - - public Set getGaugeSubmissions() { - return this.gaugeSubmissions; - } - - public void setGaugeSubmissions(Set gaugeSubmissions) { - this.gaugeSubmissions = gaugeSubmissions; - } - - public Set getCounterSubmissions() { - return this.counterSubmissions; - } - - public void setCounterSubmissions(Set counterSubmissions) { - this.counterSubmissions = counterSubmissions; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfiguration.java deleted file mode 100644 index c237ccf6ef10..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfiguration.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.metrics; - -import com.codahale.metrics.MetricRegistry; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.buffer.BufferCounterService; -import org.springframework.boot.actuate.metrics.buffer.BufferGaugeService; -import org.springframework.boot.actuate.metrics.buffer.BufferMetricReader; -import org.springframework.boot.actuate.metrics.buffer.CounterBuffers; -import org.springframework.boot.actuate.metrics.buffer.GaugeBuffers; -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.writer.MetricWriter; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.MessageChannel; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for metrics services. Creates - * user-facing {@link GaugeService} and {@link CounterService} instances, and also back - * end repositories to catch the data pumped into them. - *

- * In general, even if metric data needs to be stored and analysed remotely, it is - * recommended to use in-memory storage to buffer metric updates locally as is done by the - * default {@link CounterBuffers} and {@link GaugeBuffers}. The values can be exported - * (e.g. on a periodic basis) using an {@link Exporter}, most implementations of which - * have optimizations for sending data to remote repositories. - *

- * If Spring Messaging is on the classpath and a {@link MessageChannel} called - * "metricsChannel" is also available, all metric update events are published additionally - * as messages on that channel. Additional analysis or actions can be taken by clients - * subscribing to that channel. - *

- * In addition if Dropwizard's metrics library is on the classpath a - * {@link MetricRegistry} will be created and the default counter and gauge services will - * switch to using it instead of the default repository. Users can create "special" - * Dropwizard metrics by prefixing their metric names with the appropriate type (e.g. - * "histogram.*", "meter.*". "timer.*") and sending them to the {@code GaugeService} or - * {@code CounterService}. - *

- * By default all metric updates go to all {@link MetricWriter} instances in the - * application context via a {@link MetricCopyExporter} firing every 5 seconds (disable - * this by setting {@code spring.metrics.export.enabled=false}). - * - * @see GaugeService - * @see CounterService - * @see MetricWriter - * @see InMemoryMetricRepository - * @see Exporter - * @author Dave Syer - * @since 2.0.0 - */ -@Configuration -public class MetricRepositoryAutoConfiguration { - - @Configuration - @ConditionalOnMissingBean(GaugeService.class) - static class FastMetricServicesConfiguration { - - @Bean - @ConditionalOnMissingBean - public CounterBuffers counterBuffers() { - return new CounterBuffers(); - } - - @Bean - @ConditionalOnMissingBean - public GaugeBuffers gaugeBuffers() { - return new GaugeBuffers(); - } - - @Bean - @ExportMetricReader - @ConditionalOnMissingBean - public BufferMetricReader actuatorMetricReader(CounterBuffers counters, - GaugeBuffers gauges) { - return new BufferMetricReader(counters, gauges); - } - - @Bean - @ConditionalOnMissingBean(CounterService.class) - public BufferCounterService counterService(CounterBuffers writer) { - return new BufferCounterService(writer); - } - - @Bean - @ConditionalOnMissingBean(GaugeService.class) - public BufferGaugeService gaugeService(GaugeBuffers writer) { - return new BufferGaugeService(writer); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsChannelAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsChannelAutoConfiguration.java deleted file mode 100644 index f5415bc61c55..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsChannelAutoConfiguration.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.metrics; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.actuate.metrics.writer.MessageChannelMetricWriter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.MessageChannel; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for writing metrics to a - * {@link MessageChannel}. - * - * @author Dave Syer - * @since 2.0.0 - */ -@Configuration -@ConditionalOnClass(MessageChannel.class) -@ConditionalOnBean(name = "metricsChannel") -@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class) -public class MetricsChannelAutoConfiguration { - - @Bean - @ExportMetricWriter - @ConditionalOnMissingBean - public MessageChannelMetricWriter messageChannelMetricWriter( - @Qualifier("metricsChannel") MessageChannel channel) { - return new MessageChannelMetricWriter(channel); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfiguration.java deleted file mode 100644 index 48a9656e3c55..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfiguration.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.metrics; - -import com.codahale.metrics.MetricRegistry; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices; -import org.springframework.boot.actuate.metrics.dropwizard.ReservoirFactory; -import org.springframework.boot.actuate.metrics.reader.MetricRegistryMetricReader; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for Dropwizard-based metrics. - * - * @author Dave Syer - * @since 2.0.0 - */ -@Configuration -@ConditionalOnClass(MetricRegistry.class) -@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class) -public class MetricsDropwizardAutoConfiguration { - - private final ReservoirFactory reservoirFactory; - - public MetricsDropwizardAutoConfiguration( - ObjectProvider reservoirFactory) { - this.reservoirFactory = reservoirFactory.getIfAvailable(); - } - - @Bean - @ConditionalOnMissingBean - public MetricRegistry metricRegistry() { - return new MetricRegistry(); - } - - @Bean - @ConditionalOnMissingBean({ DropwizardMetricServices.class, CounterService.class, - GaugeService.class }) - public DropwizardMetricServices dropwizardMetricServices( - MetricRegistry metricRegistry) { - if (this.reservoirFactory == null) { - return new DropwizardMetricServices(metricRegistry); - } - else { - return new DropwizardMetricServices(metricRegistry, this.reservoirFactory); - } - } - - @Bean - public MetricReaderPublicMetrics dropwizardPublicMetrics( - MetricRegistry metricRegistry) { - MetricRegistryMetricReader reader = new MetricRegistryMetricReader( - metricRegistry); - return new MetricReaderPublicMetrics(reader); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfiguration.java deleted file mode 100644 index 7aefe9d18426..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfiguration.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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.metrics; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import javax.servlet.Servlet; -import javax.sql.DataSource; - -import org.apache.catalina.startup.Tomcat; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.actuate.autoconfigure.cache.CacheStatisticsAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; -import org.springframework.boot.actuate.cache.CacheStatisticsProvider; -import org.springframework.boot.actuate.endpoint.CachePublicMetrics; -import org.springframework.boot.actuate.endpoint.DataSourcePublicMetrics; -import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; -import org.springframework.boot.actuate.endpoint.PublicMetrics; -import org.springframework.boot.actuate.endpoint.RichGaugeReaderPublicMetrics; -import org.springframework.boot.actuate.endpoint.SystemPublicMetrics; -import org.springframework.boot.actuate.endpoint.TomcatPublicMetrics; -import org.springframework.boot.actuate.metrics.integration.SpringIntegrationMetricReader; -import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.rich.RichGaugeReader; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.condition.SearchStrategy; -import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; -import org.springframework.cache.CacheManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.integration.config.EnableIntegrationManagement; -import org.springframework.integration.support.management.IntegrationManagementConfigurer; - -/** - * {@link EnableAutoConfiguration Auto-configuration} for {@link PublicMetrics}. - * - * @author Stephane Nicoll - * @author Phillip Webb - * @author Johannes Edmeier - * @author Artem Bilan - * @since 2.0.0 - */ -@Configuration -@AutoConfigureBefore(EndpointAutoConfiguration.class) -@AutoConfigureAfter({ DataSourceAutoConfiguration.class, CacheAutoConfiguration.class, - MetricRepositoryAutoConfiguration.class, CacheStatisticsAutoConfiguration.class, - IntegrationAutoConfiguration.class }) -public class PublicMetricsAutoConfiguration { - - private final List metricReaders; - - public PublicMetricsAutoConfiguration( - @ExportMetricReader ObjectProvider> metricReaders) { - this.metricReaders = metricReaders.getIfAvailable(); - } - - @Bean - public SystemPublicMetrics systemPublicMetrics() { - return new SystemPublicMetrics(); - } - - @Bean - public MetricReaderPublicMetrics metricReaderPublicMetrics() { - return new MetricReaderPublicMetrics( - new CompositeMetricReader(this.metricReaders == null ? new MetricReader[0] - : this.metricReaders - .toArray(new MetricReader[this.metricReaders.size()]))); - } - - @Bean - @ConditionalOnBean(RichGaugeReader.class) - public RichGaugeReaderPublicMetrics richGaugePublicMetrics( - RichGaugeReader richGaugeReader) { - return new RichGaugeReaderPublicMetrics(richGaugeReader); - } - - @Configuration - @ConditionalOnClass(DataSource.class) - @ConditionalOnBean(DataSource.class) - static class DataSourceMetricsConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(DataSourcePoolMetadataProvider.class) - public DataSourcePublicMetrics dataSourcePublicMetrics() { - return new DataSourcePublicMetrics(); - } - - } - - @Configuration - @ConditionalOnClass({ Servlet.class, Tomcat.class }) - @ConditionalOnWebApplication - static class TomcatMetricsConfiguration { - - @Bean - @ConditionalOnMissingBean - public TomcatPublicMetrics tomcatPublicMetrics() { - return new TomcatPublicMetrics(); - } - - } - - @Configuration - @ConditionalOnClass(CacheManager.class) - @ConditionalOnBean(CacheManager.class) - static class CacheStatisticsConfiguration { - - @Bean - @ConditionalOnMissingBean - @ConditionalOnBean(CacheStatisticsProvider.class) - public CachePublicMetrics cachePublicMetrics( - Map cacheManagers, - Collection> statisticsProviders) { - return new CachePublicMetrics(cacheManagers, statisticsProviders); - } - - } - - @Configuration - @ConditionalOnClass(EnableIntegrationManagement.class) - static class IntegrationMetricsConfiguration { - - @Bean(name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME) - @ConditionalOnMissingBean(value = IntegrationManagementConfigurer.class, name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME, search = SearchStrategy.CURRENT) - public IntegrationManagementConfigurer managementConfigurer() { - IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer(); - configurer.setDefaultCountsEnabled(true); - configurer.setDefaultStatsEnabled(true); - return configurer; - } - - @Bean - @ConditionalOnMissingBean(name = "springIntegrationPublicMetrics") - public MetricReaderPublicMetrics springIntegrationPublicMetrics( - IntegrationManagementConfigurer managementConfigurer) { - return new MetricReaderPublicMetrics( - new SpringIntegrationMetricReader(managementConfigurer)); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/package-info.java deleted file mode 100644 index d6fe8ba5c84d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Auto-configuration for metrics. - */ -package org.springframework.boot.actuate.autoconfigure.metrics; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/AbstractJmxCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/AbstractJmxCacheStatisticsProvider.java deleted file mode 100644 index d922a8ef1121..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/AbstractJmxCacheStatisticsProvider.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.cache; - -import java.lang.management.ManagementFactory; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.management.AttributeNotFoundException; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanServer; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.ReflectionException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -/** - * Base {@link CacheStatisticsProvider} implementation that uses JMX to retrieve the cache - * statistics. - * - * @param The cache type - * @author Stephane Nicoll - * @since 1.3.0 - */ -public abstract class AbstractJmxCacheStatisticsProvider - implements CacheStatisticsProvider { - - private static final Logger logger = LoggerFactory - .getLogger(AbstractJmxCacheStatisticsProvider.class); - - private MBeanServer mBeanServer; - - private final Map caches = new ConcurrentHashMap<>(); - - @Override - public CacheStatistics getCacheStatistics(CacheManager cacheManager, C cache) { - try { - ObjectName objectName = internalGetObjectName(cache); - return (objectName == null ? null : getCacheStatistics(objectName)); - } - catch (MalformedObjectNameException ex) { - throw new IllegalStateException(ex); - } - } - - /** - * Return the {@link ObjectName} of the MBean that is managing the specified cache or - * {@code null} if none is found. - * @param cache the cache to handle - * @return the object name of the cache statistics MBean - * @throws MalformedObjectNameException if the {@link ObjectName} for that cache is - * invalid - */ - protected abstract ObjectName getObjectName(C cache) - throws MalformedObjectNameException; - - /** - * Return the current {@link CacheStatistics} snapshot from the MBean identified by - * the specified {@link ObjectName}. - * @param objectName the object name of the cache statistics MBean - * @return the current cache statistics - */ - protected abstract CacheStatistics getCacheStatistics(ObjectName objectName); - - private ObjectName internalGetObjectName(C cache) - throws MalformedObjectNameException { - String cacheName = cache.getName(); - ObjectNameWrapper value = this.caches.get(cacheName); - if (value != null) { - return value.objectName; - } - ObjectName objectName = getObjectName(cache); - this.caches.put(cacheName, new ObjectNameWrapper(objectName)); - return objectName; - } - - protected MBeanServer getMBeanServer() { - if (this.mBeanServer == null) { - this.mBeanServer = ManagementFactory.getPlatformMBeanServer(); - } - return this.mBeanServer; - } - - protected T getAttribute(ObjectName objectName, String attributeName, - Class type) { - try { - Object attribute = getMBeanServer().getAttribute(objectName, attributeName); - return type.cast(attribute); - } - catch (MBeanException | ReflectionException ex) { - throw new IllegalStateException(ex); - } - catch (AttributeNotFoundException ex) { - throw new IllegalStateException("Unexpected: MBean with name '" + objectName - + "' " + "does not expose attribute with name " + attributeName, ex); - } - catch (InstanceNotFoundException ex) { - logger.warn("Cache statistics are no longer available", ex); - return null; - } - } - - private static class ObjectNameWrapper { - - private final ObjectName objectName; - - ObjectNameWrapper(ObjectName objectName) { - this.objectName = objectName; - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatistics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatistics.java deleted file mode 100644 index f6cc96e1f988..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatistics.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.cache; - -import java.util.Collection; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Snapshot of the statistics of a given cache. {@code CacheStatistics} instances have a - * very short life as it represents the statistics of a cache at one particular point in - * time. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public interface CacheStatistics { - - /** - * Generate the relevant {@link Metric} instances based on the specified prefix. - * @param prefix the metrics prefix (ends with '.') - * @return the metrics corresponding to this instance - */ - Collection> toMetrics(String prefix); - - /** - * Return the size of the cache or {@code null} if that information is not available. - * @return the size of the cache or {@code null} - */ - Long getSize(); - - /** - * Return the ratio of cache requests which were hits as a value between 0 and 1 where - * 0 means that the hit ratio is 0% and 1 means it is 100%. - *

- * This may also return {@code null} if the cache-specifics statistics does not - * provide the necessary information - * @return the hit ratio or {@code null} - */ - Double getHitRatio(); - - /** - * Return the ratio of cache requests which were misses as value between 0 and 1 where - * 0 means that the miss ratio is 0% and 1 means it is 100%. - *

- * This may also return {@code null} if the cache-specifics statistics does not - * provide the necessary information - * @return the miss ratio or {@code null} - */ - Double getMissRatio(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatisticsProvider.java deleted file mode 100644 index 2aebddea6c92..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CacheStatisticsProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.cache; - -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -/** - * Provide a {@link CacheStatistics} based on a {@link Cache}. - * - * @param The {@link Cache} type - * @author Stephane Nicoll - * @author Phillip Webb - * @since 1.3.0 - */ -@FunctionalInterface -public interface CacheStatisticsProvider { - - /** - * Return the current {@link CacheStatistics} snapshot for the specified {@link Cache} - * or {@code null} if the given cache could not be handled. - * @param cacheManager the {@link CacheManager} handling this cache - * @param cache the cache to handle - * @return the current cache statistics or {@code null} - */ - CacheStatistics getCacheStatistics(CacheManager cacheManager, C cache); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CaffeineCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CaffeineCacheStatisticsProvider.java deleted file mode 100644 index dc6e77ffe8e3..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/CaffeineCacheStatisticsProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012-2016 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.cache; - -import com.github.benmanes.caffeine.cache.stats.CacheStats; - -import org.springframework.cache.CacheManager; -import org.springframework.cache.caffeine.CaffeineCache; - -/** - * {@link CacheStatisticsProvider} implementation for Caffeine. - * - * @author EddĂș MelĂ©ndez - * @since 1.4.0 - */ -public class CaffeineCacheStatisticsProvider - implements CacheStatisticsProvider { - - @Override - public CacheStatistics getCacheStatistics(CacheManager cacheManager, - CaffeineCache cache) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - statistics.setSize(cache.getNativeCache().estimatedSize()); - CacheStats caffeineStatistics = cache.getNativeCache().stats(); - if (caffeineStatistics.requestCount() > 0) { - statistics.setHitRatio(caffeineStatistics.hitRate()); - statistics.setMissRatio(caffeineStatistics.missRate()); - } - return statistics; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/ConcurrentMapCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/ConcurrentMapCacheStatisticsProvider.java deleted file mode 100644 index 7adee9999fa5..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/ConcurrentMapCacheStatisticsProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.cache; - -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCache; - -/** - * {@link CacheStatisticsProvider} implementation for {@link ConcurrentMapCache}. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class ConcurrentMapCacheStatisticsProvider - implements CacheStatisticsProvider { - - @Override - public CacheStatistics getCacheStatistics(CacheManager cacheManager, - ConcurrentMapCache cache) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - statistics.setSize((long) cache.getNativeCache().size()); - return statistics; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/DefaultCacheStatistics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/DefaultCacheStatistics.java deleted file mode 100644 index 091ab34ccb55..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/DefaultCacheStatistics.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.cache; - -import java.util.ArrayList; -import java.util.Collection; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * A default {@link CacheStatistics} implementation. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class DefaultCacheStatistics implements CacheStatistics { - - private Long size; - - private Double hitRatio; - - private Double missRatio; - - @Override - public Collection> toMetrics(String prefix) { - Collection> result = new ArrayList<>(); - addMetric(result, prefix + "size", getSize()); - addMetric(result, prefix + "hit.ratio", getHitRatio()); - addMetric(result, prefix + "miss.ratio", getMissRatio()); - return result; - } - - public void setGetCacheCounts(long hitCount, long missCount) { - long total = hitCount + missCount; - if (total > 0) { - double hitRatio = hitCount / (double) total; - setHitRatio(hitRatio); - setMissRatio(1 - hitRatio); - } - } - - @Override - public Long getSize() { - return this.size; - } - - public void setSize(Long size) { - this.size = size; - } - - @Override - public Double getHitRatio() { - return this.hitRatio; - } - - public void setHitRatio(Double hitRatio) { - this.hitRatio = hitRatio; - } - - @Override - public Double getMissRatio() { - return this.missRatio; - } - - public void setMissRatio(Double missRatio) { - this.missRatio = missRatio; - } - - private void addMetric(Collection> metrics, String name, - T value) { - if (value != null) { - metrics.add(new Metric<>(name, value)); - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/EhCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/EhCacheStatisticsProvider.java deleted file mode 100644 index 98eae49faed1..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/EhCacheStatisticsProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2016 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.cache; - -import net.sf.ehcache.statistics.StatisticsGateway; - -import org.springframework.cache.CacheManager; -import org.springframework.cache.ehcache.EhCacheCache; - -/** - * {@link CacheStatisticsProvider} implementation for EhCache. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class EhCacheStatisticsProvider implements CacheStatisticsProvider { - - @Override - public CacheStatistics getCacheStatistics(CacheManager cacheManager, - EhCacheCache cache) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - StatisticsGateway ehCacheStatistics = cache.getNativeCache().getStatistics(); - statistics.setSize(ehCacheStatistics.getSize()); - double hitRatio = cacheHitRatio(ehCacheStatistics); - if (!Double.isNaN(hitRatio)) { - // ratio is calculated 'racily' and can drift marginally above unity, - // so we cap it here - double sanitizedHitRatio = (hitRatio > 1 ? 1 : hitRatio); - statistics.setHitRatio(sanitizedHitRatio); - statistics.setMissRatio(1 - sanitizedHitRatio); - } - return statistics; - } - - private double cacheHitRatio(StatisticsGateway stats) { - long hitCount = stats.cacheHitCount(); - long missCount = stats.cacheMissCount(); - return ((double) hitCount) / (hitCount + missCount); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/HazelcastCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/HazelcastCacheStatisticsProvider.java deleted file mode 100644 index d445f9d6bdf9..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/HazelcastCacheStatisticsProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.cache; - -import com.hazelcast.core.IMap; -import com.hazelcast.monitor.LocalMapStats; -import com.hazelcast.spring.cache.HazelcastCache; - -import org.springframework.cache.CacheManager; - -/** - * {@link CacheStatisticsProvider} implementation for Hazelcast. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class HazelcastCacheStatisticsProvider - implements CacheStatisticsProvider { - - @Override - public CacheStatistics getCacheStatistics(CacheManager cacheManager, - HazelcastCache cache) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - LocalMapStats mapStatistics = ((IMap) cache.getNativeCache()) - .getLocalMapStats(); - statistics.setSize(mapStatistics.getOwnedEntryCount()); - statistics.setGetCacheCounts(mapStatistics.getHits(), - mapStatistics.getGetOperationCount() - mapStatistics.getHits()); - return statistics; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/InfinispanCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/InfinispanCacheStatisticsProvider.java deleted file mode 100644 index 2a424ae2b522..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/InfinispanCacheStatisticsProvider.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.cache; - -import java.util.Set; - -import javax.management.MalformedObjectNameException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -import org.infinispan.spring.provider.SpringCache; - -/** - * {@link CacheStatisticsProvider} implementation for Infinispan. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class InfinispanCacheStatisticsProvider - extends AbstractJmxCacheStatisticsProvider { - - @Override - protected ObjectName getObjectName(SpringCache cache) - throws MalformedObjectNameException { - ObjectName name = new ObjectName( - "org.infinispan:component=Statistics,type=Cache,name=\"" + cache.getName() - + "(local)\",*"); - Set instances = getMBeanServer().queryMBeans(name, null); - if (instances.size() == 1) { - return instances.iterator().next().getObjectName(); - } - // None or more than one - return null; - } - - @Override - protected CacheStatistics getCacheStatistics(ObjectName objectName) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - Integer size = getAttribute(objectName, "numberOfEntries", Integer.class); - if (size != null) { - statistics.setSize((long) size); - if (size > 0) { - // Let's initialize the stats if we have some data - initializeStats(objectName, statistics); - } - } - return statistics; - } - - private void initializeStats(ObjectName objectName, - DefaultCacheStatistics statistics) { - Double hitRatio = getAttribute(objectName, "hitRatio", Double.class); - if ((hitRatio != null)) { - statistics.setHitRatio(hitRatio); - statistics.setMissRatio(1 - hitRatio); - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/JCacheCacheStatisticsProvider.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/JCacheCacheStatisticsProvider.java deleted file mode 100644 index 02cc62ae1738..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/JCacheCacheStatisticsProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.cache; - -import java.util.Set; - -import javax.management.MalformedObjectNameException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -import org.springframework.cache.jcache.JCacheCache; - -/** - * {@link CacheStatisticsProvider} implementation for a JSR-107 compliant cache. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class JCacheCacheStatisticsProvider - extends AbstractJmxCacheStatisticsProvider { - - @Override - protected ObjectName getObjectName(JCacheCache cache) - throws MalformedObjectNameException { - ObjectName name = new ObjectName( - "javax.cache:type=CacheStatistics,Cache=" + cache.getName() + ",*"); - Set instances = getMBeanServer().queryMBeans(name, null); - if (instances.size() == 1) { - return instances.iterator().next().getObjectName(); - } - // None or more than one - return null; - } - - @Override - protected CacheStatistics getCacheStatistics(ObjectName objectName) { - DefaultCacheStatistics statistics = new DefaultCacheStatistics(); - Float hitPercentage = getAttribute(objectName, "CacheHitPercentage", Float.class); - Float missPercentage = getAttribute(objectName, "CacheMissPercentage", - Float.class); - if ((hitPercentage != null && missPercentage != null) - && (hitPercentage > 0 || missPercentage > 0)) { - statistics.setHitRatio(hitPercentage / (double) 100); - statistics.setMissRatio(missPercentage / (double) 100); - } - return statistics; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/package-info.java deleted file mode 100644 index 3fb8898be2cb..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cache/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Classes for cache statistics. - */ -package org.springframework.boot.actuate.cache; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/CachePublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/CachePublicMetrics.java deleted file mode 100644 index 94193f2c31c5..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/CachePublicMetrics.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import org.springframework.boot.actuate.cache.CacheStatistics; -import org.springframework.boot.actuate.cache.CacheStatisticsProvider; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.cache.transaction.TransactionAwareCacheDecorator; -import org.springframework.core.ResolvableType; -import org.springframework.util.ClassUtils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * A {@link PublicMetrics} implementation that provides cache statistics. - * - * @author Stephane Nicoll - * @since 1.3.0 - */ -public class CachePublicMetrics implements PublicMetrics { - - private final Map cacheManagers; - - private final Collection> statisticsProviders; - - /** - * Create a new {@link CachePublicMetrics} instance. - * @param cacheManagers the cache managers - * @param statisticsProviders the statistics providers - */ - public CachePublicMetrics(Map cacheManagers, - Collection> statisticsProviders) { - this.cacheManagers = cacheManagers; - this.statisticsProviders = statisticsProviders; - } - - @Override - public Collection> metrics() { - Collection> metrics = new HashSet<>(); - for (Map.Entry> entry : getCacheManagerBeans() - .entrySet()) { - addMetrics(metrics, entry.getKey(), entry.getValue()); - } - return metrics; - } - - private MultiValueMap getCacheManagerBeans() { - MultiValueMap cacheManagerNamesByCacheName = new LinkedMultiValueMap<>(); - for (Map.Entry entry : this.cacheManagers.entrySet()) { - for (String cacheName : entry.getValue().getCacheNames()) { - cacheManagerNamesByCacheName.add(cacheName, - new CacheManagerBean(entry.getKey(), entry.getValue())); - } - } - return cacheManagerNamesByCacheName; - } - - private void addMetrics(Collection> metrics, String cacheName, - List cacheManagerBeans) { - for (CacheManagerBean cacheManagerBean : cacheManagerBeans) { - CacheManager cacheManager = cacheManagerBean.getCacheManager(); - Cache cache = unwrapIfNecessary(cacheManager.getCache(cacheName)); - CacheStatistics statistics = getCacheStatistics(cache, cacheManager); - if (statistics != null) { - String prefix = cacheName; - if (cacheManagerBeans.size() > 1) { - prefix = cacheManagerBean.getBeanName() + "_" + prefix; - } - prefix = "cache." + prefix + (prefix.endsWith(".") ? "" : "."); - metrics.addAll(statistics.toMetrics(prefix)); - } - } - } - - private Cache unwrapIfNecessary(Cache cache) { - if (ClassUtils.isPresent( - "org.springframework.cache.transaction.TransactionAwareCacheDecorator", - getClass().getClassLoader())) { - return TransactionAwareCacheDecoratorHandler.unwrapIfNecessary(cache); - } - return cache; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private CacheStatistics getCacheStatistics(Cache cache, CacheManager cacheManager) { - if (this.statisticsProviders != null) { - for (CacheStatisticsProvider provider : this.statisticsProviders) { - Class cacheType = ResolvableType - .forClass(CacheStatisticsProvider.class, provider.getClass()) - .resolveGeneric(); - if (cacheType.isInstance(cache)) { - CacheStatistics statistics = provider.getCacheStatistics(cacheManager, - cache); - if (statistics != null) { - return statistics; - } - } - } - } - return null; - } - - private static class CacheManagerBean { - - private final String beanName; - - private final CacheManager cacheManager; - - CacheManagerBean(String beanName, CacheManager cacheManager) { - this.beanName = beanName; - this.cacheManager = cacheManager; - } - - public String getBeanName() { - return this.beanName; - } - - public CacheManager getCacheManager() { - return this.cacheManager; - } - - } - - private static class TransactionAwareCacheDecoratorHandler { - - private static Cache unwrapIfNecessary(Cache cache) { - try { - if (cache instanceof TransactionAwareCacheDecorator) { - return ((TransactionAwareCacheDecorator) cache).getTargetCache(); - } - } - catch (NoClassDefFoundError ex) { - // Ignore - } - return cache; - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DataSourcePublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DataSourcePublicMetrics.java deleted file mode 100644 index 29b03e968631..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DataSourcePublicMetrics.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import javax.annotation.PostConstruct; -import javax.sql.DataSource; - -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadata; -import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; -import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProviders; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Primary; - -/** - * A {@link PublicMetrics} implementation that provides data source usage statistics. - * - * @author Stephane Nicoll - * @since 1.2.0 - */ -public class DataSourcePublicMetrics implements PublicMetrics { - - private static final String DATASOURCE_SUFFIX = "dataSource"; - - @Autowired - private ApplicationContext applicationContext; - - @Autowired - private Collection providers; - - private final Map metadataByPrefix = new HashMap<>(); - - @PostConstruct - public void initialize() { - DataSource primaryDataSource = getPrimaryDataSource(); - DataSourcePoolMetadataProvider provider = new DataSourcePoolMetadataProviders( - this.providers); - for (Map.Entry entry : this.applicationContext - .getBeansOfType(DataSource.class).entrySet()) { - String beanName = entry.getKey(); - DataSource bean = entry.getValue(); - String prefix = createPrefix(beanName, bean, bean.equals(primaryDataSource)); - DataSourcePoolMetadata poolMetadata = provider - .getDataSourcePoolMetadata(bean); - if (poolMetadata != null) { - this.metadataByPrefix.put(prefix, poolMetadata); - } - } - } - - @Override - public Collection> metrics() { - Set> metrics = new LinkedHashSet<>(); - for (Map.Entry entry : this.metadataByPrefix - .entrySet()) { - String prefix = entry.getKey(); - prefix = (prefix.endsWith(".") ? prefix : prefix + "."); - DataSourcePoolMetadata metadata = entry.getValue(); - addMetric(metrics, prefix + "active", metadata.getActive()); - addMetric(metrics, prefix + "usage", metadata.getUsage()); - } - return metrics; - } - - private void addMetric(Set> metrics, String name, - T value) { - if (value != null) { - metrics.add(new Metric<>(name, value)); - } - } - - /** - * Create the prefix to use for the metrics to associate with the given - * {@link DataSource}. - * @param name the name of the data source bean - * @param dataSource the data source to configure - * @param primary if this data source is the primary data source - * @return a prefix for the given data source - */ - protected String createPrefix(String name, DataSource dataSource, boolean primary) { - if (primary) { - return "datasource.primary"; - } - if (name.length() > DATASOURCE_SUFFIX.length() - && name.toLowerCase().endsWith(DATASOURCE_SUFFIX.toLowerCase())) { - name = name.substring(0, name.length() - DATASOURCE_SUFFIX.length()); - } - return "datasource." + name; - } - - /** - * Attempt to locate the primary {@link DataSource} (i.e. either the only data source - * available or the one amongst the candidates marked as {@link Primary}). Return - * {@code null} if there no primary data source could be found. - * @return the primary datasource - */ - private DataSource getPrimaryDataSource() { - try { - return this.applicationContext.getBean(DataSource.class); - } - catch (NoSuchBeanDefinitionException ex) { - return null; - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetrics.java deleted file mode 100644 index b68784d1c8ca..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetrics.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.util.Assert; - -/** - * {@link PublicMetrics} exposed from a {@link MetricReader}. - * - * @author Dave Syer - * @author Christian Dupuis - * @author Stephane Nicoll - * @author Phillip Webb - */ -public class MetricReaderPublicMetrics implements PublicMetrics { - - private final MetricReader metricReader; - - public MetricReaderPublicMetrics(MetricReader metricReader) { - Assert.notNull(metricReader, "MetricReader must not be null"); - this.metricReader = metricReader; - } - - @Override - public Collection> metrics() { - List> result = new ArrayList<>(); - for (Metric metric : this.metricReader.findAll()) { - result.add(metric); - } - return result; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java deleted file mode 100644 index 06316797153e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.endpoint.Endpoint; -import org.springframework.boot.endpoint.ReadOperation; -import org.springframework.boot.endpoint.Selector; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * {@link Endpoint} to expose a collection of {@link PublicMetrics}. - * - * @author Dave Syer - */ -@Endpoint(id = "metrics") -public class MetricsEndpoint { - - private final List publicMetrics; - - /** - * Create a new {@link MetricsEndpoint} instance. - * @param publicMetrics the metrics to expose - */ - public MetricsEndpoint(PublicMetrics publicMetrics) { - this(Collections.singleton(publicMetrics)); - } - - /** - * Create a new {@link MetricsEndpoint} instance. - * @param publicMetrics the metrics to expose. The collection will be sorted using the - * {@link AnnotationAwareOrderComparator}. - */ - public MetricsEndpoint(Collection publicMetrics) { - Assert.notNull(publicMetrics, "PublicMetrics must not be null"); - this.publicMetrics = new ArrayList<>(publicMetrics); - AnnotationAwareOrderComparator.sort(this.publicMetrics); - } - - public void registerPublicMetrics(PublicMetrics metrics) { - this.publicMetrics.add(metrics); - AnnotationAwareOrderComparator.sort(this.publicMetrics); - } - - public void unregisterPublicMetrics(PublicMetrics metrics) { - this.publicMetrics.remove(metrics); - } - - @ReadOperation - public Map metrics(String pattern) { - return metrics(StringUtils.hasText(pattern) - ? Pattern.compile(pattern).asPredicate() : (name) -> true); - } - - @ReadOperation - public Map metricNamed(@Selector String requiredName) { - Map metrics = metrics((name) -> name.equals(requiredName)); - if (metrics.isEmpty()) { - return null; - } - return metrics; - } - - private Map metrics(Predicate namePredicate) { - Map result = new LinkedHashMap<>(); - List metrics = new ArrayList<>(this.publicMetrics); - for (PublicMetrics publicMetric : metrics) { - try { - for (Metric metric : publicMetric.metrics()) { - if (namePredicate.test(metric.getName()) - && metric.getValue() != null) { - result.put(metric.getName(), metric.getValue()); - } - } - } - catch (Exception ex) { - // Could not evaluate metrics - } - } - return result; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpointMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpointMetricReader.java deleted file mode 100644 index 381956290fcb..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/MetricsEndpointMetricReader.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; - -/** - * {@link MetricReader} that pulls all current values out of the {@link MetricsEndpoint}. - * No timestamp information is available, so there is no way to check if the values are - * recent, and they all come out with the default (current time). - * - * @author Dave Syer - * @since 1.3.0 - */ -public class MetricsEndpointMetricReader implements MetricReader { - - private final MetricsEndpoint endpoint; - - public MetricsEndpointMetricReader(MetricsEndpoint endpoint) { - this.endpoint = endpoint; - } - - @Override - public Metric findOne(String metricName) { - Metric metric = null; - Object value = this.endpoint.metrics(null).get(metricName); - if (value != null) { - metric = new Metric<>(metricName, (Number) value); - } - return metric; - } - - @Override - public Iterable> findAll() { - List> metrics = new ArrayList<>(); - Map values = this.endpoint.metrics(null); - Date timestamp = new Date(); - for (Entry entry : values.entrySet()) { - String name = entry.getKey(); - Object value = entry.getValue(); - metrics.add(new Metric<>(name, (Number) value, timestamp)); - } - return metrics; - } - - @Override - public long count() { - return this.endpoint.metrics(null).size(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/PublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/PublicMetrics.java deleted file mode 100644 index dca14978c36d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/PublicMetrics.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Collection; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Interface to expose specific {@link Metric}s via a {@link MetricsEndpoint}. - * Implementations should take care that the metrics they provide have unique names in the - * application context, but they shouldn't have to care about global uniqueness in the JVM - * or across a distributed system. - * - * @author Dave Syer - * @see SystemPublicMetrics SystemPublicMetrics for an example implementation - */ -@FunctionalInterface -public interface PublicMetrics { - - /** - * Return an indication of current state through metrics. - * @return the public metrics - */ - Collection> metrics(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetrics.java deleted file mode 100644 index 970cec57d077..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetrics.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.rich.RichGauge; -import org.springframework.boot.actuate.metrics.rich.RichGaugeReader; -import org.springframework.util.Assert; - -/** - * {@link PublicMetrics} exposed from a {@link RichGaugeReader}. - * - * @author Johannes Edmeier - * @since 1.2 - */ -public class RichGaugeReaderPublicMetrics implements PublicMetrics { - - private final RichGaugeReader richGaugeReader; - - public RichGaugeReaderPublicMetrics(RichGaugeReader richGaugeReader) { - Assert.notNull(richGaugeReader, "RichGaugeReader must not be null"); - this.richGaugeReader = richGaugeReader; - } - - @Override - public Collection> metrics() { - List> result = new ArrayList<>(); - for (RichGauge richGauge : this.richGaugeReader.findAll()) { - result.addAll(convert(richGauge)); - } - return result; - } - - private List> convert(RichGauge gauge) { - List> result = new ArrayList<>(6); - result.add(new Metric<>(gauge.getName() + RichGauge.AVG, gauge.getAverage())); - result.add(new Metric<>(gauge.getName() + RichGauge.VAL, gauge.getValue())); - result.add(new Metric<>(gauge.getName() + RichGauge.MIN, gauge.getMin())); - result.add(new Metric<>(gauge.getName() + RichGauge.MAX, gauge.getMax())); - result.add(new Metric<>(gauge.getName() + RichGauge.ALPHA, gauge.getAlpha())); - result.add(new Metric<>(gauge.getName() + RichGauge.COUNT, gauge.getCount())); - return result; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SystemPublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SystemPublicMetrics.java deleted file mode 100644 index 6a0a97ecb40b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SystemPublicMetrics.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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.endpoint; - -import java.lang.management.ClassLoadingMXBean; -import java.lang.management.GarbageCollectorMXBean; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryUsage; -import java.lang.management.ThreadMXBean; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.core.Ordered; -import org.springframework.util.StringUtils; - -/** - * A {@link PublicMetrics} implementation that provides various system-related metrics. - * - * @author Dave Syer - * @author Christian Dupuis - * @author Stephane Nicoll - * @author Johannes Edmeier - * @since 1.2.0 - */ -public class SystemPublicMetrics implements PublicMetrics, Ordered { - - private long timestamp; - - public SystemPublicMetrics() { - this.timestamp = System.currentTimeMillis(); - } - - @Override - public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 10; - } - - @Override - public Collection> metrics() { - Collection> result = new LinkedHashSet<>(); - addBasicMetrics(result); - addManagementMetrics(result); - return result; - } - - /** - * Add basic system metrics. - * @param result the result - */ - protected void addBasicMetrics(Collection> result) { - // NOTE: ManagementFactory must not be used here since it fails on GAE - Runtime runtime = Runtime.getRuntime(); - result.add(newMemoryMetric("mem", - runtime.totalMemory() + getTotalNonHeapMemoryIfPossible())); - result.add(newMemoryMetric("mem.free", runtime.freeMemory())); - result.add(new Metric<>("processors", runtime.availableProcessors())); - result.add(new Metric<>("instance.uptime", - System.currentTimeMillis() - this.timestamp)); - } - - private long getTotalNonHeapMemoryIfPossible() { - try { - return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed(); - } - catch (Throwable ex) { - return 0; - } - } - - /** - * Add metrics from ManagementFactory if possible. Note that ManagementFactory is not - * available on Google App Engine. - * @param result the result - */ - private void addManagementMetrics(Collection> result) { - try { - // Add JVM up time in ms - result.add(new Metric<>("uptime", - ManagementFactory.getRuntimeMXBean().getUptime())); - result.add(new Metric<>("systemload.average", - ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage())); - addHeapMetrics(result); - addNonHeapMetrics(result); - addThreadMetrics(result); - addClassLoadingMetrics(result); - addGarbageCollectionMetrics(result); - } - catch (NoClassDefFoundError ex) { - // Expected on Google App Engine - } - } - - /** - * Add JVM heap metrics. - * @param result the result - */ - protected void addHeapMetrics(Collection> result) { - MemoryUsage memoryUsage = ManagementFactory.getMemoryMXBean() - .getHeapMemoryUsage(); - result.add(newMemoryMetric("heap.committed", memoryUsage.getCommitted())); - result.add(newMemoryMetric("heap.init", memoryUsage.getInit())); - result.add(newMemoryMetric("heap.used", memoryUsage.getUsed())); - result.add(newMemoryMetric("heap", memoryUsage.getMax())); - } - - /** - * Add JVM non-heap metrics. - * @param result the result - */ - private void addNonHeapMetrics(Collection> result) { - MemoryUsage memoryUsage = ManagementFactory.getMemoryMXBean() - .getNonHeapMemoryUsage(); - result.add(newMemoryMetric("nonheap.committed", memoryUsage.getCommitted())); - result.add(newMemoryMetric("nonheap.init", memoryUsage.getInit())); - result.add(newMemoryMetric("nonheap.used", memoryUsage.getUsed())); - result.add(newMemoryMetric("nonheap", memoryUsage.getMax())); - } - - private Metric newMemoryMetric(String name, long bytes) { - return new Metric<>(name, bytes / 1024); - } - - /** - * Add thread metrics. - * @param result the result - */ - protected void addThreadMetrics(Collection> result) { - ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean(); - result.add( - new Metric<>("threads.peak", (long) threadMxBean.getPeakThreadCount())); - result.add(new Metric<>("threads.daemon", - (long) threadMxBean.getDaemonThreadCount())); - result.add(new Metric<>("threads.totalStarted", - threadMxBean.getTotalStartedThreadCount())); - result.add(new Metric<>("threads", (long) threadMxBean.getThreadCount())); - } - - /** - * Add class loading metrics. - * @param result the result - */ - protected void addClassLoadingMetrics(Collection> result) { - ClassLoadingMXBean classLoadingMxBean = ManagementFactory.getClassLoadingMXBean(); - result.add( - new Metric<>("classes", (long) classLoadingMxBean.getLoadedClassCount())); - result.add(new Metric<>("classes.loaded", - classLoadingMxBean.getTotalLoadedClassCount())); - result.add(new Metric<>("classes.unloaded", - classLoadingMxBean.getUnloadedClassCount())); - } - - /** - * Add garbage collection metrics. - * @param result the result - */ - protected void addGarbageCollectionMetrics(Collection> result) { - List garbageCollectorMxBeans = ManagementFactory - .getGarbageCollectorMXBeans(); - for (GarbageCollectorMXBean garbageCollectorMXBean : garbageCollectorMxBeans) { - String name = beautifyGcName(garbageCollectorMXBean.getName()); - result.add(new Metric<>("gc." + name + ".count", - garbageCollectorMXBean.getCollectionCount())); - result.add(new Metric<>("gc." + name + ".time", - garbageCollectorMXBean.getCollectionTime())); - } - } - - /** - * Turn GC names like 'PS Scavenge' or 'PS MarkSweep' into something that is more - * metrics friendly. - * @param name the source name - * @return a metric friendly name - */ - private String beautifyGcName(String name) { - return StringUtils.replace(name, " ", "_").toLowerCase(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetrics.java deleted file mode 100644 index a27af6ef6d96..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetrics.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.apache.catalina.Container; -import org.apache.catalina.Context; -import org.apache.catalina.Manager; -import org.apache.catalina.session.ManagerBase; - -import org.springframework.beans.BeansException; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.server.WebServer; -import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * A {@link PublicMetrics} implementation that provides Tomcat statistics. - * - * @author Johannes Edmeier - * @author Phillip Webb - * @since 1.2.0 - */ -public class TomcatPublicMetrics implements PublicMetrics, ApplicationContextAware { - - private ApplicationContext applicationContext; - - @Override - public Collection> metrics() { - if (this.applicationContext instanceof ServletWebServerApplicationContext) { - Manager manager = getManager( - (ServletWebServerApplicationContext) this.applicationContext); - if (manager != null) { - return metrics(manager); - } - } - return Collections.emptySet(); - } - - private Manager getManager(ServletWebServerApplicationContext applicationContext) { - WebServer webServer = applicationContext.getWebServer(); - if (webServer instanceof TomcatWebServer) { - return getManager((TomcatWebServer) webServer); - } - return null; - } - - private Manager getManager(TomcatWebServer webServer) { - for (Container container : webServer.getTomcat().getHost().findChildren()) { - if (container instanceof Context) { - return ((Context) container).getManager(); - } - } - return null; - } - - private Collection> metrics(Manager manager) { - List> metrics = new ArrayList<>(2); - if (manager instanceof ManagerBase) { - addMetric(metrics, "httpsessions.max", - ((ManagerBase) manager).getMaxActiveSessions()); - } - addMetric(metrics, "httpsessions.active", manager.getActiveSessions()); - return metrics; - } - - private void addMetric(List> metrics, String name, Integer value) { - metrics.add(new Metric<>(name, value)); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/CounterService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/CounterService.java deleted file mode 100644 index aae0921f912c..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/CounterService.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2012-2013 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.metrics; - -/** - * A service that can be used to increment, decrement and reset a named counter value. - * - * @author Dave Syer - */ -public interface CounterService { - - /** - * Increment the specified counter by 1. - * @param metricName the name of the counter - */ - void increment(String metricName); - - /** - * Decrement the specified counter by 1. - * @param metricName the name of the counter - */ - void decrement(String metricName); - - /** - * Reset the specified counter. - * @param metricName the name of the counter - */ - void reset(String metricName); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/GaugeService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/GaugeService.java deleted file mode 100644 index eaa00fb48d3c..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/GaugeService.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.metrics; - -/** - * A service that can be used to submit a named double value for storage and analysis. Any - * statistics or analysis that needs to be carried out is best left for other concerns, - * but ultimately they are under control of the implementation of this service. For - * instance, the value submitted here could be a method execution timing result, and it - * would go to a backend that keeps a histogram of recent values for comparison purposes. - * Or it could be a simple measurement of a sensor value (like a temperature reading) to - * be passed on to a monitoring system in its raw form. - * - * @author Dave Syer - */ -@FunctionalInterface -public interface GaugeService { - - /** - * Set the specified gauge value. - * @param metricName the name of the gauge to set - * @param value the value of the gauge - */ - void submit(String metricName, double value); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/Metric.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/Metric.java deleted file mode 100644 index 19d61ac1784d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/Metric.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.metrics; - -import java.util.Date; - -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; - -/** - * Immutable class that can be used to hold any arbitrary system measurement value (a - * named numeric value with a timestamp). For example a metric might record the number of - * active connections to a server, or the temperature of a meeting room. - * - * @param the value type - * @author Dave Syer - */ -public class Metric { - - private final String name; - - private final T value; - - private final Date timestamp; - - /** - * Create a new {@link Metric} instance for the current time. - * @param name the name of the metric - * @param value the value of the metric - */ - public Metric(String name, T value) { - this(name, value, new Date()); - } - - /** - * Create a new {@link Metric} instance. - * @param name the name of the metric - * @param value the value of the metric - * @param timestamp the timestamp for the metric - */ - public Metric(String name, T value, Date timestamp) { - Assert.notNull(name, "Name must not be null"); - this.name = name; - this.value = value; - this.timestamp = timestamp; - } - - /** - * Returns the name of the metric. - * @return the name - */ - public String getName() { - return this.name; - } - - /** - * Returns the value of the metric. - * @return the value - */ - public T getValue() { - return this.value; - } - - public Date getTimestamp() { - return this.timestamp; - } - - @Override - public String toString() { - return "Metric [name=" + this.name + ", value=" + this.value + ", timestamp=" - + this.timestamp + "]"; - } - - /** - * Create a new {@link Metric} with an incremented value. - * @param amount the amount that the new metric will differ from this one - * @return a new {@link Metric} instance - */ - public Metric increment(int amount) { - return new Metric<>(this.getName(), - Long.valueOf(this.getValue().longValue() + amount)); - } - - /** - * Create a new {@link Metric} with a different value. - * @param the metric value type - * @param value the value of the new metric - * @return a new {@link Metric} instance - */ - public Metric set(S value) { - return new Metric<>(this.getName(), value); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ObjectUtils.nullSafeHashCode(this.name); - result = prime * result + ObjectUtils.nullSafeHashCode(this.timestamp); - result = prime * result + ObjectUtils.nullSafeHashCode(this.value); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (obj instanceof Metric) { - Metric other = (Metric) obj; - boolean rtn = true; - rtn = rtn && ObjectUtils.nullSafeEquals(this.name, other.name); - rtn = rtn && ObjectUtils.nullSafeEquals(this.timestamp, other.timestamp); - rtn = rtn && ObjectUtils.nullSafeEquals(this.value, other.value); - return rtn; - } - return super.equals(obj); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReader.java deleted file mode 100644 index 96a3ec368040..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReader.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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.metrics.aggregate; - -import java.util.HashSet; -import java.util.Set; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.util.StringUtils; - -/** - * A metric reader that aggregates values from a source reader, normally one that has been - * collecting data from many sources in the same form (like a scaled-out application). The - * source has metrics with names in the form {@code *.*.counter.**} and - * {@code *.*.[anything].**}, and the result has metric names in the form - * {@code aggregate.count.**} and {@code aggregate.[anything].**}. Counters are summed and - * anything else (i.e. gauges) are aggregated by choosing the most recent value. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class AggregateMetricReader implements MetricReader { - - private MetricReader source; - - private String keyPattern = "d.d"; - - private String prefix = "aggregate."; - - public AggregateMetricReader(MetricReader source) { - this.source = source; - } - - /** - * Pattern that tells the aggregator what to do with the keys from the source - * repository. The keys in the source repository are assumed to be period separated, - * and the pattern is in the same format, e.g. "d.d.k.d". The pattern segments are - * matched against the source keys and a rule is applied: - *

    - *
  • "d" means "discard" this key segment (useful for global prefixes like system - * identifiers, or aggregate keys a.k.a. physical identifiers)
  • - *
  • "k" means "keep" it with no change (useful for logical identifiers like app - * names)
  • - *
- * Default is "d.d" (we assume there is a global prefix of length 2). - * @param keyPattern the keyPattern to set - */ - public void setKeyPattern(String keyPattern) { - this.keyPattern = keyPattern; - } - - /** - * Prefix to apply to all output metrics. A period will be appended if not present in - * the provided value. - * @param prefix the prefix to use (default "aggregator.") - */ - public void setPrefix(String prefix) { - if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) { - prefix = prefix + "."; - } - this.prefix = prefix; - } - - @Override - public Metric findOne(String metricName) { - if (!metricName.startsWith(this.prefix)) { - return null; - } - InMemoryMetricRepository result = new InMemoryMetricRepository(); - String baseName = metricName.substring(this.prefix.length()); - for (Metric metric : this.source.findAll()) { - String name = getSourceKey(metric.getName()); - if (baseName.equals(name)) { - update(result, name, metric); - } - } - return result.findOne(metricName); - } - - @Override - public Iterable> findAll() { - InMemoryMetricRepository result = new InMemoryMetricRepository(); - for (Metric metric : this.source.findAll()) { - String key = getSourceKey(metric.getName()); - if (key != null) { - update(result, key, metric); - } - } - return result.findAll(); - } - - @Override - public long count() { - Set names = new HashSet<>(); - for (Metric metric : this.source.findAll()) { - String name = getSourceKey(metric.getName()); - if (name != null) { - names.add(name); - } - } - return names.size(); - } - - private void update(InMemoryMetricRepository result, String key, Metric metric) { - String name = this.prefix + key; - Metric aggregate = result.findOne(name); - if (aggregate == null) { - aggregate = new Metric(name, metric.getValue(), - metric.getTimestamp()); - } - else if (key.contains("counter.")) { - // accumulate all values - aggregate = new Metric(name, - metric.increment(aggregate.getValue().intValue()).getValue(), - metric.getTimestamp()); - } - else if (aggregate.getTimestamp().before(metric.getTimestamp())) { - // sort by timestamp and only take the latest - aggregate = new Metric(name, metric.getValue(), - metric.getTimestamp()); - } - result.set(aggregate); - } - - private String getSourceKey(String name) { - String[] keys = StringUtils.delimitedListToStringArray(name, "."); - String[] patterns = StringUtils.delimitedListToStringArray(this.keyPattern, "."); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < patterns.length; i++) { - if ("k".equals(patterns[i])) { - builder.append(builder.length() > 0 ? "." : ""); - builder.append(keys[i]); - } - } - for (int i = patterns.length; i < keys.length; i++) { - builder.append(builder.length() > 0 ? "." : ""); - builder.append(keys[i]); - } - return builder.toString(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/package-info.java deleted file mode 100644 index 85e328bc6ec9..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/aggregate/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Classes for aggregation metrics. - */ -package org.springframework.boot.actuate.metrics.aggregate; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffer.java deleted file mode 100644 index 708fbf89d743..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.buffer; - -/** - * Base class for a mutable buffer containing a timestamp and a value. - * - * @param the value type - * @author Dave Syer - * @author Phillip Webb - */ -abstract class Buffer { - - private volatile long timestamp; - - Buffer(long timestamp) { - this.timestamp = timestamp; - } - - public long getTimestamp() { - return this.timestamp; - } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - /** - * Returns the buffer value. - * @return the value of the buffer - */ - public abstract T getValue(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferCounterService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferCounterService.java deleted file mode 100644 index 0ffa20dc85ab..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferCounterService.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.boot.actuate.metrics.CounterService; - -/** - * Fast implementation of {@link CounterService} using {@link CounterBuffers}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class BufferCounterService implements CounterService { - - private final ConcurrentHashMap names = new ConcurrentHashMap<>(); - - private final CounterBuffers buffers; - - /** - * Create a {@link BufferCounterService} instance. - * @param buffers the underlying buffers used to store metrics - */ - public BufferCounterService(CounterBuffers buffers) { - this.buffers = buffers; - } - - @Override - public void increment(String metricName) { - this.buffers.increment(wrap(metricName), 1L); - } - - @Override - public void decrement(String metricName) { - this.buffers.increment(wrap(metricName), -1L); - } - - @Override - public void reset(String metricName) { - this.buffers.reset(wrap(metricName)); - } - - private String wrap(String metricName) { - String cached = this.names.get(metricName); - if (cached != null) { - return cached; - } - if (metricName.startsWith("counter") || metricName.startsWith("meter")) { - return metricName; - } - String name = "counter." + metricName; - this.names.put(metricName, name); - return name; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeService.java deleted file mode 100644 index d928cbd31f4d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.boot.actuate.metrics.GaugeService; - -/** - * Fast implementation of {@link GaugeService} using {@link GaugeBuffers}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class BufferGaugeService implements GaugeService { - - private final ConcurrentHashMap names = new ConcurrentHashMap<>(); - - private final GaugeBuffers buffers; - - /** - * Create a {@link BufferGaugeService} instance. - * @param buffers the underlying buffers used to store metrics - */ - public BufferGaugeService(GaugeBuffers buffers) { - this.buffers = buffers; - } - - @Override - public void submit(String metricName, double value) { - this.buffers.set(wrap(metricName), value); - } - - private String wrap(String metricName) { - String cached = this.names.get(metricName); - if (cached != null) { - return cached; - } - if (metricName.startsWith("gauge") || metricName.startsWith("histogram") - || metricName.startsWith("timer")) { - return metricName; - } - String name = "gauge." + metricName; - this.names.put(metricName, name); - return name; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReader.java deleted file mode 100644 index ae0070fafe89..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReader.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.reader.PrefixMetricReader; - -/** - * {@link MetricReader} implementation using {@link CounterBuffers} and - * {@link GaugeBuffers}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class BufferMetricReader implements MetricReader, PrefixMetricReader { - - private static final Predicate ALL = Pattern.compile(".*").asPredicate(); - - private final CounterBuffers counterBuffers; - - private final GaugeBuffers gaugeBuffers; - - public BufferMetricReader(CounterBuffers counterBuffers, GaugeBuffers gaugeBuffers) { - this.counterBuffers = counterBuffers; - this.gaugeBuffers = gaugeBuffers; - } - - @Override - public Metric findOne(String name) { - Buffer buffer = this.counterBuffers.find(name); - if (buffer == null) { - buffer = this.gaugeBuffers.find(name); - } - return (buffer == null ? null : asMetric(name, buffer)); - } - - @Override - public Iterable> findAll() { - return findAll(BufferMetricReader.ALL); - } - - @Override - public Iterable> findAll(String prefix) { - return findAll(Pattern.compile(prefix + ".*").asPredicate()); - } - - @Override - public long count() { - return this.counterBuffers.count() + this.gaugeBuffers.count(); - } - - private Iterable> findAll(Predicate predicate) { - final List> metrics = new ArrayList<>(); - collectMetrics(this.gaugeBuffers, predicate, metrics); - collectMetrics(this.counterBuffers, predicate, metrics); - return metrics; - } - - private > void collectMetrics( - Buffers buffers, Predicate predicate, - final List> metrics) { - buffers.forEach(predicate, (name, value) -> metrics.add(asMetric(name, value))); - } - - private Metric asMetric(String name, Buffer buffer) { - return new Metric<>(name, buffer.getValue(), new Date(buffer.getTimestamp())); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffers.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffers.java deleted file mode 100644 index f7bad60d514a..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/Buffers.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Predicate; - -/** - * Base class used to manage a map of {@link Buffer} objects. - * - * @param The buffer type - * @author Dave Syer - * @author Phillip Webb - */ -abstract class Buffers> { - - private final ConcurrentHashMap buffers = new ConcurrentHashMap<>(); - - public void forEach(final Predicate predicate, - BiConsumer consumer) { - this.buffers.forEach((name, value) -> { - if (predicate.test(name)) { - consumer.accept(name, value); - } - }); - } - - public B find(String name) { - return this.buffers.get(name); - } - - public int count() { - return this.buffers.size(); - } - - protected final void doWith(String name, Consumer consumer) { - B buffer = this.buffers.get(name); - if (buffer == null) { - buffer = this.buffers.computeIfAbsent(name, (k) -> createBuffer()); - } - consumer.accept(buffer); - } - - protected abstract B createBuffer(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffer.java deleted file mode 100644 index 2d34e68acb4b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.buffer; - -import java.util.concurrent.atomic.LongAdder; - -/** - * Mutable buffer containing a long adder (Java 8) and a timestamp. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class CounterBuffer extends Buffer { - - private final LongAdder adder; - - public CounterBuffer(long timestamp) { - super(timestamp); - this.adder = new LongAdder(); - } - - public void add(long delta) { - this.adder.add(delta); - } - - public void reset() { - this.adder.reset(); - } - - @Override - public Long getValue() { - return this.adder.sum(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffers.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffers.java deleted file mode 100644 index 7381fde6c52c..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffers.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.metrics.buffer; - -/** - * Fast writes to in-memory metrics store using {@link CounterBuffer}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class CounterBuffers extends Buffers { - - public void increment(String name, long delta) { - doWith(name, (buffer) -> { - buffer.setTimestamp(System.currentTimeMillis()); - buffer.add(delta); - }); - } - - public void reset(String name) { - doWith(name, (buffer) -> { - buffer.setTimestamp(System.currentTimeMillis()); - buffer.reset(); - }); - } - - @Override - protected CounterBuffer createBuffer() { - return new CounterBuffer(0); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffer.java deleted file mode 100644 index fa5f6568bc1e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.buffer; - -/** - * Mutable buffer containing a double value and a timestamp. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class GaugeBuffer extends Buffer { - - private volatile double value; - - public GaugeBuffer(long timestamp) { - super(timestamp); - this.value = 0; - } - - @Override - public Double getValue() { - return this.value; - } - - public void setValue(double value) { - this.value = value; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffers.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffers.java deleted file mode 100644 index 6ed46231858a..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/GaugeBuffers.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.metrics.buffer; - -/** - * Fast writes to in-memory metrics store using {@link GaugeBuffer}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class GaugeBuffers extends Buffers { - - public void set(String name, double value) { - doWith(name, (buffer) -> { - buffer.setTimestamp(System.currentTimeMillis()); - buffer.setValue(value); - }); - } - - @Override - protected GaugeBuffer createBuffer() { - return new GaugeBuffer(0L); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/package-info.java deleted file mode 100644 index b7090d885b41..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/buffer/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics buffering support. - */ -package org.springframework.boot.actuate.metrics.buffer; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java deleted file mode 100644 index 64d11a5605f8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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.metrics.dropwizard; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -import com.codahale.metrics.Counter; -import com.codahale.metrics.Gauge; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.Meter; -import com.codahale.metrics.Metric; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.Reservoir; -import com.codahale.metrics.Timer; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.core.ResolvableType; -import org.springframework.util.Assert; - -/** - * A {@link GaugeService} and {@link CounterService} that sends data to a Dropwizard - * {@link MetricRegistry} based on a naming convention. - *
    - *
  • Updates to {@link #increment(String)} with names in "meter.*" are treated as - * {@link Meter} events
  • - *
  • Other deltas are treated as simple {@link Counter} values
  • - *
  • Inputs to {@link #submit(String, double)} with names in "histogram.*" are treated - * as {@link Histogram} updates
  • - *
  • Inputs to {@link #submit(String, double)} with names in "timer.*" are treated as - * {@link Timer} updates
  • - *
  • Other metrics are treated as simple {@link Gauge} values (single valued - * measurements of type double)
  • - *
- * - * @author Dave Syer - * @author Jay Anderson - * @author Andy Wilkinson - */ -public class DropwizardMetricServices implements CounterService, GaugeService { - - private final MetricRegistry registry; - - private final ReservoirFactory reservoirFactory; - - private final ConcurrentMap gauges = new ConcurrentHashMap<>(); - - private final ConcurrentHashMap names = new ConcurrentHashMap<>(); - - /** - * Create a new {@link DropwizardMetricServices} instance. - * @param registry the underlying metric registry - */ - public DropwizardMetricServices(MetricRegistry registry) { - this(registry, null); - } - - /** - * Create a new {@link DropwizardMetricServices} instance. - * @param registry the underlying metric registry - * @param reservoirFactory the factory that instantiates the {@link Reservoir} that - * will be used on Timers and Histograms - */ - public DropwizardMetricServices(MetricRegistry registry, - ReservoirFactory reservoirFactory) { - this.registry = registry; - this.reservoirFactory = (reservoirFactory == null ? ReservoirFactory.NONE - : reservoirFactory); - } - - @Override - public void increment(String name) { - incrementInternal(name, 1L); - } - - @Override - public void decrement(String name) { - incrementInternal(name, -1L); - } - - private void incrementInternal(String name, long value) { - if (name.startsWith("meter")) { - Meter meter = this.registry.meter(name); - meter.mark(value); - } - else { - name = wrapCounterName(name); - Counter counter = this.registry.counter(name); - counter.inc(value); - } - } - - @Override - public void submit(String name, double value) { - if (name.startsWith("histogram")) { - submitHistogram(name, value); - } - else if (name.startsWith("timer")) { - submitTimer(name, value); - } - else { - name = wrapGaugeName(name); - setGaugeValue(name, value); - } - } - - private void submitTimer(String name, double value) { - long longValue = (long) value; - Timer metric = register(name, new TimerMetricRegistrar()); - metric.update(longValue, TimeUnit.MILLISECONDS); - } - - private void submitHistogram(String name, double value) { - long longValue = (long) value; - Histogram metric = register(name, new HistogramMetricRegistrar()); - metric.update(longValue); - } - - @SuppressWarnings("unchecked") - private T register(String name, MetricRegistrar registrar) { - Reservoir reservoir = this.reservoirFactory.getReservoir(name); - if (reservoir == null) { - return registrar.register(this.registry, name); - } - Metric metric = this.registry.getMetrics().get(name); - if (metric != null) { - registrar.checkExisting(metric); - return (T) metric; - } - try { - return this.registry.register(name, registrar.createForReservoir(reservoir)); - } - catch (IllegalArgumentException ex) { - Metric added = this.registry.getMetrics().get(name); - registrar.checkExisting(added); - return (T) added; - } - } - - private void setGaugeValue(String name, double value) { - // NOTE: Dropwizard provides no way to do this atomically - SimpleGauge gauge = this.gauges.get(name); - if (gauge == null) { - SimpleGauge newGauge = new SimpleGauge(value); - gauge = this.gauges.putIfAbsent(name, newGauge); - if (gauge == null) { - this.registry.register(name, newGauge); - return; - } - } - gauge.setValue(value); - } - - private String wrapGaugeName(String metricName) { - return wrapName(metricName, "gauge."); - } - - private String wrapCounterName(String metricName) { - return wrapName(metricName, "counter."); - } - - private String wrapName(String metricName, String prefix) { - String cached = this.names.get(metricName); - if (cached != null) { - return cached; - } - if (metricName.startsWith(prefix)) { - return metricName; - } - String name = prefix + metricName; - this.names.put(metricName, name); - return name; - } - - @Override - public void reset(String name) { - if (!name.startsWith("meter")) { - name = wrapCounterName(name); - } - this.registry.remove(name); - } - - /** - * Simple {@link Gauge} implementation to {@literal double} value. - */ - private final static class SimpleGauge implements Gauge { - - private volatile double value; - - private SimpleGauge(double value) { - this.value = value; - } - - @Override - public Double getValue() { - return this.value; - } - - public void setValue(double value) { - this.value = value; - } - - } - - /** - * Strategy used to register metrics. - */ - private static abstract class MetricRegistrar { - - private final Class type; - - @SuppressWarnings("unchecked") - MetricRegistrar() { - this.type = (Class) ResolvableType - .forClass(MetricRegistrar.class, getClass()).resolveGeneric(); - } - - public void checkExisting(Metric metric) { - Assert.isInstanceOf(this.type, metric, - "Different metric type already registered"); - } - - protected abstract T register(MetricRegistry registry, String name); - - protected abstract T createForReservoir(Reservoir reservoir); - - } - - /** - * {@link MetricRegistrar} for {@link Timer} metrics. - */ - private static class TimerMetricRegistrar extends MetricRegistrar { - - @Override - protected Timer register(MetricRegistry registry, String name) { - return registry.timer(name); - } - - @Override - protected Timer createForReservoir(Reservoir reservoir) { - return new Timer(reservoir); - } - - } - - /** - * {@link MetricRegistrar} for {@link Histogram} metrics. - */ - private static class HistogramMetricRegistrar extends MetricRegistrar { - - @Override - protected Histogram register(MetricRegistry registry, String name) { - return registry.histogram(name); - } - - @Override - protected Histogram createForReservoir(Reservoir reservoir) { - return new Histogram(reservoir); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/ReservoirFactory.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/ReservoirFactory.java deleted file mode 100644 index b3a20b6edfbf..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/ReservoirFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.metrics.dropwizard; - -import com.codahale.metrics.Reservoir; - -/** - * Factory interface that can be used by {@link DropwizardMetricServices} to create a - * custom {@link Reservoir}. - * - * @author Lucas Saldanha - * @author Phillip Webb - * @since 1.5.0 - */ -@FunctionalInterface -public interface ReservoirFactory { - - /** - * Default empty {@link ReservoirFactory} implementation. - */ - ReservoirFactory NONE = (name) -> null; - - /** - * Return the {@link Reservoir} instance to use or {@code null} if a custom reservoir - * is not needed. - * @param name the name of the metric - * @return a reservoir instance or {@code null} - */ - Reservoir getReservoir(String name); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/package-info.java deleted file mode 100644 index 14864c15e2d4..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics integration with Dropwizard Metrics. - */ -package org.springframework.boot.actuate.metrics.dropwizard; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java deleted file mode 100644 index 9a93e2b0f7f7..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.metrics.export; - -import java.io.Closeable; -import java.io.Flushable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.util.StringUtils; - -/** - * Base class for metric exporters that have common features, principally a prefix for - * exported metrics and filtering by timestamp (so only new values are included in the - * export). - * - * @author Dave Syer - * @since 1.3.0 - */ -public abstract class AbstractMetricExporter implements Exporter, Closeable, Flushable { - - private static final Log logger = LogFactory.getLog(AbstractMetricExporter.class); - - private final String prefix; - - private Date earliestTimestamp = new Date(); - - private boolean ignoreTimestamps = false; - - private boolean sendLatest = true; - - private volatile AtomicBoolean processing = new AtomicBoolean(false); - - private Date latestTimestamp = new Date(0L); - - public AbstractMetricExporter(String prefix) { - this.prefix = (!StringUtils.hasText(prefix) ? "" - : (prefix.endsWith(".") ? prefix : prefix + ".")); - } - - /** - * The earliest time for which data will be exported. - * @param earliestTimestamp the timestamp to set - */ - public void setEarliestTimestamp(Date earliestTimestamp) { - this.earliestTimestamp = earliestTimestamp; - } - - /** - * Ignore timestamps (export all metrics). - * @param ignoreTimestamps the flag to set - */ - public void setIgnoreTimestamps(boolean ignoreTimestamps) { - this.ignoreTimestamps = ignoreTimestamps; - } - - /** - * Send only the data that changed since the last export. - * @param sendLatest the flag to set - */ - public void setSendLatest(boolean sendLatest) { - this.sendLatest = sendLatest; - } - - @Override - public void export() { - if (this.processing.compareAndSet(false, true)) { - long latestTimestamp = System.currentTimeMillis(); - try { - exportGroups(); - } - catch (Exception ex) { - logger.warn("Could not write to MetricWriter: " + ex.getClass() + ": " - + ex.getMessage()); - } - finally { - this.latestTimestamp = new Date(latestTimestamp); - flushQuietly(); - this.processing.set(false); - } - } - } - - private void exportGroups() { - for (String group : groups()) { - Collection> values = new ArrayList<>(); - for (Metric metric : next(group)) { - Date timestamp = metric.getTimestamp(); - if (canExportTimestamp(timestamp)) { - values.add(getPrefixedMetric(metric)); - } - } - if (!values.isEmpty()) { - write(group, values); - } - } - } - - private Metric getPrefixedMetric(Metric metric) { - String name = this.prefix + metric.getName(); - return new Metric(name, metric.getValue(), metric.getTimestamp()); - } - - private boolean canExportTimestamp(Date timestamp) { - if (this.ignoreTimestamps) { - return true; - } - if (this.earliestTimestamp.after(timestamp)) { - return false; - } - if (this.sendLatest && this.latestTimestamp.after(timestamp)) { - return false; - } - return true; - } - - private void flushQuietly() { - try { - flush(); - } - catch (Exception ex) { - logger.warn("Could not flush MetricWriter: " + ex.getClass() + ": " - + ex.getMessage()); - } - } - - @Override - public void close() throws IOException { - export(); - flushQuietly(); - } - - @Override - public void flush() { - } - - /** - * Generate a group of metrics to iterate over in the form of a set of Strings (e.g. - * prefixes). If the metrics to be exported partition into groups identified by a - * String, subclasses should override this method. Otherwise the default should be - * fine (iteration over all metrics). - * @return groups of metrics to iterate over (default singleton empty string) - */ - protected Iterable groups() { - return Collections.singleton(""); - } - - /** - * Write the values associated with a group. - * @param group the group to write - * @param values the values to write - */ - protected abstract void write(String group, Collection> values); - - /** - * Get the next group of metrics to write. - * @param group the group name to write - * @return some metrics to write - */ - protected abstract Iterable> next(String group); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/Exporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/Exporter.java deleted file mode 100644 index 067197b19ada..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/Exporter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.metrics.export; - -/** - * Generic interface for metric exports. As you scale up metric collection you will often - * need to buffer metric data locally and export it periodically (e.g. for aggregation - * across a cluster), so this is the marker interface for those operations. The trigger of - * an export operation might be periodic or event driven, but it remains outside the scope - * of this interface. You might for instance create an instance of an Exporter and trigger - * it using a {@code @Scheduled} annotation in a Spring ApplicationContext. - * - * @author Dave Syer - * @since 1.3.0 - */ -@FunctionalInterface -public interface Exporter { - - /** - * Export metric data. - */ - void export(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporter.java deleted file mode 100644 index 5eec2cdff568..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporter.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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.metrics.export; - -import java.io.Flushable; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.writer.CompositeMetricWriter; -import org.springframework.boot.actuate.metrics.writer.CounterWriter; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; -import org.springframework.util.ClassUtils; -import org.springframework.util.ObjectUtils; -import org.springframework.util.PatternMatchUtils; -import org.springframework.util.ReflectionUtils; - -/** - * {@link Exporter} that "exports" by copying metric data from a source - * {@link MetricReader} to a destination {@link MetricWriter}. Actually the output writer - * can be a {@link GaugeWriter}, in which case all metrics are simply output as their - * current value. If the output writer is also a {@link CounterWriter} then metrics whose - * names begin with "counter." are special: instead of writing them out as simple gauges - * the writer will increment the counter value. This involves the exporter storing the - * previous value of the counter so the delta can be computed. For best results with the - * counters, do not use the exporter concurrently in multiple threads (normally it will - * only be used periodically and sequentially, even if it is in a background thread, and - * this is fine). - * - * @author Dave Syer - * @since 1.3.0 - */ -public class MetricCopyExporter extends AbstractMetricExporter { - - private static final Log logger = LogFactory.getLog(MetricCopyExporter.class); - - private final MetricReader reader; - - private final GaugeWriter writer; - - private final CounterWriter counter; - - private ConcurrentMap counts = new ConcurrentHashMap<>(); - - private String[] includes = new String[0]; - - private String[] excludes = new String[0]; - - /** - * Create a new {@link MetricCopyExporter} instance. - * @param reader the metric reader - * @param writer the metric writer - */ - public MetricCopyExporter(MetricReader reader, GaugeWriter writer) { - this(reader, writer, ""); - } - - /** - * Create a new {@link MetricCopyExporter} instance. - * @param reader the metric reader - * @param writer the metric writer - * @param prefix the name prefix - */ - public MetricCopyExporter(MetricReader reader, GaugeWriter writer, String prefix) { - super(prefix); - this.reader = reader; - this.writer = writer; - if (writer instanceof CounterWriter) { - this.counter = (CounterWriter) writer; - } - else { - this.counter = null; - } - } - - /** - * Set the include patterns used to filter metrics. - * @param includes the include patterns - */ - public void setIncludes(String... includes) { - if (includes != null) { - this.includes = includes; - } - } - - /** - * Set the exclude patterns used to filter metrics. - * @param excludes the exclude patterns - */ - public void setExcludes(String... excludes) { - if (excludes != null) { - this.excludes = excludes; - } - } - - @Override - protected Iterable> next(String group) { - if (ObjectUtils.isEmpty(this.includes) && ObjectUtils.isEmpty(this.excludes)) { - return this.reader.findAll(); - } - return new PatternMatchingIterable(MetricCopyExporter.this.reader); - } - - @Override - protected void write(String group, Collection> values) { - for (Metric value : values) { - if (value.getName().startsWith("counter.") && this.counter != null) { - this.counter.increment(calculateDelta(value)); - } - else { - this.writer.set(value); - } - } - } - - private Delta calculateDelta(Metric value) { - long delta = value.getValue().longValue(); - Long old = this.counts.replace(value.getName(), delta); - if (old != null) { - delta = delta - old; - } - else { - this.counts.putIfAbsent(value.getName(), delta); - } - return new Delta<>(value.getName(), delta, value.getTimestamp()); - } - - @Override - public void flush() { - flush(this.writer); - } - - private void flush(GaugeWriter writer) { - if (writer instanceof CompositeMetricWriter) { - for (MetricWriter child : (CompositeMetricWriter) writer) { - flush(child); - } - } - try { - if (ClassUtils.isPresent("java.io.Flushable", null)) { - if (writer instanceof Flushable) { - ((Flushable) writer).flush(); - return; - } - } - Method method = ReflectionUtils.findMethod(writer.getClass(), "flush"); - if (method != null) { - ReflectionUtils.invokeMethod(method, writer); - } - } - catch (Exception ex) { - logger.warn("Could not flush MetricWriter: " + ex.getClass() + ": " - + ex.getMessage()); - } - } - - private class PatternMatchingIterable implements Iterable> { - - private final MetricReader reader; - - PatternMatchingIterable(MetricReader reader) { - this.reader = reader; - } - - @Override - public Iterator> iterator() { - return new PatternMatchingIterator(this.reader.findAll().iterator()); - } - - } - - private class PatternMatchingIterator implements Iterator> { - - private Metric buffer = null; - - private Iterator> iterator; - - PatternMatchingIterator(Iterator> iterator) { - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - if (this.buffer != null) { - return true; - } - this.buffer = findNext(); - return this.buffer != null; - } - - private Metric findNext() { - while (this.iterator.hasNext()) { - Metric metric = this.iterator.next(); - if (isMatch(metric)) { - return metric; - } - } - return null; - } - - private boolean isMatch(Metric metric) { - String[] includes = MetricCopyExporter.this.includes; - String[] excludes = MetricCopyExporter.this.excludes; - String name = metric.getName(); - if (ObjectUtils.isEmpty(includes) - || PatternMatchUtils.simpleMatch(includes, name)) { - return !PatternMatchUtils.simpleMatch(excludes, name); - } - return false; - } - - @Override - public Metric next() { - Metric metric = this.buffer; - this.buffer = null; - return metric; - } - - }; - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExportProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExportProperties.java deleted file mode 100644 index 39222ea745c9..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExportProperties.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import javax.annotation.PostConstruct; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.PatternMatchUtils; - -/** - * Configuration properties for metrics export. - * - * @author Dave Syer - * @author Simon Buettner - * @since 1.3.0 - */ -@ConfigurationProperties(prefix = "spring.metrics.export") -public class MetricExportProperties extends TriggerProperties { - - /** - * Specific trigger properties per MetricWriter bean name. - */ - private Map triggers = new LinkedHashMap<>(); - - private Aggregate aggregate = new Aggregate(); - - private Redis redis = new Redis(); - - private Statsd statsd = new Statsd(); - - @PostConstruct - public void setUpDefaults() { - TriggerProperties defaults = this; - for (Entry entry : this.triggers.entrySet()) { - String key = entry.getKey(); - SpecificTriggerProperties value = entry.getValue(); - if (value.getNames() == null || value.getNames().length == 0) { - value.setNames(new String[] { key }); - } - } - if (defaults.isSendLatest() == null) { - defaults.setSendLatest(true); - } - if (defaults.getDelayMillis() == null) { - defaults.setDelayMillis(5000); - } - for (TriggerProperties value : this.triggers.values()) { - if (value.isSendLatest() == null) { - value.setSendLatest(defaults.isSendLatest()); - } - if (value.getDelayMillis() == null) { - value.setDelayMillis(defaults.getDelayMillis()); - } - } - } - - /** - * Configuration for triggers on individual named writers. Each value can individually - * specify a name pattern explicitly, or else the map key will be used if the name is - * not set. - * @return the writers - */ - public Map getTriggers() { - return this.triggers; - } - - public Aggregate getAggregate() { - return this.aggregate; - } - - public void setAggregate(Aggregate aggregate) { - this.aggregate = aggregate; - } - - public Redis getRedis() { - return this.redis; - } - - public void setRedis(Redis redis) { - this.redis = redis; - } - - public Statsd getStatsd() { - return this.statsd; - } - - public void setStatsd(Statsd statsd) { - this.statsd = statsd; - } - - /** - * Find a matching trigger configuration. - * @param name the bean name to match - * @return a matching configuration if there is one - */ - public TriggerProperties findTrigger(String name) { - for (SpecificTriggerProperties value : this.triggers.values()) { - if (PatternMatchUtils.simpleMatch(value.getNames(), name)) { - return value; - } - } - return this; - } - - /** - * Aggregate properties. - */ - public static class Aggregate { - - /** - * Prefix for global repository if active. Should be unique for this JVM, but most - * useful if it also has the form "a.b" where "a" is unique to this logical - * process (this application) and "b" is unique to this physical process. If you - * set spring.application.name elsewhere, then the default will be in the right - * form. - */ - private String prefix = ""; - - /** - * Pattern that tells the aggregator what to do with the keys from the source - * repository. The keys in the source repository are assumed to be period - * separated, and the pattern is in the same format, e.g. "d.d.k.d". Here "d" - * means "discard" and "k" means "keep" the key segment in the corresponding - * position in the source. - */ - private String keyPattern = ""; - - public String getPrefix() { - return this.prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public String getKeyPattern() { - return this.keyPattern; - } - - public void setKeyPattern(String keyPattern) { - this.keyPattern = keyPattern; - } - - } - - /** - * Redis properties. - */ - public static class Redis { - - /** - * Prefix for redis repository if active. Should be globally unique across all - * processes sharing the same repository. - */ - private String prefix = "spring.metrics"; - - /** - * Key for redis repository export (if active). Should be globally unique for a - * system sharing a redis repository across multiple processes. - */ - private String key = "keys.spring.metrics"; - - public String getPrefix() { - return this.prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public String getKey() { - return this.key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getAggregatePrefix() { - // The common case including a standalone aggregator would have a prefix that - // starts with the end of the key, so strip that bit off and call it the - // aggregate prefix. - if (this.key.startsWith("keys.")) { - String candidate = this.key.substring("keys.".length()); - if (this.prefix.startsWith(candidate)) { - return candidate; - } - return candidate; - } - // If the user went off piste, choose something that is safe (not empty) but - // not the whole prefix (on the assumption that it contains dimension keys) - if (this.prefix.contains(".") - && this.prefix.indexOf(".") < this.prefix.length() - 1) { - return this.prefix.substring(this.prefix.indexOf(".") + 1); - } - return this.prefix; - } - - } - - /** - * Statsd properties. - */ - public static class Statsd { - - /** - * Host of a statsd server to receive exported metrics. - */ - private String host; - - /** - * Port of a statsd server to receive exported metrics. - */ - private int port = 8125; - - /** - * Prefix for statsd exported metrics. - */ - private String prefix; - - public String getHost() { - return this.host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return this.port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getPrefix() { - return this.prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java deleted file mode 100644 index fb6d06e7d205..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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.metrics.export; - -import java.io.Closeable; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.config.IntervalTask; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -/** - * {@link SchedulingConfigurer} to handle metrics {@link MetricCopyExporter export}. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class MetricExporters implements SchedulingConfigurer, Closeable { - - private MetricReader reader; - - private Map writers = new HashMap<>(); - - private final MetricExportProperties properties; - - private final Map exporters = new HashMap<>(); - - private final Set closeables = new HashSet<>(); - - public MetricExporters(MetricExportProperties properties) { - this.properties = properties; - } - - public void setReader(MetricReader reader) { - this.reader = reader; - } - - public void setWriters(Map writers) { - this.writers.putAll(writers); - } - - public void setExporters(Map exporters) { - this.exporters.putAll(exporters); - } - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - for (Entry entry : this.exporters.entrySet()) { - String name = entry.getKey(); - Exporter exporter = entry.getValue(); - TriggerProperties trigger = this.properties.findTrigger(name); - if (trigger != null) { - ExportRunner runner = new ExportRunner(exporter); - IntervalTask task = new IntervalTask(runner, trigger.getDelayMillis(), - trigger.getDelayMillis()); - taskRegistrar.addFixedDelayTask(task); - } - } - for (Entry entry : this.writers.entrySet()) { - String name = entry.getKey(); - GaugeWriter writer = entry.getValue(); - TriggerProperties trigger = this.properties.findTrigger(name); - if (trigger != null) { - MetricCopyExporter exporter = getExporter(writer, trigger); - this.exporters.put(name, exporter); - this.closeables.add(name); - ExportRunner runner = new ExportRunner(exporter); - IntervalTask task = new IntervalTask(runner, trigger.getDelayMillis(), - trigger.getDelayMillis()); - taskRegistrar.addFixedDelayTask(task); - } - } - } - - private MetricCopyExporter getExporter(GaugeWriter writer, - TriggerProperties trigger) { - MetricCopyExporter exporter = new MetricCopyExporter(this.reader, writer); - exporter.setIncludes(trigger.getIncludes()); - exporter.setExcludes(trigger.getExcludes()); - exporter.setSendLatest(trigger.isSendLatest()); - return exporter; - } - - public Map getExporters() { - return this.exporters; - } - - @Override - public void close() throws IOException { - for (String name : this.closeables) { - Exporter exporter = this.exporters.get(name); - if (exporter instanceof Closeable) { - ((Closeable) exporter).close(); - } - } - } - - private static class ExportRunner implements Runnable { - - private final Exporter exporter; - - ExportRunner(Exporter exporter) { - this.exporter = exporter; - } - - @Override - public void run() { - this.exporter.export(); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java deleted file mode 100644 index 90e8a9ebe77d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.PrefixMetricReader; -import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter; - -/** - * A convenient exporter for a group of metrics from a {@link PrefixMetricReader}. Exports - * all metrics whose name starts with a prefix (or all metrics if the prefix is empty). - * - * @author Dave Syer - * @since 1.3.0 - */ -public class PrefixMetricGroupExporter extends AbstractMetricExporter { - - private final PrefixMetricReader reader; - - private final PrefixMetricWriter writer; - - private ConcurrentMap counts = new ConcurrentHashMap<>(); - - private Set groups = new HashSet<>(); - - /** - * Create a new exporter for metrics to a writer based on an empty prefix for the - * metric names. - * @param reader a reader as the source of metrics - * @param writer the writer to send the metrics to - */ - public PrefixMetricGroupExporter(PrefixMetricReader reader, - PrefixMetricWriter writer) { - this(reader, writer, ""); - } - - /** - * Create a new exporter for metrics to a writer based on a prefix for the metric - * names. - * @param reader a reader as the source of metrics - * @param writer the writer to send the metrics to - * @param prefix the prefix for metrics to export - */ - public PrefixMetricGroupExporter(PrefixMetricReader reader, PrefixMetricWriter writer, - String prefix) { - super(prefix); - this.reader = reader; - this.writer = writer; - } - - /** - * The groups to export. - * @param groups the groups to set - */ - public void setGroups(Set groups) { - this.groups = groups; - } - - @Override - protected Iterable groups() { - if ((this.reader instanceof MultiMetricRepository) && this.groups.isEmpty()) { - return ((MultiMetricRepository) this.reader).groups(); - } - return this.groups; - } - - @Override - protected Iterable> next(String group) { - return this.reader.findAll(group); - } - - @Override - protected void write(String group, Collection> values) { - if (group.contains("counter.")) { - for (Metric value : values) { - this.writer.increment(group, calculateDelta(value)); - } - } - else { - this.writer.set(group, values); - } - } - - private Delta calculateDelta(Metric value) { - long delta = value.getValue().longValue(); - Long old = this.counts.replace(value.getName(), delta); - if (old != null) { - delta = delta - old; - } - else { - this.counts.putIfAbsent(value.getName(), delta); - } - return new Delta<>(value.getName(), delta, value.getTimestamp()); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporter.java deleted file mode 100644 index f996bac0f1f0..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporter.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; -import org.springframework.boot.actuate.metrics.rich.RichGauge; -import org.springframework.boot.actuate.metrics.rich.RichGaugeReader; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; -import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter; - -/** - * Exporter or converter for {@link RichGauge} data to a metric-based back end. Each gauge - * measurement is stored as a set of related metrics with a common prefix (the name of the - * gauge), and suffixes that describe the data. For example, a gauge called {@code foo} is - * stored as {@code[foo.min, foo.max. foo.val, foo.count, foo.avg, foo.alpha]}. If the - * {@link MetricWriter} provided is a {@link MultiMetricRepository} then the values for a - * gauge will be stored as a group, and hence will be retrievable from the repository in a - * single query (or optionally individually). - * - * @author Dave Syer - * @since 1.3.0 - */ -public class RichGaugeExporter extends AbstractMetricExporter { - - private static final String MIN = ".min"; - - private static final String MAX = ".max"; - - private static final String COUNT = ".count"; - - private static final String VALUE = ".val"; - - private static final String AVG = ".avg"; - - private static final String ALPHA = ".alpha"; - - private final RichGaugeReader reader; - - private final PrefixMetricWriter writer; - - public RichGaugeExporter(RichGaugeReader reader, PrefixMetricWriter writer) { - this(reader, writer, ""); - } - - public RichGaugeExporter(RichGaugeReader reader, PrefixMetricWriter writer, - String prefix) { - super(prefix); - this.reader = reader; - this.writer = writer; - } - - @Override - protected Iterable> next(String group) { - RichGauge rich = this.reader.findOne(group); - Collection> metrics = new ArrayList<>(); - metrics.add(new Metric(group + MIN, rich.getMin())); - metrics.add(new Metric(group + MAX, rich.getMax())); - metrics.add(new Metric(group + COUNT, rich.getCount())); - metrics.add(new Metric(group + VALUE, rich.getValue())); - metrics.add(new Metric(group + AVG, rich.getAverage())); - metrics.add(new Metric(group + ALPHA, rich.getAlpha())); - return metrics; - } - - @Override - protected Iterable groups() { - Collection names = new HashSet<>(); - for (RichGauge rich : this.reader.findAll()) { - names.add(rich.getName()); - } - return names; - } - - @Override - protected void write(String group, Collection> values) { - this.writer.set(group, values); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/SpecificTriggerProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/SpecificTriggerProperties.java deleted file mode 100644 index 0b291dbb9ed2..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/SpecificTriggerProperties.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.export; - -/** - * Trigger for specific names or patterns. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class SpecificTriggerProperties extends TriggerProperties { - - /** - * Names (or patterns) for bean names that this configuration applies to. - */ - private String[] names; - - public String[] getNames() { - return this.names; - } - - public void setNames(String[] names) { - this.names = names; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/TriggerProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/TriggerProperties.java deleted file mode 100644 index 513c0a0f377a..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/TriggerProperties.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.export; - -/** - * Abstract base class for trigger properties. - * - * @author Dave Syer - * @since 1.3.0 - */ -public abstract class TriggerProperties { - - /** - * Delay in milliseconds between export ticks. Metrics are exported to external - * sources on a schedule with this delay. - */ - private Long delayMillis; - - /** - * Flag to enable metric export (assuming a MetricWriter is available). - */ - private boolean enabled = true; - - /** - * Flag to switch off any available optimizations based on not exporting unchanged - * metric values. - */ - private Boolean sendLatest; - - /** - * List of patterns for metric names to include. - */ - private String[] includes; - - /** - * List of patterns for metric names to exclude. Applied after the includes. - */ - private String[] excludes; - - public String[] getIncludes() { - return this.includes; - } - - public void setIncludes(String[] includes) { - this.includes = includes; - } - - public void setExcludes(String[] excludes) { - this.excludes = excludes; - } - - public String[] getExcludes() { - return this.excludes; - } - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public Long getDelayMillis() { - return this.delayMillis; - } - - public void setDelayMillis(long delayMillis) { - this.delayMillis = delayMillis; - } - - public Boolean isSendLatest() { - return this.sendLatest; - } - - public void setSendLatest(boolean sendLatest) { - this.sendLatest = sendLatest; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/package-info.java deleted file mode 100644 index 2a0ab81c8095..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics export support. - */ -package org.springframework.boot.actuate.metrics.export; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java deleted file mode 100644 index cb3bffb186ae..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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.metrics.integration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.integration.support.management.IntegrationManagementConfigurer; -import org.springframework.integration.support.management.MessageChannelMetrics; -import org.springframework.integration.support.management.MessageHandlerMetrics; -import org.springframework.integration.support.management.MessageSourceMetrics; -import org.springframework.integration.support.management.PollableChannelManagement; -import org.springframework.integration.support.management.Statistics; - -/** - * A {@link MetricReader} for Spring Integration metrics (as provided by - * {@link IntegrationManagementConfigurer}). - * - * @author Dave Syer - * @author Artem Bilan - * @since 1.3.0 - */ -public class SpringIntegrationMetricReader implements MetricReader { - - private final IntegrationManagementConfigurer configurer; - - public SpringIntegrationMetricReader(IntegrationManagementConfigurer configurer) { - this.configurer = configurer; - } - - @Override - public Metric findOne(String metricName) { - return null; - } - - @Override - public Iterable> findAll() { - List> result = new ArrayList<>(); - String[] channelNames = this.configurer.getChannelNames(); - String[] handlerNames = this.configurer.getHandlerNames(); - String[] sourceNames = this.configurer.getSourceNames(); - addChannelMetrics(result, channelNames); - addHandlerMetrics(result, handlerNames); - addSourceMetrics(result, sourceNames); - result.add(new Metric<>("integration.handlerCount", handlerNames.length)); - result.add(new Metric<>("integration.channelCount", channelNames.length)); - result.add(new Metric<>("integration.sourceCount", sourceNames.length)); - return result; - } - - private void addChannelMetrics(List> result, String[] names) { - for (String name : names) { - addChannelMetrics(result, name, this.configurer.getChannelMetrics(name)); - } - } - - private void addChannelMetrics(List> result, String name, - MessageChannelMetrics metrics) { - String prefix = "integration.channel." + name; - result.addAll(getStatistics(prefix + ".errorRate", metrics.getErrorRate())); - result.add(new Metric<>(prefix + ".sendCount", metrics.getSendCountLong())); - result.addAll(getStatistics(prefix + ".sendRate", metrics.getSendRate())); - if (metrics instanceof PollableChannelManagement) { - result.add(new Metric<>(prefix + ".receiveCount", - ((PollableChannelManagement) metrics).getReceiveCountLong())); - } - } - - private void addHandlerMetrics(List> result, String[] names) { - for (String name : names) { - addHandlerMetrics(result, name, this.configurer.getHandlerMetrics(name)); - } - } - - private void addHandlerMetrics(List> result, String name, - MessageHandlerMetrics metrics) { - String prefix = "integration.handler." + name; - result.addAll(getStatistics(prefix + ".duration", metrics.getDuration())); - long activeCount = metrics.getActiveCountLong(); - result.add(new Metric<>(prefix + ".activeCount", activeCount)); - } - - private void addSourceMetrics(List> result, String[] names) { - for (String name : names) { - addSourceMetrics(result, name, this.configurer.getSourceMetrics(name)); - } - } - - private void addSourceMetrics(List> result, String name, - MessageSourceMetrics sourceMetrics) { - String prefix = "integration.source." + name; - result.add(new Metric<>(prefix + ".messageCount", - sourceMetrics.getMessageCountLong())); - } - - private Collection> getStatistics(String name, Statistics stats) { - List> metrics = new ArrayList<>(); - metrics.add(new Metric<>(name + ".mean", stats.getMean())); - metrics.add(new Metric<>(name + ".max", stats.getMax())); - metrics.add(new Metric<>(name + ".min", stats.getMin())); - metrics.add(new Metric<>(name + ".stdev", stats.getStandardDeviation())); - metrics.add(new Metric<>(name + ".count", stats.getCountLong())); - return metrics; - } - - @Override - public long count() { - int totalChannelCount = this.configurer.getChannelNames().length; - int totalHandlerCount = this.configurer.getHandlerNames().length; - int totalSourceCount = this.configurer.getSourceNames().length; - return totalChannelCount + totalHandlerCount + totalSourceCount; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/package-info.java deleted file mode 100644 index bfa7a446fe0f..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Spring Integration metrics support. - */ -package org.springframework.boot.actuate.metrics.integration; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategy.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategy.java deleted file mode 100644 index 45ddd1e36d55..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategy.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.metrics.jmx; - -import java.util.Hashtable; - -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -import org.springframework.jmx.export.naming.KeyNamingStrategy; -import org.springframework.jmx.export.naming.ObjectNamingStrategy; -import org.springframework.util.StringUtils; - -/** - * MBean naming strategy for metric keys. A metric name of {@code counter.foo.bar.spam} - * translates to an object name with {@code type=counter}, {@code name=foo} and - * {@code value=bar.spam}. This results in a more or less pleasing view with no tweaks in - * jconsole or jvisualvm. The domain is copied from the input key and the type in the - * input key is discarded. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class DefaultMetricNamingStrategy implements ObjectNamingStrategy { - - private ObjectNamingStrategy namingStrategy = new KeyNamingStrategy(); - - @Override - public ObjectName getObjectName(Object managedBean, String beanKey) - throws MalformedObjectNameException { - ObjectName objectName = this.namingStrategy.getObjectName(managedBean, beanKey); - String domain = objectName.getDomain(); - Hashtable table = new Hashtable<>( - objectName.getKeyPropertyList()); - String name = objectName.getKeyProperty("name"); - if (name != null) { - table.remove("name"); - String[] parts = StringUtils.delimitedListToStringArray(name, "."); - table.put("type", parts[0]); - if (parts.length > 1) { - table.put(parts.length > 2 ? "name" : "value", parts[1]); - } - if (parts.length > 2) { - table.put("value", - name.substring(parts[0].length() + parts[1].length() + 2)); - } - } - return new ObjectName(domain, table); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/JmxMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/JmxMetricWriter.java deleted file mode 100644 index 9a0f271ea953..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/JmxMetricWriter.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.metrics.jmx; - -import java.util.Date; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; -import org.springframework.jmx.export.MBeanExporter; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.jmx.export.naming.ObjectNamingStrategy; - -/** - * A {@link MetricWriter} for MBeans. Each metric is registered as an individual MBean, so - * (for instance) it can be graphed and monitored. The object names are provided by an - * {@link ObjectNamingStrategy}, where the default is a - * {@link DefaultMetricNamingStrategy} which provides {@code type}, {@code name} and - * {@code value} keys by splitting up the metric name on periods. - * - * @author Dave Syer - * @since 1.3.0 - */ -@ManagedResource(description = "MetricWriter for pushing metrics to JMX MBeans.") -public class JmxMetricWriter implements MetricWriter { - - private static final Log logger = LogFactory.getLog(JmxMetricWriter.class); - - private final ConcurrentMap values = new ConcurrentHashMap<>(); - - private final MBeanExporter exporter; - - private ObjectNamingStrategy namingStrategy = new DefaultMetricNamingStrategy(); - - private String domain = "org.springframework.metrics"; - - public JmxMetricWriter(MBeanExporter exporter) { - this.exporter = exporter; - } - - public void setNamingStrategy(ObjectNamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; - } - - public void setDomain(String domain) { - this.domain = domain; - } - - @ManagedOperation - public void increment(String name, long value) { - increment(new Delta<>(name, value)); - } - - @Override - public void increment(Delta delta) { - MetricValue counter = getValue(delta.getName()); - counter.increment(delta.getValue().longValue()); - } - - @ManagedOperation - public void set(String name, double value) { - set(new Metric<>(name, value)); - } - - @Override - public void set(Metric value) { - MetricValue metric = getValue(value.getName()); - metric.setValue(value.getValue().doubleValue()); - } - - @Override - @ManagedOperation - public void reset(String name) { - MetricValue value = this.values.remove(name); - if (value != null) { - try { - // We can unregister the MBean, but if this writer is on the end of an - // Exporter the chances are it will be re-registered almost immediately. - this.exporter.unregisterManagedResource(getName(name, value)); - } - catch (MalformedObjectNameException ex) { - logger.warn("Could not unregister MBean for " + name); - } - } - } - - private MetricValue getValue(String name) { - MetricValue value = this.values.get(name); - if (value == null) { - value = new MetricValue(); - MetricValue oldValue = this.values.putIfAbsent(name, value); - if (oldValue != null) { - value = oldValue; - } - try { - this.exporter.registerManagedResource(value, getName(name, value)); - } - catch (Exception ex) { - // Could not register mbean, maybe just a race condition - } - } - return value; - } - - private ObjectName getName(String name, MetricValue value) - throws MalformedObjectNameException { - String key = String.format(this.domain + ":type=MetricValue,name=%s", name); - return this.namingStrategy.getObjectName(value, key); - } - - /** - * A single metric value. - */ - @ManagedResource - public static class MetricValue { - - private double value; - - private long lastUpdated = 0; - - public void setValue(double value) { - if (this.value != value) { - this.lastUpdated = System.currentTimeMillis(); - } - this.value = value; - } - - public void increment(long value) { - this.lastUpdated = System.currentTimeMillis(); - this.value += value; - } - - @ManagedAttribute - public double getValue() { - return this.value; - } - - @ManagedAttribute - public Date getLastUpdated() { - return new Date(this.lastUpdated); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/package-info.java deleted file mode 100644 index af557de79930..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/jmx/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics integration with JMX. - */ -package org.springframework.boot.actuate.metrics.jmx; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/DefaultOpenTsdbNamingStrategy.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/DefaultOpenTsdbNamingStrategy.java deleted file mode 100644 index abdd76fc99a8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/DefaultOpenTsdbNamingStrategy.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.metrics.opentsdb; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.util.ObjectUtils; - -/** - * A naming strategy that just passes through the metric name, together with tags from a - * set of static values. Open TSDB requires at least one tag, so tags are always added for - * you: the {@value #DOMAIN_KEY} key is added with a value "spring", and the - * {@value #PROCESS_KEY} key is added with a value equal to the object hash of "this" (the - * naming strategy). The "domain" value is a system identifier - it would be common to all - * processes in the same distributed system. In most cases this will be unique enough to - * allow aggregation of the underlying metrics in Open TSDB, but normally it is best to - * provide your own tags, including a prefix and process identifier if you know one - * (overwriting the default). - * - * @author Dave Syer - * @since 1.3.0 - */ -public class DefaultOpenTsdbNamingStrategy implements OpenTsdbNamingStrategy { - - /** - * The domain key. - */ - public static final String DOMAIN_KEY = "domain"; - - /** - * The process key. - */ - public static final String PROCESS_KEY = "process"; - - /** - * Tags to apply to every metric. Open TSDB requires at least one tag, so a "prefix" - * tag is added for you by default. - */ - private Map tags = new LinkedHashMap<>(); - - private Map cache = new HashMap<>(); - - public DefaultOpenTsdbNamingStrategy() { - this.tags.put(DOMAIN_KEY, "org.springframework.metrics"); - this.tags.put(PROCESS_KEY, ObjectUtils.getIdentityHexString(this)); - } - - public void setTags(Map staticTags) { - this.tags.putAll(staticTags); - } - - @Override - public OpenTsdbName getName(String name) { - if (this.cache.containsKey(name)) { - return this.cache.get(name); - } - OpenTsdbName value = new OpenTsdbName(name); - value.setTags(this.tags); - this.cache.put(name, value); - return value; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbData.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbData.java deleted file mode 100644 index df216ab96548..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbData.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.opentsdb; - -import java.util.Map; - -/** - * OpenTSDB Data. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class OpenTsdbData { - - private OpenTsdbName name; - - private Long timestamp; - - private Number value; - - protected OpenTsdbData() { - this.name = new OpenTsdbName(); - } - - public OpenTsdbData(String metric, Number value) { - this(metric, value, System.currentTimeMillis()); - } - - public OpenTsdbData(String metric, Number value, Long timestamp) { - this(new OpenTsdbName(metric), value, timestamp); - } - - public OpenTsdbData(OpenTsdbName name, Number value, Long timestamp) { - this.name = name; - this.value = value; - this.timestamp = timestamp; - } - - public String getMetric() { - return this.name.getMetric(); - } - - public void setMetric(String metric) { - this.name.setMetric(metric); - } - - public Long getTimestamp() { - return this.timestamp; - } - - public void setTimestamp(Long timestamp) { - this.timestamp = timestamp; - } - - public Number getValue() { - return this.value; - } - - public void setValue(Number value) { - this.value = value; - } - - public Map getTags() { - return this.name.getTags(); - } - - public void setTags(Map tags) { - this.name.setTags(tags); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriter.java deleted file mode 100644 index 576ffa20f5a3..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriter.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.metrics.opentsdb; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.client.RestOperations; -import org.springframework.web.client.RestTemplate; - -/** - * A {@link GaugeWriter} for the Open TSDB database (version 2.0), writing metrics to the - * HTTP endpoint provided by the server. Data are buffered according to the - * {@link #setBufferSize(int) bufferSize} property, and only flushed automatically when - * the buffer size is reached. Users should either manually {@link #flush()} after writing - * a batch of data if that makes sense, or consider adding a {@link Scheduled Scheduled} - * task to flush periodically. - * - * @author Dave Syer - * @author Thomas Badie - * @since 1.3.0 - */ -public class OpenTsdbGaugeWriter implements GaugeWriter { - - private static final int DEFAULT_CONNECT_TIMEOUT = 10000; - - private static final int DEFAULT_READ_TIMEOUT = 30000; - - private static final Log logger = LogFactory.getLog(OpenTsdbGaugeWriter.class); - - private RestOperations restTemplate; - - /** - * URL for POSTing data. Defaults to http://localhost:4242/api/put. - */ - private String url = "http://localhost:4242/api/put"; - - /** - * Buffer size to fill before posting data to server. - */ - private int bufferSize = 64; - - /** - * The media type to use to serialize and accept responses from the server. Defaults - * to "application/json". - */ - private MediaType mediaType = MediaType.APPLICATION_JSON; - - private final List buffer = new ArrayList<>(this.bufferSize); - - private OpenTsdbNamingStrategy namingStrategy = new DefaultOpenTsdbNamingStrategy(); - - /** - * Creates a new {@code OpenTsdbGaugeWriter} with the default connect (10 seconds) and - * read (30 seconds) timeouts. - */ - public OpenTsdbGaugeWriter() { - this(DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT); - } - - /** - * Creates a new {@code OpenTsdbGaugeWriter} with the given millisecond - * {@code connectTimeout} and {@code readTimeout}. - * @param connectTimeout the connect timeout in milliseconds - * @param readTimeout the read timeout in milliseconds - */ - public OpenTsdbGaugeWriter(int connectTimeout, int readTimeout) { - SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); - requestFactory.setConnectTimeout(connectTimeout); - requestFactory.setReadTimeout(readTimeout); - this.restTemplate = new RestTemplate(requestFactory); - } - - public RestOperations getRestTemplate() { - return this.restTemplate; - } - - public void setRestTemplate(RestOperations restTemplate) { - this.restTemplate = restTemplate; - } - - public void setUrl(String url) { - this.url = url; - } - - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - public void setMediaType(MediaType mediaType) { - this.mediaType = mediaType; - } - - public void setNamingStrategy(OpenTsdbNamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; - } - - @Override - public void set(Metric value) { - OpenTsdbData data = new OpenTsdbData(this.namingStrategy.getName(value.getName()), - value.getValue(), value.getTimestamp().getTime()); - synchronized (this.buffer) { - this.buffer.add(data); - if (this.buffer.size() >= this.bufferSize) { - flush(); - } - } - } - - /** - * Flush the buffer without waiting for it to fill any further. - */ - @SuppressWarnings("rawtypes") - public void flush() { - List snapshot = getBufferSnapshot(); - if (snapshot.isEmpty()) { - return; - } - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(this.mediaType)); - headers.setContentType(this.mediaType); - ResponseEntity response = this.restTemplate.postForEntity(this.url, - new HttpEntity<>(snapshot, headers), Map.class); - if (!response.getStatusCode().is2xxSuccessful()) { - logger.warn("Cannot write metrics (discarded " + snapshot.size() - + " values): " + response.getBody()); - } - } - - private List getBufferSnapshot() { - synchronized (this.buffer) { - if (this.buffer.isEmpty()) { - return Collections.emptyList(); - } - List snapshot = new ArrayList<>(this.buffer); - this.buffer.clear(); - return snapshot; - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbName.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbName.java deleted file mode 100644 index 682f69912f31..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbName.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.metrics.opentsdb; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * OpenTSDB Name. - * - * @author Dave Syer - * @since 1.3.0 - */ -public class OpenTsdbName { - - private String metric; - - private Map tags = new LinkedHashMap<>(); - - protected OpenTsdbName() { - } - - public OpenTsdbName(String metric) { - this.metric = metric; - } - - public String getMetric() { - return this.metric; - } - - public void setMetric(String metric) { - this.metric = metric; - } - - public Map getTags() { - return this.tags; - } - - public void setTags(Map tags) { - this.tags.putAll(tags); - } - - public void tag(String name, String value) { - this.tags.put(name, value); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbNamingStrategy.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbNamingStrategy.java deleted file mode 100644 index 82ab5e0a9fc8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbNamingStrategy.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.metrics.opentsdb; - -/** - * Strategy used to convert a metric name into an {@link OpenTsdbName}. - * - * @author Dave Syer - * @since 1.3.0 - */ -@FunctionalInterface -public interface OpenTsdbNamingStrategy { - - /** - * Convert the metric name into a {@link OpenTsdbName}. - * @param metricName the name of the metric - * @return an Open TSDB name - */ - OpenTsdbName getName(String metricName); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/package-info.java deleted file mode 100644 index 619a3f161c16..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/opentsdb/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics integration with OpenTSDB. - */ -package org.springframework.boot.actuate.metrics.opentsdb; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/package-info.java deleted file mode 100644 index b220f18cd930..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Core metrics classes. - */ -package org.springframework.boot.actuate.metrics; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/CompositeMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/CompositeMetricReader.java deleted file mode 100644 index 1a8cb8fa4f91..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/CompositeMetricReader.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.metrics.reader; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Composite implementation of {@link MetricReader}. - * - * @author Dave Syer - */ -public class CompositeMetricReader implements MetricReader { - - private final List readers = new ArrayList<>(); - - public CompositeMetricReader(MetricReader... readers) { - Collections.addAll(this.readers, readers); - } - - @Override - public Metric findOne(String metricName) { - for (MetricReader delegate : this.readers) { - Metric value = delegate.findOne(metricName); - if (value != null) { - return value; - } - } - return null; - } - - @Override - public Iterable> findAll() { - List> values = new ArrayList<>((int) count()); - for (MetricReader delegate : this.readers) { - Iterable> all = delegate.findAll(); - for (Metric value : all) { - values.add(value); - } - } - return values; - } - - @Override - public long count() { - long count = 0; - for (MetricReader delegate : this.readers) { - count += delegate.count(); - - } - return count; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricReader.java deleted file mode 100644 index e82eede79ecc..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricReader.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2013 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.metrics.reader; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * A simple reader interface used to interrogate {@link Metric}s. - * - * @author Dave Syer - */ -public interface MetricReader { - - /** - * Find an instance of the metric with the given name (usually the latest recorded - * value). - * @param metricName the name of the metric to find - * @return a metric value or null if there are none with that name - */ - Metric findOne(String metricName); - - /** - * Find all the metrics known to this reader. - * @return all instances of metrics known to this reader - */ - Iterable> findAll(); - - /** - * The number of metrics known to this reader. - * @return the number of metrics - */ - long count(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java deleted file mode 100644 index 76a9da69883e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * 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.metrics.reader; - -import java.beans.PropertyDescriptor; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -import com.codahale.metrics.Counter; -import com.codahale.metrics.Gauge; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.Meter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.MetricRegistryListener; -import com.codahale.metrics.Sampling; -import com.codahale.metrics.Timer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.util.ClassUtils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; - -/** - * A Spring Boot {@link MetricReader} that reads metrics from a Dropwizard - * {@link MetricRegistry}. Gauges and Counters are reflected as a single value. Timers, - * Meters and Histograms are expanded into sets of metrics containing all the properties - * of type Number. - * - * @author Dave Syer - * @author Andy Wilkinson - */ -public class MetricRegistryMetricReader implements MetricReader, MetricRegistryListener { - - private static final Log logger = LogFactory.getLog(MetricRegistryMetricReader.class); - - private static final Map, Set> numberKeys = new ConcurrentHashMap<>(); - - private final Object monitor = new Object(); - - private final Map names = new ConcurrentHashMap<>(); - - private final MultiValueMap reverse = new LinkedMultiValueMap<>(); - - private final MetricRegistry registry; - - public MetricRegistryMetricReader(MetricRegistry registry) { - this.registry = registry; - registry.addListener(this); - } - - @Override - public Metric findOne(String metricName) { - String name = this.names.get(metricName); - if (name == null) { - return null; - } - com.codahale.metrics.Metric metric = this.registry.getMetrics().get(name); - if (metric == null) { - return null; - } - if (metric instanceof Counter) { - Counter counter = (Counter) metric; - return new Metric(metricName, counter.getCount()); - } - if (metric instanceof Gauge) { - Object value = ((Gauge) metric).getValue(); - if (value instanceof Number) { - return new Metric<>(metricName, (Number) value); - } - if (logger.isDebugEnabled()) { - logger.debug("Ignoring gauge '" + name + "' (" + metric - + ") as its value is not a Number"); - } - return null; - } - if (metric instanceof Sampling) { - if (metricName.contains(".snapshot.")) { - Number value = getMetric(((Sampling) metric).getSnapshot(), metricName); - if (metric instanceof Timer) { - // convert back to MILLISEC - value = TimeUnit.MILLISECONDS.convert(value.longValue(), - TimeUnit.NANOSECONDS); - } - return new Metric<>(metricName, value); - } - } - return new Metric<>(metricName, getMetric(metric, metricName)); - } - - @Override - public Iterable> findAll() { - return () -> { - Set> metrics = new HashSet<>(); - for (String name : MetricRegistryMetricReader.this.names.keySet()) { - Metric metric = findOne(name); - if (metric != null) { - metrics.add(metric); - } - } - return metrics.iterator(); - }; - } - - @Override - public long count() { - return this.names.size(); - } - - @Override - public void onGaugeAdded(String name, Gauge gauge) { - this.names.put(name, name); - synchronized (this.monitor) { - this.reverse.add(name, name); - } - } - - @Override - public void onGaugeRemoved(String name) { - remove(name); - } - - @Override - public void onCounterAdded(String name, Counter counter) { - this.names.put(name, name); - synchronized (this.monitor) { - this.reverse.add(name, name); - } - } - - @Override - public void onCounterRemoved(String name) { - remove(name); - } - - @Override - public void onHistogramAdded(String name, Histogram histogram) { - for (String key : getNumberKeys(histogram)) { - String metricName = name + "." + key; - this.names.put(metricName, name); - synchronized (this.monitor) { - this.reverse.add(name, metricName); - } - } - for (String key : getNumberKeys(histogram.getSnapshot())) { - String metricName = name + ".snapshot." + key; - this.names.put(metricName, name); - synchronized (this.monitor) { - this.reverse.add(name, metricName); - } - } - } - - @Override - public void onHistogramRemoved(String name) { - remove(name); - } - - @Override - public void onMeterAdded(String name, Meter meter) { - for (String key : getNumberKeys(meter)) { - String metricName = name + "." + key; - this.names.put(metricName, name); - synchronized (this.monitor) { - this.reverse.add(name, metricName); - } - } - } - - @Override - public void onMeterRemoved(String name) { - remove(name); - } - - @Override - public void onTimerAdded(String name, Timer timer) { - for (String key : getNumberKeys(timer)) { - String metricName = name + "." + key; - this.names.put(metricName, name); - synchronized (this.monitor) { - this.reverse.add(name, metricName); - } - } - for (String key : getNumberKeys(timer.getSnapshot())) { - String metricName = name + ".snapshot." + key; - this.names.put(metricName, name); - synchronized (this.monitor) { - this.reverse.add(name, metricName); - } - } - } - - @Override - public void onTimerRemoved(String name) { - remove(name); - } - - private void remove(String name) { - List keys; - synchronized (this.monitor) { - keys = this.reverse.remove(name); - } - if (keys != null) { - for (String key : keys) { - this.names.remove(name + "." + key); - } - } - } - - private static Set getNumberKeys(Object metric) { - Set result = numberKeys.get(metric.getClass()); - if (result == null) { - result = new HashSet<>(); - } - if (result.isEmpty()) { - for (PropertyDescriptor descriptor : BeanUtils - .getPropertyDescriptors(metric.getClass())) { - if (ClassUtils.isAssignable(Number.class, descriptor.getPropertyType())) { - result.add(descriptor.getName()); - } - } - numberKeys.put(metric.getClass(), result); - } - return result; - } - - private static Number getMetric(Object metric, String metricName) { - String key = StringUtils.getFilenameExtension(metricName); - return (Number) new BeanWrapperImpl(metric).getPropertyValue(key); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/PrefixMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/PrefixMetricReader.java deleted file mode 100644 index 39c599bd9035..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/PrefixMetricReader.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.metrics.reader; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Interface for extracting metrics as a group whose name starts with a prefix. - * - * @author Dave Syer - */ -@FunctionalInterface -public interface PrefixMetricReader { - - /** - * Find all metrics whose name starts with the given prefix. - * @param prefix the prefix for metric names - * @return all metrics with names starting with the prefix - */ - Iterable> findAll(String prefix); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/package-info.java deleted file mode 100644 index 2c0a84ffd0b5..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics readers. - * - * @see org.springframework.boot.actuate.metrics.reader.MetricReader - */ -package org.springframework.boot.actuate.metrics.reader; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java deleted file mode 100644 index 37f9e71a1532..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.metrics.repository; - -import java.util.Date; -import java.util.concurrent.ConcurrentNavigableMap; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.util.SimpleInMemoryRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; - -/** - * {@link MetricRepository} implementation that stores metrics in memory. - * - * @author Dave Syer - * @author Stephane Nicoll - */ -public class InMemoryMetricRepository implements MetricRepository { - - private final SimpleInMemoryRepository> metrics = new SimpleInMemoryRepository<>(); - - public void setValues(ConcurrentNavigableMap> values) { - this.metrics.setValues(values); - } - - @Override - public void increment(Delta delta) { - final String metricName = delta.getName(); - final int amount = delta.getValue().intValue(); - final Date timestamp = delta.getTimestamp(); - this.metrics.update(metricName, (current) -> { - if (current != null) { - return new Metric<>(metricName, current.increment(amount).getValue(), - timestamp); - } - return new Metric<>(metricName, (long) amount, timestamp); - }); - } - - @Override - public void set(Metric value) { - this.metrics.set(value.getName(), value); - } - - @Override - public long count() { - return this.metrics.count(); - } - - @Override - public void reset(String metricName) { - this.metrics.remove(metricName); - } - - @Override - public Metric findOne(String metricName) { - return this.metrics.findOne(metricName); - } - - @Override - public Iterable> findAll() { - return this.metrics.findAll(); - } - - public Iterable> findAllWithPrefix(String prefix) { - return this.metrics.findAllWithPrefix(prefix); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java deleted file mode 100644 index ed82b152d57d..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.metrics.repository; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.util.Assert; - -/** - * {@link MultiMetricRepository} implementation backed by a - * {@link InMemoryMetricRepository}. - * - * @author Stephane Nicoll - * @since 1.5.0 - */ -public class InMemoryMultiMetricRepository implements MultiMetricRepository { - - private final InMemoryMetricRepository repository; - - private final Collection groups = new HashSet<>(); - - /** - * Create a new {@link InMemoryMetricRepository} backed by a new - * {@link InMemoryMetricRepository}. - */ - public InMemoryMultiMetricRepository() { - this(new InMemoryMetricRepository()); - } - - /** - * Create a new {@link InMemoryMetricRepository} backed by the specified - * {@link InMemoryMetricRepository}. - * @param repository the backing repository - */ - public InMemoryMultiMetricRepository(InMemoryMetricRepository repository) { - Assert.notNull(repository, "Repository must not be null"); - this.repository = repository; - } - - @Override - public void set(String group, Collection> values) { - String prefix = group; - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - for (Metric metric : values) { - if (!metric.getName().startsWith(prefix)) { - metric = new Metric(prefix + metric.getName(), metric.getValue(), - metric.getTimestamp()); - } - this.repository.set(metric); - } - this.groups.add(group); - } - - @Override - public void increment(String group, Delta delta) { - String prefix = group; - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - if (!delta.getName().startsWith(prefix)) { - delta = new Delta(prefix + delta.getName(), delta.getValue(), - delta.getTimestamp()); - } - this.repository.increment(delta); - this.groups.add(group); - } - - @Override - public Iterable groups() { - return Collections.unmodifiableCollection(this.groups); - } - - @Override - public long countGroups() { - return this.groups.size(); - } - - @Override - public void reset(String group) { - for (Metric metric : findAll(group)) { - this.repository.reset(metric.getName()); - } - this.groups.remove(group); - } - - @Override - public Iterable> findAll(String metricNamePrefix) { - return this.repository.findAllWithPrefix(metricNamePrefix); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MetricRepository.java deleted file mode 100644 index ff69d6d712fe..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MetricRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012-2013 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.metrics.repository; - -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; - -/** - * Convenient combination of reader and writer concerns. - * - * @author Dave Syer - */ -public interface MetricRepository extends MetricReader, MetricWriter { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java deleted file mode 100644 index c80a2576e066..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2014 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.metrics.repository; - -import org.springframework.boot.actuate.metrics.reader.PrefixMetricReader; -import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter; - -/** - * A repository for metrics that allows efficient storage and retrieval of groups of - * metrics with a common name prefix (their group name). - * - * @author Dave Syer - */ -public interface MultiMetricRepository extends PrefixMetricReader, PrefixMetricWriter { - - /** - * The names of all the groups known to this repository. - * @return all available group names - */ - Iterable groups(); - - /** - * The number of groups available in this repository. - * @return the number of groups - */ - long countGroups(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/package-info.java deleted file mode 100644 index 57a4bdcbfd7e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics repository support. - * - * @see org.springframework.boot.actuate.metrics.repository.MetricRepository - */ -package org.springframework.boot.actuate.metrics.repository; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepository.java deleted file mode 100644 index be77aec59a71..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepository.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.metrics.repository.redis; - -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.MetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.BoundZSetOperations; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.util.Assert; - -/** - * A {@link MetricRepository} implementation for a redis backend. Metric values are stored - * as zset values plus a regular hash value for the timestamp, both against a key composed - * of the metric name prefixed with a constant (default "spring.metrics."). If you have - * multiple metrics repositories all point at the same instance of Redis, it may be useful - * to change the prefix to be unique (but not if you want them to contribute to the same - * metrics). - * - * @author Dave Syer - */ -public class RedisMetricRepository implements MetricRepository { - - private static final String DEFAULT_METRICS_PREFIX = "spring.metrics."; - - private static final String DEFAULT_KEY = "keys.spring.metrics"; - - private String prefix = DEFAULT_METRICS_PREFIX; - - private String key = DEFAULT_KEY; - - private BoundZSetOperations zSetOperations; - - private final RedisOperations redisOperations; - - /** - * Create a RedisMetricRepository with a default prefix to apply to all metric names. - * If multiple repositories share a redis instance they will feed into the same global - * metrics. - * @param redisConnectionFactory the redis connection factory - */ - public RedisMetricRepository(RedisConnectionFactory redisConnectionFactory) { - this(redisConnectionFactory, null); - } - - /** - * Create a RedisMetricRepository with a prefix to apply to all metric names (ideally - * unique to this repository or to a logical repository contributed to by multiple - * instances, where they all see the same values). Recommended constructor for general - * purpose use. - * @param redisConnectionFactory the redis connection factory - * @param prefix the prefix to set for all metrics keys - */ - public RedisMetricRepository(RedisConnectionFactory redisConnectionFactory, - String prefix) { - this(redisConnectionFactory, prefix, null); - } - - /** - * Allows user to set the prefix and key to use to store the index of other keys. The - * redis store will hold a zset under the key just so the metric names can be - * enumerated. Read operations, especially {@link #findAll()} and {@link #count()}, - * will only be accurate if the key is unique to the prefix of this repository. - * @param redisConnectionFactory the redis connection factory - * @param prefix the prefix to set for all metrics keys - * @param key the key to set - */ - public RedisMetricRepository(RedisConnectionFactory redisConnectionFactory, - String prefix, String key) { - if (prefix == null) { - prefix = DEFAULT_METRICS_PREFIX; - if (key == null) { - key = DEFAULT_KEY; - } - } - else if (key == null) { - key = "keys." + prefix; - } - Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); - this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - this.prefix = prefix; - if (key.endsWith(".")) { - key = key.substring(0, key.length() - 1); - } - this.key = key; - this.zSetOperations = this.redisOperations.boundZSetOps(this.key); - } - - @Override - public Metric findOne(String metricName) { - String redisKey = keyFor(metricName); - String raw = this.redisOperations.opsForValue().get(redisKey); - return deserialize(redisKey, raw, this.zSetOperations.score(redisKey)); - } - - @Override - public Iterable> findAll() { - - // This set is sorted - Set keys = this.zSetOperations.range(0, -1); - Iterator keysIt = keys.iterator(); - - List> result = new ArrayList<>(keys.size()); - List values = this.redisOperations.opsForValue().multiGet(keys); - for (String v : values) { - String key = keysIt.next(); - Metric value = deserialize(key, v, this.zSetOperations.score(key)); - if (value != null) { - result.add(value); - } - } - return result; - - } - - @Override - public long count() { - return this.zSetOperations.size(); - } - - @Override - public void increment(Delta delta) { - String name = delta.getName(); - String key = keyFor(name); - trackMembership(key); - double value = this.zSetOperations.incrementScore(key, - delta.getValue().doubleValue()); - String raw = serialize(new Metric<>(name, value, delta.getTimestamp())); - this.redisOperations.opsForValue().set(key, raw); - } - - @Override - public void set(Metric value) { - String name = value.getName(); - String key = keyFor(name); - trackMembership(key); - this.zSetOperations.add(key, value.getValue().doubleValue()); - String raw = serialize(value); - this.redisOperations.opsForValue().set(key, raw); - } - - @Override - public void reset(String metricName) { - String key = keyFor(metricName); - if (this.zSetOperations.remove(key) == 1) { - this.redisOperations.delete(key); - } - } - - private Metric deserialize(String redisKey, String v, Double value) { - if (redisKey == null || v == null || !redisKey.startsWith(this.prefix)) { - return null; - } - Date timestamp = new Date(Long.valueOf(v)); - return new Metric<>(nameFor(redisKey), value, timestamp); - } - - private String serialize(Metric entity) { - return String.valueOf(entity.getTimestamp().getTime()); - } - - private String keyFor(String name) { - return this.prefix + name; - } - - private String nameFor(String redisKey) { - return redisKey.substring(this.prefix.length()); - } - - private void trackMembership(String redisKey) { - this.zSetOperations.incrementScore(redisKey, 0.0D); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java deleted file mode 100644 index aeeadee27180..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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.metrics.repository.redis; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.BoundZSetOperations; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.util.Assert; - -/** - * {@link MultiMetricRepository} implementation backed by a redis store. Metric values are - * stored as zset values and the timestamps as regular values, both against a key composed - * of the group name prefixed with a constant prefix (default "spring.groups."). The group - * names are stored as a zset under "keys." + {@code [prefix]}. - * - * @author Dave Syer - */ -public class RedisMultiMetricRepository implements MultiMetricRepository { - - private static final String DEFAULT_METRICS_PREFIX = "spring.groups."; - - private final String prefix; - - private final String keys; - - private final BoundZSetOperations zSetOperations; - - private final RedisOperations redisOperations; - - public RedisMultiMetricRepository(RedisConnectionFactory redisConnectionFactory) { - this(redisConnectionFactory, DEFAULT_METRICS_PREFIX); - } - - public RedisMultiMetricRepository(RedisConnectionFactory redisConnectionFactory, - String prefix) { - Assert.notNull(redisConnectionFactory, "RedisConnectionFactory must not be null"); - this.redisOperations = RedisUtils.stringTemplate(redisConnectionFactory); - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - this.prefix = prefix; - this.keys = "keys." + this.prefix.substring(0, prefix.length() - 1); - this.zSetOperations = this.redisOperations.boundZSetOps(this.keys); - } - - @Override - public Iterable> findAll(String group) { - - BoundZSetOperations zSetOperations = this.redisOperations - .boundZSetOps(keyFor(group)); - - Set keys = zSetOperations.range(0, -1); - Iterator keysIt = keys.iterator(); - - List> result = new ArrayList<>(keys.size()); - List values = this.redisOperations.opsForValue().multiGet(keys); - for (String v : values) { - String key = keysIt.next(); - result.add(deserialize(group, key, v, zSetOperations.score(key))); - } - return result; - - } - - @Override - public void set(String group, Collection> values) { - String groupKey = keyFor(group); - trackMembership(groupKey); - BoundZSetOperations zSetOperations = this.redisOperations - .boundZSetOps(groupKey); - for (Metric metric : values) { - String raw = serialize(metric); - String key = keyFor(metric.getName()); - zSetOperations.add(key, metric.getValue().doubleValue()); - this.redisOperations.opsForValue().set(key, raw); - } - } - - @Override - public void increment(String group, Delta delta) { - String groupKey = keyFor(group); - trackMembership(groupKey); - BoundZSetOperations zSetOperations = this.redisOperations - .boundZSetOps(groupKey); - String key = keyFor(delta.getName()); - double value = zSetOperations.incrementScore(key, delta.getValue().doubleValue()); - String raw = serialize( - new Metric<>(delta.getName(), value, delta.getTimestamp())); - this.redisOperations.opsForValue().set(key, raw); - } - - @Override - public Iterable groups() { - Set range = this.zSetOperations.range(0, -1); - Collection result = new ArrayList<>(); - for (String key : range) { - result.add(key.substring(this.prefix.length())); - } - return result; - } - - @Override - public long countGroups() { - return this.zSetOperations.size(); - } - - @Override - public void reset(String group) { - String groupKey = keyFor(group); - if (this.redisOperations.hasKey(groupKey)) { - BoundZSetOperations zSetOperations = this.redisOperations - .boundZSetOps(groupKey); - Set keys = zSetOperations.range(0, -1); - for (String key : keys) { - this.redisOperations.delete(key); - } - this.redisOperations.delete(groupKey); - } - this.zSetOperations.remove(groupKey); - } - - private Metric deserialize(String group, String redisKey, String v, Double value) { - Date timestamp = new Date(Long.valueOf(v)); - return new Metric<>(nameFor(redisKey), value, timestamp); - } - - private String serialize(Metric entity) { - return String.valueOf(entity.getTimestamp().getTime()); - } - - private String keyFor(String name) { - return this.prefix + name; - } - - private String nameFor(String redisKey) { - Assert.state(redisKey != null && redisKey.startsWith(this.prefix), - "Invalid key does not start with prefix: " + redisKey); - return redisKey.substring(this.prefix.length()); - } - - private void trackMembership(String redisKey) { - this.zSetOperations.incrementScore(redisKey, 0.0D); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisUtils.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisUtils.java deleted file mode 100644 index 44ddfe5518b4..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.metrics.repository.redis; - -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.serializer.GenericToStringSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; - -/** - * General Utils for working with Redis. - * - * @author Luke Taylor - */ -final class RedisUtils { - - private RedisUtils() { - } - - static RedisTemplate createRedisTemplate( - RedisConnectionFactory connectionFactory, Class valueClass) { - RedisTemplate redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new GenericToStringSerializer<>(valueClass)); - - // avoids proxy - redisTemplate.setExposeConnection(true); - - redisTemplate.setConnectionFactory(connectionFactory); - redisTemplate.afterPropertiesSet(); - return redisTemplate; - } - - static RedisOperations stringTemplate( - RedisConnectionFactory redisConnectionFactory) { - return new StringRedisTemplate(redisConnectionFactory); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/package-info.java deleted file mode 100644 index 2062da27fabd..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics Redis repository support. - * - * @see org.springframework.boot.actuate.metrics.repository.redis.RedisMetricRepository - */ -package org.springframework.boot.actuate.metrics.repository.redis; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepository.java deleted file mode 100644 index 6ecc54eb10c1..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepository.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.metrics.rich; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.util.SimpleInMemoryRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; - -/** - * In memory implementation of {@link MetricWriter} and {@link RichGaugeReader}. When you - * {@link MetricWriter#set(Metric) set} or {@link MetricWriter#increment(Delta) increment} - * a metric value it is used to update a {@link RichGauge}. Gauge values can then be read - * out using the reader operations. - * - * @author Dave Syer - * @author Andy Wilkinson - */ -public class InMemoryRichGaugeRepository implements RichGaugeRepository { - - private final SimpleInMemoryRepository repository = new SimpleInMemoryRepository<>(); - - @Override - public void increment(Delta delta) { - this.repository.update(delta.getName(), (current) -> { - double value = ((Number) delta.getValue()).doubleValue(); - if (current == null) { - return new RichGauge(delta.getName(), value); - } - current.set(current.getValue() + value); - return current; - }); - } - - @Override - public void set(Metric metric) { - final String name = metric.getName(); - final double value = metric.getValue().doubleValue(); - this.repository.update(name, (current) -> { - if (current == null) { - return new RichGauge(name, value); - } - current.set(value); - return current; - }); - } - - @Override - public void reset(String metricName) { - this.repository.remove(metricName); - } - - @Override - public RichGauge findOne(String metricName) { - return this.repository.findOne(metricName); - } - - @Override - public Iterable findAll() { - return this.repository.findAll(); - } - - @Override - public long count() { - return this.repository.count(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java deleted file mode 100644 index 66abf8b96e5b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.metrics.rich; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; - -/** - * A {@link RichGaugeReader} that works by reading metric values from a - * {@link MultiMetricRepository} where the group name is the RichGauge name. The format - * used matches that in the RichGaugeExporter, so this reader can be used on a store that - * has been populated using that exporter. - * - * @author Dave Syer - * @since 1.1.0 - */ -public class MultiMetricRichGaugeReader implements RichGaugeReader { - - private final MultiMetricRepository repository; - - public MultiMetricRichGaugeReader(MultiMetricRepository repository) { - this.repository = repository; - } - - @Override - public RichGauge findOne(String name) { - Iterable> metrics = this.repository.findAll(name); - double value = 0; - double average = 0.; - double alpha = -1.; - double min = 0.; - double max = 0.; - long count = 0; - for (Metric metric : metrics) { - if (metric.getName().endsWith(RichGauge.VAL)) { - value = metric.getValue().doubleValue(); - } - else if (metric.getName().endsWith(RichGauge.ALPHA)) { - alpha = metric.getValue().doubleValue(); - } - else if (metric.getName().endsWith(RichGauge.AVG)) { - average = metric.getValue().doubleValue(); - } - else if (metric.getName().endsWith(RichGauge.MIN)) { - min = metric.getValue().doubleValue(); - } - else if (metric.getName().endsWith(RichGauge.MAX)) { - max = metric.getValue().doubleValue(); - } - else if (metric.getName().endsWith(RichGauge.COUNT)) { - count = metric.getValue().longValue(); - } - } - return new RichGauge(name, value, alpha, average, max, min, count); - } - - @Override - public Iterable findAll() { - List result = new ArrayList<>(); - for (String name : this.repository.groups()) { - result.add(findOne(name)); - } - return result; - } - - @Override - public long count() { - return this.repository.countGroups(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGauge.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGauge.java deleted file mode 100644 index 564f44dea762..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGauge.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2012-2014 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.metrics.rich; - -import org.springframework.util.Assert; - -/** - * A gauge which stores the maximum, minimum and average in addition to the current value. - *

- * The value of the average will depend on whether a weight ('alpha') is set for the - * gauge. If it is unset, the average will contain a simple arithmetic mean. If a weight - * is set, an exponential moving average will be calculated as defined in this - * NIST - * document. - * - * @author Luke Taylor - */ -public final class RichGauge { - - /** - * The suffix for count gauges. - */ - public static final String COUNT = ".count"; - - /** - * The suffix for max gauges. - */ - public static final String MAX = ".max"; - - /** - * The suffix for min gauges. - */ - public static final String MIN = ".min"; - - /** - * The suffix for average value gauges. - */ - public static final String AVG = ".avg"; - - /** - * The suffix for alpha gauges. - */ - public static final String ALPHA = ".alpha"; - - /** - * The suffix for value gauges. - */ - public static final String VAL = ".val"; - - private final String name; - - private double value; - - private double average; - - private double max; - - private double min; - - private long count; - - private double alpha; - - /** - * Creates an "empty" gauge. The average, max and min will be zero, but this initial - * value will not be included after the first value has been set on the gauge. - * @param name the name under which the gauge will be stored. - */ - public RichGauge(String name) { - this(name, 0.0); - this.count = 0; - } - - public RichGauge(String name, double value) { - Assert.notNull(name, "The gauge name cannot be null or empty"); - this.name = name; - this.value = value; - this.average = this.value; - this.min = this.value; - this.max = this.value; - this.alpha = -1.0; - this.count = 1; - } - - public RichGauge(String name, double value, double alpha, double mean, double max, - double min, long count) { - this.name = name; - this.value = value; - this.alpha = alpha; - this.average = mean; - this.max = max; - this.min = min; - this.count = count; - } - - /** - * Return the name of the gauge. - * @return the name - */ - public String getName() { - return this.name; - } - - /** - * Return the current value of the gauge. - * @return the value - */ - public double getValue() { - return this.value; - } - - /** - * Return either an exponential weighted moving average or a simple mean, - * respectively, depending on whether the weight 'alpha' has been set for this gauge. - * @return The average over all the accumulated values - */ - public double getAverage() { - return this.average; - } - - /** - * Return the maximum value of the gauge. - * @return the maximum value - */ - public double getMax() { - return this.max; - } - - /** - * Return the minimum value of the gauge. - * @return the minimum value - */ - public double getMin() { - return this.min; - } - - /** - * Return the number of times the value has been set. - * @return the value set count - */ - public long getCount() { - return this.count; - } - - /** - * Return the smoothing constant value. - * @return the alpha smoothing value - */ - public double getAlpha() { - return this.alpha; - } - - public RichGauge setAlpha(double alpha) { - Assert.isTrue(alpha == -1 || (alpha > 0.0 && alpha < 1.0), - "Smoothing constant must be between 0 and 1, or -1 to use arithmetic mean"); - this.alpha = alpha; - return this; - } - - RichGauge set(double value) { - if (this.count == 0) { - this.max = value; - this.min = value; - } - else if (value > this.max) { - this.max = value; - } - else if (value < this.min) { - this.min = value; - } - - if (this.alpha > 0.0 && this.count > 0) { - this.average = this.alpha * this.value + (1 - this.alpha) * this.average; - } - else { - double sum = this.average * this.count; - sum += value; - this.average = sum / (this.count + 1); - } - this.count++; - this.value = value; - return this; - } - - RichGauge reset() { - this.value = 0.0; - this.max = 0.0; - this.min = 0.0; - this.average = 0.0; - this.count = 0; - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - RichGauge richGauge = (RichGauge) o; - - if (!this.name.equals(richGauge.name)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return this.name.hashCode(); - } - - @Override - public String toString() { - return "Gauge [name = " + this.name + ", value = " + this.value + ", alpha = " - + this.alpha + ", average = " + this.average + ", max = " + this.max - + ", min = " + this.min + ", count = " + this.count + "]"; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeReader.java deleted file mode 100644 index 34d608b759b0..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeReader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2013 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.metrics.rich; - -/** - * A basic set of read operations for {@link RichGauge} instances. - * - * @author Dave Syer - */ -public interface RichGaugeReader { - - /** - * Find a single instance of a rich gauge by name. - * @param name the name of the gauge - * @return a rich gauge value - */ - RichGauge findOne(String name); - - /** - * Find all instances of rich gauge known to this reader. - * @return all instances known to this reader - */ - Iterable findAll(); - - /** - * Return the number of gauge values available. - * @return the number of values - */ - long count(); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeRepository.java deleted file mode 100644 index 00da0108e470..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/RichGaugeRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2012-2013 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.metrics.rich; - -import org.springframework.boot.actuate.metrics.writer.MetricWriter; - -/** - * Convenient combination of reader and writer concerns for {@link RichGauge} instances. - * - * @author Dave Syer - */ -public interface RichGaugeRepository extends RichGaugeReader, MetricWriter { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/package-info.java deleted file mode 100644 index 85e92b4db21e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics rich gauge support. - * - * @see org.springframework.boot.actuate.metrics.rich.RichGauge - */ -package org.springframework.boot.actuate.metrics.rich; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriter.java deleted file mode 100644 index d4cc7703bde1..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.metrics.statsd; - -import java.io.Closeable; - -import com.timgroup.statsd.NonBlockingStatsDClient; -import com.timgroup.statsd.StatsDClient; -import com.timgroup.statsd.StatsDClientErrorHandler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * A {@link MetricWriter} that pushes data to statsd. Statsd has the concept of counters - * and gauges, but only supports gauges with data type Long, so values will be truncated - * towards zero. Metrics whose name contains "timer." (but not "gauge." or "counter.") - * will be treated as execution times (in statsd terms). Anything incremented is treated - * as a counter, and anything with a snapshot value in {@link #set(Metric)} is treated as - * a gauge. - * - * @author Dave Syer - * @author OdĂ­n del RĂ­o - * @since 1.3.0 - */ -public class StatsdMetricWriter implements MetricWriter, Closeable { - - private static final Log logger = LogFactory.getLog(StatsdMetricWriter.class); - - private final StatsDClient client; - - /** - * Create a new writer instance with the given parameters. - * @param host the hostname for the statsd server - * @param port the port for the statsd server - */ - public StatsdMetricWriter(String host, int port) { - this(null, host, port); - } - - /** - * Create a new writer with the given parameters. - * @param prefix the prefix to apply to all metric names (can be null) - * @param host the hostname for the statsd server - * @param port the port for the statsd server - */ - public StatsdMetricWriter(String prefix, String host, int port) { - this(new NonBlockingStatsDClient(trimPrefix(prefix), host, port, - new LoggingStatsdErrorHandler())); - } - - /** - * Create a new writer with the given client. - * @param client StatsD client to write metrics with - */ - public StatsdMetricWriter(StatsDClient client) { - Assert.notNull(client, "Client must not be null"); - this.client = client; - } - - private static String trimPrefix(String prefix) { - String trimmedPrefix = StringUtils.hasText(prefix) ? prefix : null; - while (trimmedPrefix != null && trimmedPrefix.endsWith(".")) { - trimmedPrefix = trimmedPrefix.substring(0, trimmedPrefix.length() - 1); - } - - return trimmedPrefix; - } - - @Override - public void increment(Delta delta) { - this.client.count(sanitizeMetricName(delta.getName()), - delta.getValue().longValue()); - } - - @Override - public void set(Metric value) { - String name = sanitizeMetricName(value.getName()); - if (name.contains("timer.") && !name.contains("gauge.") - && !name.contains("counter.")) { - this.client.recordExecutionTime(name, value.getValue().longValue()); - } - else { - if (name.contains("counter.")) { - this.client.count(name, value.getValue().longValue()); - } - else { - this.client.gauge(name, value.getValue().doubleValue()); - } - } - } - - @Override - public void reset(String name) { - // Not implemented - } - - @Override - public void close() { - this.client.stop(); - } - - /** - * Sanitize the metric name if necessary. - * @param name the metric name - * @return the sanitized metric name - */ - private String sanitizeMetricName(String name) { - return name.replace(":", "-"); - } - - private static final class LoggingStatsdErrorHandler - implements StatsDClientErrorHandler { - - @Override - public void handle(Exception e) { - logger.debug("Failed to write metric. Exception: " + e.getClass() - + ", message: " + e.getMessage()); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/package-info.java deleted file mode 100644 index 5346aec9c68e..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/statsd/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics integration with Statsd. - */ -package org.springframework.boot.actuate.metrics.statsd; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepository.java deleted file mode 100644 index 69f536111dee..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepository.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.metrics.util; - -import java.util.ArrayList; -import java.util.NavigableMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; - -/** - * Repository utility that stores stuff in memory with period-separated String keys. - * - * @param the type to store - * @author Dave Syer - * @author Andy Wilkinson - */ -public class SimpleInMemoryRepository { - - private ConcurrentNavigableMap values = new ConcurrentSkipListMap<>(); - - private final ConcurrentMap locks = new ConcurrentHashMap<>(); - - public T update(String name, Callback callback) { - Object lock = getLock(name); - synchronized (lock) { - T current = this.values.get(name); - T value = callback.modify(current); - this.values.put(name, value); - return value; - } - } - - private Object getLock(String name) { - Object lock = this.locks.get(name); - if (lock == null) { - Object newLock = new Object(); - lock = this.locks.putIfAbsent(name, newLock); - if (lock == null) { - lock = newLock; - } - } - return lock; - } - - public void set(String name, T value) { - this.values.put(name, value); - } - - public long count() { - return this.values.size(); - } - - public void remove(String name) { - this.values.remove(name); - } - - public T findOne(String name) { - return this.values.get(name); - } - - public Iterable findAll() { - return new ArrayList<>(this.values.values()); - } - - public Iterable findAllWithPrefix(String prefix) { - if (prefix.endsWith(".*")) { - prefix = prefix.substring(0, prefix.length() - 1); - } - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - return new ArrayList<>( - this.values.subMap(prefix, false, prefix + "~", true).values()); - } - - public void setValues(ConcurrentNavigableMap values) { - this.values = values; - } - - protected NavigableMap getValues() { - return this.values; - } - - /** - * Callback used to update a value. - * - * @param the value type - */ - @FunctionalInterface - public interface Callback { - - /** - * Modify an existing value. - * @param current the value to modify - * @return the updated value - */ - T modify(T current); - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/package-info.java deleted file mode 100644 index 67297dd3c8c3..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/util/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics utility classes. - * - * @see org.springframework.boot.actuate.metrics.rich.RichGauge - */ -package org.springframework.boot.actuate.metrics.util; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilter.java deleted file mode 100644 index 978172589191..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilter.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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.metrics.web.servlet; - -import java.io.IOException; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Pattern; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatus.Series; -import org.springframework.util.StopWatch; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.util.UrlPathHelper; - -/** - * Filter that counts requests and measures processing times. - * - * @author Dave Syer - * @author Andy Wilkinson - * @since 2.0.0 - */ -@Order(Ordered.HIGHEST_PRECEDENCE) -public final class MetricsFilter extends OncePerRequestFilter { - - private static final String ATTRIBUTE_STOP_WATCH = MetricsFilter.class.getName() - + ".StopWatch"; - - private static final int UNDEFINED_HTTP_STATUS = 999; - - private static final String UNKNOWN_PATH_SUFFIX = "/unmapped"; - - private static final Log logger = LogFactory.getLog(MetricsFilter.class); - - private final CounterService counterService; - - private final GaugeService gaugeService; - - private final Set counterSubmissions; - - private final Set gaugeSubmissions; - - private static final Set STATUS_REPLACERS; - - static { - Set replacements = new LinkedHashSet<>(); - replacements.add(new PatternReplacer("\\{(.+?)(?::.+)?\\}", 0, "-$1-")); - replacements.add(new PatternReplacer("**", Pattern.LITERAL, "-star-star-")); - replacements.add(new PatternReplacer("*", Pattern.LITERAL, "-star-")); - replacements.add(new PatternReplacer("/-", Pattern.LITERAL, "/")); - replacements.add(new PatternReplacer("-/", Pattern.LITERAL, "/")); - STATUS_REPLACERS = Collections.unmodifiableSet(replacements); - } - - private static final Set KEY_REPLACERS; - - static { - Set replacements = new LinkedHashSet<>(); - replacements.add(new PatternReplacer("/", Pattern.LITERAL, ".")); - replacements.add(new PatternReplacer("..", Pattern.LITERAL, ".")); - KEY_REPLACERS = Collections.unmodifiableSet(replacements); - } - - public MetricsFilter(CounterService counterService, GaugeService gaugeService, - Set counterSubmissions, - Set gaugeSubmissions) { - this.counterService = counterService; - this.gaugeService = gaugeService; - this.counterSubmissions = counterSubmissions; - this.gaugeSubmissions = gaugeSubmissions; - } - - @Override - protected boolean shouldNotFilterAsyncDispatch() { - return false; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws ServletException, IOException { - StopWatch stopWatch = createStopWatchIfNecessary(request); - String path = new UrlPathHelper().getPathWithinApplication(request); - int status = HttpStatus.INTERNAL_SERVER_ERROR.value(); - try { - chain.doFilter(request, response); - status = getStatus(response); - } - finally { - if (!request.isAsyncStarted()) { - if (response.isCommitted()) { - status = getStatus(response); - } - stopWatch.stop(); - request.removeAttribute(ATTRIBUTE_STOP_WATCH); - recordMetrics(request, path, status, stopWatch.getTotalTimeMillis()); - } - } - } - - private StopWatch createStopWatchIfNecessary(HttpServletRequest request) { - StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH); - if (stopWatch == null) { - stopWatch = new StopWatch(); - stopWatch.start(); - request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch); - } - return stopWatch; - } - - private int getStatus(HttpServletResponse response) { - try { - return response.getStatus(); - } - catch (Exception ex) { - return UNDEFINED_HTTP_STATUS; - } - } - - private void recordMetrics(HttpServletRequest request, String path, int status, - long time) { - String suffix = determineMetricNameSuffix(request, path, status); - submitMetrics(MetricsFilterSubmission.MERGED, request, status, time, suffix); - submitMetrics(MetricsFilterSubmission.PER_HTTP_METHOD, request, status, time, - suffix); - } - - private String determineMetricNameSuffix(HttpServletRequest request, String path, - int status) { - Object bestMatchingPattern = request - .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); - if (bestMatchingPattern != null) { - return fixSpecialCharacters(bestMatchingPattern.toString()); - } - Series series = getSeries(status); - if (Series.CLIENT_ERROR.equals(series) || Series.SERVER_ERROR.equals(series) - || Series.REDIRECTION.equals(series)) { - return UNKNOWN_PATH_SUFFIX; - } - return path; - } - - private String fixSpecialCharacters(String value) { - String result = value; - for (PatternReplacer replacer : STATUS_REPLACERS) { - result = replacer.apply(result); - } - if (result.endsWith("-")) { - result = result.substring(0, result.length() - 1); - } - if (result.startsWith("-")) { - result = result.substring(1); - } - return result; - } - - private Series getSeries(int status) { - try { - return HttpStatus.valueOf(status).series(); - } - catch (Exception ex) { - return null; - } - } - - private void submitMetrics(MetricsFilterSubmission submission, - HttpServletRequest request, int status, long time, String suffix) { - String prefix = ""; - if (submission == MetricsFilterSubmission.PER_HTTP_METHOD) { - prefix = request.getMethod() + "."; - } - if (shouldSubmitToGauge(submission)) { - submitToGauge(getKey("response." + prefix + suffix), time); - } - if (shouldSubmitToCounter(submission)) { - incrementCounter(getKey("status." + prefix + status + suffix)); - } - } - - private boolean shouldSubmitToGauge(MetricsFilterSubmission submission) { - return shouldSubmit(this.gaugeSubmissions, submission); - } - - private boolean shouldSubmitToCounter(MetricsFilterSubmission submission) { - return shouldSubmit(this.counterSubmissions, submission); - } - - private boolean shouldSubmit(Set submissions, - MetricsFilterSubmission submission) { - return submissions != null && submissions.contains(submission); - } - - private String getKey(String string) { - // graphite compatible metric names - String key = string; - for (PatternReplacer replacer : KEY_REPLACERS) { - key = replacer.apply(key); - } - if (key.endsWith(".")) { - key = key + "root"; - } - if (key.startsWith("_")) { - key = key.substring(1); - } - return key; - } - - private void submitToGauge(String metricName, double value) { - try { - this.gaugeService.submit(metricName, value); - } - catch (Exception ex) { - logger.warn("Unable to submit gauge metric '" + metricName + "'", ex); - } - } - - private void incrementCounter(String metricName) { - try { - this.counterService.increment(metricName); - } - catch (Exception ex) { - logger.warn("Unable to submit counter metric '" + metricName + "'", ex); - } - } - - private static class PatternReplacer { - - private final Pattern pattern; - - private final String replacement; - - PatternReplacer(String regex, int flags, String replacement) { - this.pattern = Pattern.compile(regex, flags); - this.replacement = replacement; - } - - public String apply(String input) { - return this.pattern.matcher(input).replaceAll(this.replacement); - } - - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilterSubmission.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilterSubmission.java deleted file mode 100644 index 846ab20aba44..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/MetricsFilterSubmission.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.metrics.web.servlet; - -/** - * Submission types that can be made by the {@link MetricsFilter}. - * - * @author Phillip Webb - * @since 2.0.0 - */ -public enum MetricsFilterSubmission { - - /** - * Merge all HTTP methods into a single submission. - */ - MERGED, - - /** - * Group submissions by the HTTP method of the request. - */ - PER_HTTP_METHOD - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/package-info.java deleted file mode 100644 index 2acf65125819..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Metrics support for Servlet-based web applications. - */ -package org.springframework.boot.actuate.metrics.web.servlet; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CompositeMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CompositeMetricWriter.java deleted file mode 100644 index 18ef8f6ad9aa..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CompositeMetricWriter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.metrics.writer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Composite implementation of {@link MetricWriter} that just sends its input to all of - * the delegates that have been registered. - * - * @author Dave Syer - */ -public class CompositeMetricWriter implements MetricWriter, Iterable { - - private final List writers = new ArrayList<>(); - - public CompositeMetricWriter(MetricWriter... writers) { - Collections.addAll(this.writers, writers); - } - - public CompositeMetricWriter(List writers) { - this.writers.addAll(writers); - } - - @Override - public Iterator iterator() { - return this.writers.iterator(); - } - - @Override - public void increment(Delta delta) { - for (MetricWriter writer : this.writers) { - writer.increment(delta); - } - } - - @Override - public void set(Metric value) { - for (MetricWriter writer : this.writers) { - writer.set(value); - } - } - - @Override - public void reset(String metricName) { - for (MetricWriter writer : this.writers) { - writer.reset(metricName); - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CounterWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CounterWriter.java deleted file mode 100644 index 1f88829e840a..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/CounterWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -/** - * Simple writer for counters (metrics that increment). - * - * @author Dave Syer - * @since 1.3.0 - */ -public interface CounterWriter { - - /** - * Increment the value of a metric (or decrement if the delta is negative). The name - * of the delta is the name of the metric to increment. - * @param delta the amount to increment by - */ - void increment(Delta delta); - - /** - * Reset the value of a metric, usually to zero value. Implementations can discard the - * old values if desired, but may choose not to. This operation is optional (some - * implementations may not be able to fulfill the contract, in which case they should - * simply do nothing). - * @param metricName the name to reset - */ - void reset(String metricName); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterService.java deleted file mode 100644 index 2151705f76c8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.metrics.writer; - -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.boot.actuate.metrics.CounterService; - -/** - * Default implementation of {@link CounterService}. - * - * @author Dave Syer - */ -public class DefaultCounterService implements CounterService { - - private final MetricWriter writer; - - private final ConcurrentHashMap names = new ConcurrentHashMap<>(); - - /** - * Create a {@link DefaultCounterService} instance. - * @param writer the underlying writer used to manage metrics - */ - public DefaultCounterService(MetricWriter writer) { - this.writer = writer; - } - - @Override - public void increment(String metricName) { - this.writer.increment(new Delta<>(wrap(metricName), 1L)); - } - - @Override - public void decrement(String metricName) { - this.writer.increment(new Delta<>(wrap(metricName), -1L)); - } - - @Override - public void reset(String metricName) { - this.writer.reset(wrap(metricName)); - } - - private String wrap(String metricName) { - String cached = this.names.get(metricName); - if (cached != null) { - return cached; - } - if (metricName.startsWith("counter.") || metricName.startsWith("meter.")) { - return metricName; - } - String name = "counter." + metricName; - this.names.put(metricName, name); - return name; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeService.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeService.java deleted file mode 100644 index daecc2b97beb..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.metrics.writer; - -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Default implementation of {@link GaugeService}. - * - * @author Dave Syer - */ -public class DefaultGaugeService implements GaugeService { - - private final MetricWriter writer; - - private final ConcurrentHashMap names = new ConcurrentHashMap<>(); - - /** - * Create a {@link DefaultGaugeService} instance. - * @param writer the underlying writer used to manage metrics - */ - public DefaultGaugeService(MetricWriter writer) { - this.writer = writer; - } - - @Override - public void submit(String metricName, double value) { - this.writer.set(new Metric<>(wrap(metricName), value)); - } - - private String wrap(String metricName) { - String cached = this.names.get(metricName); - if (cached != null) { - return cached; - } - if (metricName.startsWith("gauge") || metricName.startsWith("histogram") - || metricName.startsWith("timer")) { - return metricName; - } - String name = "gauge." + metricName; - this.names.put(metricName, name); - return name; - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/Delta.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/Delta.java deleted file mode 100644 index 679fb2fe2336..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/Delta.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import java.util.Date; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * A value object representing an increment in a metric value (usually a counter). - * - * @param the value type - * @author Dave Syer - */ -public class Delta extends Metric { - - public Delta(String name, T value, Date timestamp) { - super(name, value, timestamp); - } - - public Delta(String name, T value) { - super(name, value); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/GaugeWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/GaugeWriter.java deleted file mode 100644 index 5cfa2d67d0b8..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/GaugeWriter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.metrics.writer; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Writer for gauge values (simple metric with a number value). - * - * @author Dave Syer - * @since 1.3.0 - */ -@FunctionalInterface -public interface GaugeWriter { - - /** - * Set the value of a metric. - * @param value the value - */ - void set(Metric value); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriter.java deleted file mode 100644 index 924667582dff..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriter.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.messaging.MessageChannel; - -/** - * A {@link MetricWriter} that publishes the metric updates on a {@link MessageChannel}. - * The messages have the writer input ({@link Delta} or {@link Metric}) as payload, and - * carry an additional header "metricName" with the name of the metric in it. - * - * @author Dave Syer - * @see MetricWriterMessageHandler - */ -public class MessageChannelMetricWriter implements MetricWriter { - - private final MessageChannel channel; - - public MessageChannelMetricWriter(MessageChannel channel) { - this.channel = channel; - } - - @Override - public void increment(Delta delta) { - this.channel.send(MetricMessage.forIncrement(delta)); - } - - @Override - public void set(Metric value) { - this.channel.send(MetricMessage.forSet(value)); - } - - @Override - public void reset(String metricName) { - this.channel.send(MetricMessage.forReset(metricName)); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricMessage.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricMessage.java deleted file mode 100644 index acbbca8d4407..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricMessage.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -/** - * A metric message sent via Spring Integration. - * - * @author Phillip Webb - */ -class MetricMessage { - - private static final String METRIC_NAME = "metricName"; - - private static final String DELETE = "delete"; - - private final Message message; - - MetricMessage(Message message) { - this.message = message; - } - - public boolean isReset() { - return DELETE.equals(getPayload()); - } - - public Object getPayload() { - return this.message.getPayload(); - } - - public String getMetricName() { - return this.message.getHeaders().get(METRIC_NAME, String.class); - } - - public static Message forIncrement(Delta delta) { - return forPayload(delta.getName(), delta); - } - - public static Message forSet(Metric value) { - return forPayload(value.getName(), value); - } - - public static Message forReset(String metricName) { - return forPayload(metricName, DELETE); - } - - private static Message forPayload(String metricName, Object payload) { - MessageBuilder builder = MessageBuilder.withPayload(payload); - builder.setHeader(METRIC_NAME, metricName); - return builder.build(); - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriter.java deleted file mode 100644 index 5756b36b9b7b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriter.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * Basic strategy for write operations on {@link Metric} data. - * - * @author Dave Syer - * @see GaugeWriter - * @see CounterWriter - */ -public interface MetricWriter extends GaugeWriter, CounterWriter { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriterMessageHandler.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriterMessageHandler.java deleted file mode 100644 index 212c6abf002b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/MetricWriterMessageHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.MessagingException; - -/** - * A {@link MessageHandler} that updates {@link Metric} values through a - * {@link MetricWriter}. - * - * @author Dave Syer - * @see MessageChannelMetricWriter - */ -public final class MetricWriterMessageHandler implements MessageHandler { - - private static final Log logger = LogFactory.getLog(MetricWriterMessageHandler.class); - - private final MetricWriter observer; - - public MetricWriterMessageHandler(MetricWriter observer) { - this.observer = observer; - } - - @Override - public void handleMessage(Message message) throws MessagingException { - handleMessage(new MetricMessage(message)); - } - - private void handleMessage(MetricMessage message) { - Object payload = message.getPayload(); - if (message.isReset()) { - this.observer.reset(message.getMetricName()); - } - else if (payload instanceof Delta) { - Delta value = (Delta) payload; - this.observer.increment(value); - } - else if (payload instanceof Metric) { - Metric value = (Metric) payload; - this.observer.set(value); - } - else { - if (logger.isWarnEnabled()) { - logger.warn("Unsupported metric payload " - + (payload == null ? "null" : payload.getClass().getName())); - } - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/PrefixMetricWriter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/PrefixMetricWriter.java deleted file mode 100644 index 4619e6a49db6..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/PrefixMetricWriter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.writer; - -import java.util.Collection; - -import org.springframework.boot.actuate.metrics.Metric; - -/** - * A writer for metrics that allows efficient storage of groups of metrics with a common - * name prefix (their group name). - * - * @author Dave Syer - * @since 1.1.0 - */ -public interface PrefixMetricWriter { - - /** - * Save some metric values and associate them with a group name. - * @param group the name of the group - * @param values the metric values to save - */ - void set(String group, Collection> values); - - /** - * Increment the value of a metric (or decrement if the delta is negative). The name - * of the metric to increment is {@code group + "." + delta.name}. - * @param group the name of the group - * @param delta the amount to increment by - */ - void increment(String group, Delta delta); - - /** - * Rest the values of all metrics in the group. Implementations may choose to discard - * the old values. - * @param group reset the whole group - */ - void reset(String group); - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/package-info.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/package-info.java deleted file mode 100644 index 2753bddf998b..000000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/writer/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** - * Support for writing metrics. - */ -package org.springframework.boot.actuate.metrics.writer; diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfigurationTests.java deleted file mode 100644 index 9a3593286ada..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/cache/CacheStatisticsAutoConfigurationTests.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * 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.cache; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; - -import javax.cache.Caching; -import javax.cache.configuration.MutableConfiguration; - -import com.github.benmanes.caffeine.cache.Caffeine; -import com.hazelcast.cache.HazelcastCachingProvider; -import com.hazelcast.config.Config; -import com.hazelcast.config.XmlConfigBuilder; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; -import com.hazelcast.spring.cache.HazelcastCacheManager; -import org.infinispan.manager.DefaultCacheManager; -import org.infinispan.manager.EmbeddedCacheManager; -import org.infinispan.spring.provider.SpringEmbeddedCacheManager; -import org.junit.After; -import org.junit.Test; - -import org.springframework.boot.actuate.cache.CacheStatistics; -import org.springframework.boot.actuate.cache.CacheStatisticsProvider; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.cache.caffeine.CaffeineCacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.springframework.cache.ehcache.EhCacheCacheManager; -import org.springframework.cache.ehcache.EhCacheManagerUtils; -import org.springframework.cache.jcache.JCacheCacheManager; -import org.springframework.cache.support.NoOpCacheManager; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.offset; - -/** - * Tests for {@link CacheStatisticsAutoConfiguration}. - * - * @author Stephane Nicoll - * @author EddĂș MelĂ©ndez - * @author Raja Kolli - */ -@SuppressWarnings({ "rawtypes", "unchecked" }) -public class CacheStatisticsAutoConfigurationTests { - - private AnnotationConfigApplicationContext context; - - private CacheManager cacheManager; - - @After - public void after() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void basicJCacheCacheStatistics() { - load(JCacheCacheConfig.class); - CacheStatisticsProvider provider = this.context - .getBean("jCacheCacheStatisticsProvider", CacheStatisticsProvider.class); - doTestCoreStatistics(provider, false); - } - - @Test - public void basicEhCacheCacheStatistics() { - load(EhCacheConfig.class); - CacheStatisticsProvider provider = this.context - .getBean("ehCacheCacheStatisticsProvider", CacheStatisticsProvider.class); - doTestCoreStatistics(provider, true); - } - - @Test - public void basicHazelcastCacheStatistics() { - load(HazelcastConfig.class); - CacheStatisticsProvider provider = this.context.getBean( - "hazelcastCacheStatisticsProvider", CacheStatisticsProvider.class); - doTestCoreStatistics(provider, true); - } - - @Test - public void basicInfinispanCacheStatistics() { - load(InfinispanConfig.class); - CacheStatisticsProvider provider = this.context.getBean( - "infinispanCacheStatisticsProvider", CacheStatisticsProvider.class); - doTestCoreStatistics(provider, true); - } - - @Test - public void baseCaffeineCacheStatistics() { - load(CaffeineCacheConfig.class); - CacheStatisticsProvider provider = this.context.getBean( - "caffeineCacheStatisticsProvider", CacheStatisticsProvider.class); - doTestCoreStatistics(provider, true); - } - - @Test - public void concurrentMapCacheStatistics() { - load(ConcurrentMapConfig.class); - CacheStatisticsProvider provider = this.context.getBean( - "concurrentMapCacheStatisticsProvider", CacheStatisticsProvider.class); - Cache books = getCache("books"); - CacheStatistics cacheStatistics = provider.getCacheStatistics(this.cacheManager, - books); - assertCoreStatistics(cacheStatistics, 0L, null, null); - getOrCreate(books, "a", "b", "b", "a", "a"); - CacheStatistics updatedCacheStatistics = provider - .getCacheStatistics(this.cacheManager, books); - assertCoreStatistics(updatedCacheStatistics, 2L, null, null); - } - - @Test - public void noOpCacheStatistics() { - load(NoOpCacheConfig.class); - CacheStatisticsProvider provider = this.context - .getBean("noOpCacheStatisticsProvider", CacheStatisticsProvider.class); - Cache books = getCache("books"); - CacheStatistics cacheStatistics = provider.getCacheStatistics(this.cacheManager, - books); - assertCoreStatistics(cacheStatistics, null, null, null); - getOrCreate(books, "a", "b", "b", "a", "a"); - CacheStatistics updatedCacheStatistics = provider - .getCacheStatistics(this.cacheManager, books); - assertCoreStatistics(updatedCacheStatistics, null, null, null); - } - - private void doTestCoreStatistics(CacheStatisticsProvider provider, - boolean supportSize) { - Cache books = getCache("books"); - CacheStatistics cacheStatistics = provider.getCacheStatistics(this.cacheManager, - books); - assertCoreStatistics(cacheStatistics, (supportSize ? 0L : null), null, null); - getOrCreate(books, "a", "b", "b", "a", "a", "a"); - CacheStatistics updatedCacheStatistics = provider - .getCacheStatistics(this.cacheManager, books); - assertCoreStatistics(updatedCacheStatistics, (supportSize ? 2L : null), 0.66D, - 0.33D); - } - - private void assertCoreStatistics(CacheStatistics metrics, Long size, Double hitRatio, - Double missRatio) { - assertThat(metrics).isNotNull(); - assertThat(metrics.getSize()).isEqualTo(size); - checkRatio("Wrong hit ratio for metrics " + metrics, hitRatio, - metrics.getHitRatio()); - checkRatio("Wrong miss ratio for metrics " + metrics, missRatio, - metrics.getMissRatio()); - } - - private void checkRatio(String message, Double expected, Double actual) { - if (expected == null || actual == null) { - assertThat(actual).as(message).isEqualTo(expected); - } - else { - assertThat(actual).as(message).isEqualTo(expected, offset(0.01D)); - } - } - - private void getOrCreate(Cache cache, String... ids) { - for (String id : ids) { - Cache.ValueWrapper wrapper = cache.get(id); - if (wrapper == null) { - cache.put(id, id); - } - } - } - - private Cache getCache(String cacheName) { - Cache cache = this.cacheManager.getCache(cacheName); - Assert.notNull(cache, "No cache with name '" + cacheName + "' found."); - return cache; - } - - private void load(Class... config) { - this.context = new AnnotationConfigApplicationContext(); - if (config.length > 0) { - this.context.register(config); - } - this.context.register(CacheStatisticsAutoConfiguration.class); - this.context.refresh(); - this.cacheManager = this.context.getBean(CacheManager.class); - } - - @Configuration - static class JCacheCacheConfig { - - @Bean - public JCacheCacheManager cacheManager() { - javax.cache.CacheManager cacheManager = jCacheCacheManager(); - return new JCacheCacheManager(cacheManager); - } - - @Bean - public javax.cache.CacheManager jCacheCacheManager() { - javax.cache.CacheManager cacheManager = Caching - .getCachingProvider(HazelcastCachingProvider.class.getName()) - .getCacheManager(); - MutableConfiguration config = new MutableConfiguration<>(); - config.setStatisticsEnabled(true); - cacheManager.createCache("books", config); - cacheManager.createCache("speakers", config); - return cacheManager; - } - - } - - @Configuration - static class EhCacheConfig { - - @Bean - public EhCacheCacheManager cacheManager() { - return new EhCacheCacheManager(ehCacheCacheManager()); - } - - @Bean - public net.sf.ehcache.CacheManager ehCacheCacheManager() { - return EhCacheManagerUtils - .buildCacheManager(new ClassPathResource("cache/test-ehcache.xml")); - } - - } - - @Configuration - static class HazelcastConfig { - - @Bean - public HazelcastCacheManager cacheManager() throws IOException { - return new HazelcastCacheManager(hazelcastInstance()); - } - - @Bean - public HazelcastInstance hazelcastInstance() throws IOException { - Resource resource = new ClassPathResource("cache/test-hazelcast.xml"); - Config cfg = new XmlConfigBuilder(resource.getURL()).build(); - return Hazelcast.newHazelcastInstance(cfg); - } - - } - - @Configuration - static class InfinispanConfig { - - @Bean - public SpringEmbeddedCacheManager cacheManager() throws IOException { - return new SpringEmbeddedCacheManager(embeddedCacheManager()); - } - - @Bean - public EmbeddedCacheManager embeddedCacheManager() throws IOException { - Resource resource = new ClassPathResource("cache/test-infinispan.xml"); - try (InputStream in = resource.getInputStream()) { - return new DefaultCacheManager(in); - } - } - - } - - @Configuration - static class ConcurrentMapConfig { - - @Bean - public ConcurrentMapCacheManager cacheManager() { - return new ConcurrentMapCacheManager("books", "speakers"); - } - - } - - @Configuration - static class NoOpCacheConfig { - - @Bean - public NoOpCacheManager cacheManager() { - return new NoOpCacheManager(); - } - - } - - @Configuration - static class CaffeineCacheConfig { - - @Bean - public CaffeineCacheManager cacheManager() { - CaffeineCacheManager cacheManager = new CaffeineCacheManager(); - cacheManager.setCaffeine(Caffeine.newBuilder().recordStats()); - cacheManager.setCacheNames(Arrays.asList("books", "speaker")); - return cacheManager; - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfigurationTests.java deleted file mode 100644 index c15932d4bf3a..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricExportAutoConfigurationTests.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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.metrics; - -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.TestPropertyValues; -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.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(); - TestPropertyValues.of("spring.metrics.export.statsd.host=localhost") - .applyTo(this.context); - 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 exporters = (Map) ReflectionTestUtils - .getField(schedulingConfigurer, "writers"); - assertThat(exporters).containsValue(statsdWriter); - - } - - @Configuration - public static class MessageChannelConfiguration { - - @Bean - public SubscribableChannel metricsChannel() { - return new FixedSubscriberChannel((message) -> { - }); - } - - } - - @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); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfigurationTests.java deleted file mode 100644 index ecffe6854a74..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricFilterAutoConfigurationTests.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * 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.metrics; - -import java.io.IOException; -import java.util.concurrent.CountDownLatch; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilter; -import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilterSubmission; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.stereotype.Component; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.async.DeferredResult; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.NestedServletException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.anyDouble; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willAnswer; -import static org.mockito.BDDMockito.willThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Tests for {@link MetricFilterAutoConfiguration}. - * - * @author Phillip Webb - * @author Andy Wilkinson - * @author Stephane Nicoll - */ -public class MetricFilterAutoConfigurationTests { - - @Test - public void defaultMetricFilterAutoConfigurationProperties() { - MetricFilterProperties properties = new MetricFilterProperties(); - assertThat(properties.getGaugeSubmissions()) - .containsExactly(MetricsFilterSubmission.MERGED); - assertThat(properties.getCounterSubmissions()) - .containsExactly(MetricsFilterSubmission.MERGED); - } - - @Test - public void recordsHttpInteractions() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - try { - Filter filter = context.getBean(Filter.class); - MockHttpServletRequest request = new MockHttpServletRequest("GET", - "/test/path"); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = mock(FilterChain.class); - willAnswer((invocation) -> { - response.setStatus(200); - return null; - }).given(chain).doFilter(request, response); - filter.doFilter(request, response, chain); - verify(context.getBean(CounterService.class)) - .increment("status.200.test.path"); - verify(context.getBean(GaugeService.class)).submit(eq("response.test.path"), - anyDouble()); - } - finally { - context.close(); - } - } - - @Test - public void recordsHttpInteractionsWithTemplateVariable() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/templateVarTest/foo")).andExpect(status().isOk()); - verify(context.getBean(CounterService.class)) - .increment("status.200.templateVarTest.someVariable"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.templateVarTest.someVariable"), anyDouble()); - context.close(); - } - - @Test - public void recordsHttpInteractionsWithRegexTemplateVariable() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/templateVarRegexTest/foo")).andExpect(status().isOk()); - verify(context.getBean(CounterService.class)) - .increment("status.200.templateVarRegexTest.someVariable"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.templateVarRegexTest.someVariable"), anyDouble()); - context.close(); - } - - @Test - public void recordsHttpInteractionsWithWildcardMapping() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/wildcardMapping/foo")).andExpect(status().isOk()); - verify(context.getBean(CounterService.class)) - .increment("status.200.wildcardMapping.star"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.wildcardMapping.star"), anyDouble()); - context.close(); - } - - @Test - public void recordsHttpInteractionsWithDoubleWildcardMapping() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/doubleWildcardMapping/foo/bar/baz")).andExpect(status().isOk()); - verify(context.getBean(CounterService.class)) - .increment("status.200.doubleWildcardMapping.star-star.baz"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.doubleWildcardMapping.star-star.baz"), anyDouble()); - context.close(); - } - - @Test - public void recordsKnown404HttpInteractionsAsSingleMetricWithPathAndTemplateVariable() - throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/knownPath/foo")).andExpect(status().isNotFound()); - verify(context.getBean(CounterService.class)) - .increment("status.404.knownPath.someVariable"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.knownPath.someVariable"), anyDouble()); - context.close(); - } - - @Test - public void records404HttpInteractionsAsSingleMetric() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/unknownPath/1")).andExpect(status().isNotFound()); - mvc.perform(get("/unknownPath/2")).andExpect(status().isNotFound()); - verify(context.getBean(CounterService.class), times(2)) - .increment("status.404.unmapped"); - verify(context.getBean(GaugeService.class), times(2)) - .submit(eq("response.unmapped"), anyDouble()); - context.close(); - } - - @Test - public void records302HttpInteractionsAsSingleMetric() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class, RedirectFilter.class); - MetricsFilter filter = context.getBean(MetricsFilter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).addFilter(context.getBean(RedirectFilter.class)) - .build(); - mvc.perform(get("/unknownPath/1")).andExpect(status().is3xxRedirection()); - mvc.perform(get("/unknownPath/2")).andExpect(status().is3xxRedirection()); - verify(context.getBean(CounterService.class), times(2)) - .increment("status.302.unmapped"); - verify(context.getBean(GaugeService.class), times(2)) - .submit(eq("response.unmapped"), anyDouble()); - context.close(); - } - - @Test - public void skipsFilterIfMissingServices() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - MetricFilterAutoConfiguration.class); - assertThat(context.getBeansOfType(Filter.class).size()).isEqualTo(0); - context.close(); - } - - @Test - public void skipsFilterIfPropertyDisabled() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("management.metrics.filter.enabled:false").applyTo(context); - context.register(Config.class, MetricFilterAutoConfiguration.class); - context.refresh(); - assertThat(context.getBeansOfType(Filter.class).size()).isEqualTo(0); - context.close(); - } - - @Test - public void controllerMethodThatThrowsUnhandledException() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - try { - mvc.perform(get("/unhandledException")) - .andExpect(status().isInternalServerError()); - } - catch (NestedServletException ex) { - // Expected - } - verify(context.getBean(CounterService.class)) - .increment("status.500.unhandledException"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.unhandledException"), anyDouble()); - context.close(); - } - - @Test - public void gaugeServiceThatThrows() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - GaugeService gaugeService = context.getBean(GaugeService.class); - willThrow(new IllegalStateException()).given(gaugeService).submit(anyString(), - anyDouble()); - Filter filter = context.getBean(Filter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter).build(); - mvc.perform(get("/templateVarTest/foo")).andExpect(status().isOk()); - verify(context.getBean(CounterService.class)) - .increment("status.200.templateVarTest.someVariable"); - verify(context.getBean(GaugeService.class)) - .submit(eq("response.templateVarTest.someVariable"), anyDouble()); - context.close(); - } - - @Test - public void correctlyRecordsMetricsForDeferredResultResponse() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - MetricsFilter filter = context.getBean(MetricsFilter.class); - CountDownLatch latch = new CountDownLatch(1); - MockMvc mvc = MockMvcBuilders - .standaloneSetup(new MetricFilterTestController(latch)).addFilter(filter) - .build(); - String attributeName = MetricsFilter.class.getName() + ".StopWatch"; - MvcResult result = mvc.perform(post("/create")).andExpect(status().isOk()) - .andExpect(request().asyncStarted()) - .andExpect(request().attribute(attributeName, is(notNullValue()))) - .andReturn(); - latch.countDown(); - mvc.perform(asyncDispatch(result)).andExpect(status().isCreated()) - .andExpect(request().attribute(attributeName, is(nullValue()))); - verify(context.getBean(CounterService.class)).increment("status.201.create"); - context.close(); - } - - @Test - public void correctlyRecordsMetricsForFailedDeferredResultResponse() - throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class); - MetricsFilter filter = context.getBean(MetricsFilter.class); - CountDownLatch latch = new CountDownLatch(1); - MockMvc mvc = MockMvcBuilders - .standaloneSetup(new MetricFilterTestController(latch)).addFilter(filter) - .build(); - String attributeName = MetricsFilter.class.getName() + ".StopWatch"; - MvcResult result = mvc.perform(post("/createFailure")).andExpect(status().isOk()) - .andExpect(request().asyncStarted()) - .andExpect(request().attribute(attributeName, is(notNullValue()))) - .andReturn(); - latch.countDown(); - try { - mvc.perform(asyncDispatch(result)); - fail(); - } - catch (Exception ex) { - assertThat(result.getRequest().getAttribute(attributeName)).isNull(); - verify(context.getBean(CounterService.class)) - .increment("status.500.createFailure"); - } - finally { - context.close(); - } - } - - @Test - public void records5xxxHttpInteractionsAsSingleMetric() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, MetricFilterAutoConfiguration.class, - ServiceUnavailableFilter.class); - MetricsFilter filter = context.getBean(MetricsFilter.class); - MockMvc mvc = MockMvcBuilders.standaloneSetup(new MetricFilterTestController()) - .addFilter(filter) - .addFilter(context.getBean(ServiceUnavailableFilter.class)).build(); - mvc.perform(get("/unknownPath/1")).andExpect(status().isServiceUnavailable()); - mvc.perform(get("/unknownPath/2")).andExpect(status().isServiceUnavailable()); - verify(context.getBean(CounterService.class), times(2)) - .increment("status.503.unmapped"); - verify(context.getBean(GaugeService.class), times(2)) - .submit(eq("response.unmapped"), anyDouble()); - context.close(); - } - - @Test - public void additionallyRecordsMetricsWithHttpMethodNameIfConfigured() - throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(Config.class, MetricFilterAutoConfiguration.class); - TestPropertyValues - .of("management.metrics.filter.gauge-submissions=merged,per-http-method", - "management.metrics.filter.counter-submissions=merged,per-http-method") - .applyTo(context); - context.refresh(); - Filter filter = context.getBean(Filter.class); - MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test/path"); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = mock(FilterChain.class); - willAnswer((invocation) -> { - response.setStatus(200); - return null; - }).given(chain).doFilter(request, response); - filter.doFilter(request, response, chain); - verify(context.getBean(GaugeService.class)).submit(eq("response.test.path"), - anyDouble()); - verify(context.getBean(GaugeService.class)).submit(eq("response.PUT.test.path"), - anyDouble()); - verify(context.getBean(CounterService.class)) - .increment(eq("status.200.test.path")); - verify(context.getBean(CounterService.class)) - .increment(eq("status.PUT.200.test.path")); - context.close(); - } - - @Test - public void doesNotRecordRolledUpMetricsIfConfigured() throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(Config.class, MetricFilterAutoConfiguration.class); - TestPropertyValues - .of("management.metrics.filter.gauge-submissions=", - "management.metrics.filter.counter-submissions=") - .applyTo(context); - context.refresh(); - Filter filter = context.getBean(Filter.class); - MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test/path"); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = mock(FilterChain.class); - willAnswer((invocation) -> { - response.setStatus(200); - return null; - }).given(chain).doFilter(request, response); - filter.doFilter(request, response, chain); - verify(context.getBean(GaugeService.class), never()).submit(anyString(), - anyDouble()); - verify(context.getBean(CounterService.class), never()).increment(anyString()); - context.close(); - } - - @Test - public void whenExceptionIsThrownResponseStatusIsUsedWhenResponseHasBeenCommitted() - throws Exception { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - try { - context.register(Config.class, MetricFilterAutoConfiguration.class); - context.refresh(); - Filter filter = context.getBean(Filter.class); - MockHttpServletRequest request = new MockHttpServletRequest("GET", - "/test/path"); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = mock(FilterChain.class); - willAnswer((invocation) -> { - response.setStatus(200); - response.setCommitted(true); - throw new IOException(); - }).given(chain).doFilter(request, response); - try { - filter.doFilter(request, response, chain); - fail(); - } - catch (IOException ex) { - // Continue - } - verify(context.getBean(CounterService.class)) - .increment(eq("status.200.test.path")); - } - finally { - context.close(); - } - } - - @Configuration - public static class Config { - - @Bean - public CounterService counterService() { - return mock(CounterService.class); - } - - @Bean - public GaugeService gaugeService() { - return mock(GaugeService.class); - } - - } - - @RestController - class MetricFilterTestController { - - private final CountDownLatch latch; - - MetricFilterTestController() { - this(null); - } - - MetricFilterTestController(CountDownLatch latch) { - this.latch = latch; - } - - @RequestMapping("templateVarTest/{someVariable}") - public String testTemplateVariableResolution(@PathVariable String someVariable) { - return someVariable; - } - - @RequestMapping("wildcardMapping/*") - public String testWildcardMapping() { - return "wildcard"; - } - - @RequestMapping("doubleWildcardMapping/**/baz") - public String testDoubleWildcardMapping() { - return "doubleWildcard"; - } - - @RequestMapping("templateVarRegexTest/{someVariable:[a-z]+}") - public String testTemplateVariableRegexResolution( - @PathVariable String someVariable) { - return someVariable; - } - - @RequestMapping("knownPath/{someVariable}") - @ResponseStatus(HttpStatus.NOT_FOUND) - @ResponseBody - public String testKnownPathWith404Response(@PathVariable String someVariable) { - return someVariable; - } - - @ResponseBody - @RequestMapping("unhandledException") - public String testException() { - throw new RuntimeException(); - } - - @RequestMapping("create") - public DeferredResult> create() { - final DeferredResult> result = new DeferredResult<>(); - new Thread(() -> { - try { - MetricFilterTestController.this.latch.await(); - result.setResult(new ResponseEntity<>("Done", HttpStatus.CREATED)); - } - catch (InterruptedException ex) { - } - }).start(); - return result; - } - - @RequestMapping("createFailure") - public DeferredResult> createFailure() { - final DeferredResult> result = new DeferredResult<>(); - new Thread(() -> { - try { - MetricFilterTestController.this.latch.await(); - result.setErrorResult(new Exception("It failed")); - } - catch (InterruptedException ex) { - } - }).start(); - return result; - } - - } - - @Component - @Order(0) - public static class RedirectFilter extends OncePerRequestFilter { - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws ServletException, IOException { - // send redirect before filter chain is executed, like Spring Security sending - // us back to a login page - response.sendRedirect("http://example.com"); - } - - } - - @Component - @Order(0) - public static class ServiceUnavailableFilter extends OncePerRequestFilter { - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws ServletException, IOException { - - response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value()); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfigurationTests.java deleted file mode 100644 index 54ba51d663bc..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricRepositoryAutoConfigurationTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.metrics; - -import com.codahale.metrics.Gauge; -import com.codahale.metrics.MetricRegistry; -import org.junit.After; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.buffer.BufferCounterService; -import org.springframework.boot.actuate.metrics.buffer.BufferGaugeService; -import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.reader.PrefixMetricReader; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link MetricRepositoryAutoConfiguration}. - * - * @author Phillip Webb - * @author Dave Syer - */ -public class MetricRepositoryAutoConfigurationTests { - - private AnnotationConfigApplicationContext context; - - @After - public void after() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void createServices() throws Exception { - this.context = new AnnotationConfigApplicationContext( - MetricRepositoryAutoConfiguration.class); - GaugeService gaugeService = this.context.getBean(BufferGaugeService.class); - assertThat(gaugeService).isNotNull(); - assertThat(this.context.getBean(BufferCounterService.class)).isNotNull(); - assertThat(this.context.getBean(PrefixMetricReader.class)).isNotNull(); - gaugeService.submit("foo", 2.7); - MetricReader bean = this.context.getBean(MetricReader.class); - assertThat(bean.findOne("gauge.foo").getValue()).isEqualTo(2.7); - } - - @Test - public void dropwizardInstalledIfPresent() { - this.context = new AnnotationConfigApplicationContext( - MetricsDropwizardAutoConfiguration.class, - MetricRepositoryAutoConfiguration.class); - GaugeService gaugeService = this.context.getBean(GaugeService.class); - assertThat(gaugeService).isNotNull(); - gaugeService.submit("foo", 2.7); - DropwizardMetricServices exporter = this.context - .getBean(DropwizardMetricServices.class); - assertThat(exporter).isEqualTo(gaugeService); - MetricRegistry registry = this.context.getBean(MetricRegistry.class); - @SuppressWarnings("unchecked") - Gauge gauge = (Gauge) registry.getMetrics().get("gauge.foo"); - assertThat(gauge.getValue()).isEqualTo(new Double(2.7)); - } - - @Test - public void skipsIfBeansExist() throws Exception { - this.context = new AnnotationConfigApplicationContext(Config.class, - MetricRepositoryAutoConfiguration.class); - assertThat(this.context.getBeansOfType(BufferGaugeService.class)).isEmpty(); - assertThat(this.context.getBeansOfType(BufferCounterService.class)).isEmpty(); - } - - @Configuration - public static class Config { - - @Bean - public GaugeService gaugeService() { - return mock(GaugeService.class); - } - - @Bean - public CounterService counterService() { - return mock(CounterService.class); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfigurationTests.java deleted file mode 100644 index 6a9d39f3444f..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsDropwizardAutoConfigurationTests.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.metrics; - -import com.codahale.metrics.Reservoir; -import com.codahale.metrics.UniformReservoir; -import org.junit.After; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices; -import org.springframework.boot.actuate.metrics.dropwizard.ReservoirFactory; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MetricsDropwizardAutoConfiguration}. - * - * @author Lucas Saldanha - */ -public class MetricsDropwizardAutoConfigurationTests { - - private AnnotationConfigApplicationContext context; - - @After - public void after() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void dropwizardWithoutCustomReservoirConfigured() { - this.context = new AnnotationConfigApplicationContext( - MetricsDropwizardAutoConfiguration.class); - DropwizardMetricServices dropwizardMetricServices = this.context - .getBean(DropwizardMetricServices.class); - ReservoirFactory reservoirFactory = (ReservoirFactory) ReflectionTestUtils - .getField(dropwizardMetricServices, "reservoirFactory"); - assertThat(reservoirFactory.getReservoir("test")).isNull(); - } - - @Test - public void dropwizardWithCustomReservoirConfigured() { - this.context = new AnnotationConfigApplicationContext( - MetricsDropwizardAutoConfiguration.class, Config.class); - DropwizardMetricServices dropwizardMetricServices = this.context - .getBean(DropwizardMetricServices.class); - ReservoirFactory reservoirFactory = (ReservoirFactory) ReflectionTestUtils - .getField(dropwizardMetricServices, "reservoirFactory"); - assertThat(reservoirFactory.getReservoir("test")) - .isInstanceOf(UniformReservoir.class); - } - - @Configuration - static class Config { - - @Bean - public ReservoirFactory reservoirFactory() { - return new UniformReservoirFactory(); - } - - } - - private static class UniformReservoirFactory implements ReservoirFactory { - - @Override - public Reservoir getReservoir(String name) { - return new UniformReservoir(); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfigurationTests.java deleted file mode 100644 index ac9d1bb04333..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PublicMetricsAutoConfigurationTests.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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.metrics; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import com.zaxxer.hikari.HikariDataSource; -import org.apache.commons.dbcp2.BasicDataSource; -import org.junit.After; -import org.junit.Test; - -import org.springframework.boot.actuate.autoconfigure.cache.CacheStatisticsAutoConfiguration; -import org.springframework.boot.actuate.endpoint.CachePublicMetrics; -import org.springframework.boot.actuate.endpoint.DataSourcePublicMetrics; -import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; -import org.springframework.boot.actuate.endpoint.PublicMetrics; -import org.springframework.boot.actuate.endpoint.RichGaugeReaderPublicMetrics; -import org.springframework.boot.actuate.endpoint.SystemPublicMetrics; -import org.springframework.boot.actuate.endpoint.TomcatPublicMetrics; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.rich.RichGauge; -import org.springframework.boot.actuate.metrics.rich.RichGaugeReader; -import org.springframework.boot.actuate.servlet.MockServletWebServerFactory; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; -import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.annotation.Order; -import org.springframework.jdbc.core.ConnectionCallback; -import org.springframework.jdbc.core.JdbcTemplate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link PublicMetricsAutoConfiguration}. - * - * @author Stephane Nicoll - * @author Dave Syer - * @author Phillip Webb - */ -public class PublicMetricsAutoConfigurationTests { - - private ConfigurableApplicationContext context; - - @After - public void after() { - if (this.context != null) { - this.context.close(); - } - } - - @Test - public void systemPublicMetrics() throws Exception { - load(); - assertThat(this.context.getBeansOfType(SystemPublicMetrics.class)).hasSize(1); - } - - @Test - public void metricReaderPublicMetrics() throws Exception { - load(); - assertThat(this.context.getBeansOfType(MetricReaderPublicMetrics.class)) - .hasSize(2); - } - - @Test - public void richGaugePublicMetrics() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( - RichGaugeReaderConfig.class, MetricRepositoryAutoConfiguration.class, - PublicMetricsAutoConfiguration.class); - RichGaugeReader richGaugeReader = context.getBean(RichGaugeReader.class); - assertThat(richGaugeReader).isNotNull(); - given(richGaugeReader.findAll()) - .willReturn(Collections.singletonList(new RichGauge("bar", 3.7d))); - RichGaugeReaderPublicMetrics publicMetrics = context - .getBean(RichGaugeReaderPublicMetrics.class); - assertThat(publicMetrics).isNotNull(); - Collection> metrics = publicMetrics.metrics(); - assertThat(metrics).isNotNull(); - assertThat(6).isEqualTo(metrics.size()); - assertHasMetric(metrics, new Metric<>("bar.val", 3.7d)); - assertHasMetric(metrics, new Metric<>("bar.avg", 3.7d)); - assertHasMetric(metrics, new Metric<>("bar.min", 3.7d)); - assertHasMetric(metrics, new Metric<>("bar.max", 3.7d)); - assertHasMetric(metrics, new Metric<>("bar.alpha", -1.d)); - assertHasMetric(metrics, new Metric<>("bar.count", 1L)); - context.close(); - } - - @Test - public void noDataSource() { - load(); - assertThat(this.context.getBeansOfType(DataSourcePublicMetrics.class)).isEmpty(); - } - - @Test - public void autoDataSource() throws SQLException { - load(DataSourceAutoConfiguration.class); - PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); - this.context.getBean(DataSource.class).getConnection().close(); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "datasource.primary.active", "datasource.primary.usage"); - } - - @Test - public void multipleDataSources() { - load(MultipleDataSourcesConfig.class); - PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "datasource.tomcat.active", "datasource.tomcat.usage", - "datasource.commonsDbcp.active", "datasource.commonsDbcp.usage"); - // Hikari won't work unless a first connection has been retrieved - JdbcTemplate jdbcTemplate = new JdbcTemplate( - this.context.getBean("hikariDS", DataSource.class)); - jdbcTemplate.execute((ConnectionCallback) (connection) -> null); - Collection> anotherMetrics = bean.metrics(); - assertMetrics(anotherMetrics, "datasource.tomcat.active", - "datasource.tomcat.usage", "datasource.hikariDS.active", - "datasource.hikariDS.usage", "datasource.commonsDbcp.active", - "datasource.commonsDbcp.usage"); - } - - @Test - public void multipleDataSourcesWithPrimary() { - load(MultipleDataSourcesWithPrimaryConfig.class); - PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "datasource.primary.active", "datasource.primary.usage", - "datasource.commonsDbcp.active", "datasource.commonsDbcp.usage"); - } - - @Test - public void multipleDataSourcesWithCustomPrimary() { - load(MultipleDataSourcesWithCustomPrimaryConfig.class); - PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "datasource.primary.active", "datasource.primary.usage", - "datasource.dataSource.active", "datasource.dataSource.usage"); - } - - @Test - public void customPrefix() { - load(MultipleDataSourcesWithPrimaryConfig.class, - CustomDataSourcePublicMetrics.class); - PublicMetrics bean = this.context.getBean(DataSourcePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "ds.first.active", "ds.first.usage", "ds.second.active", - "ds.second.usage"); - } - - @Test - public void tomcatMetrics() throws Exception { - loadWeb(TomcatConfiguration.class); - assertThat(this.context.getBeansOfType(TomcatPublicMetrics.class)).hasSize(1); - } - - @Test - public void noCacheMetrics() { - load(); - assertThat(this.context.getBeansOfType(CachePublicMetrics.class)).isEmpty(); - } - - @Test - public void autoCacheManager() { - load(CacheConfiguration.class); - CachePublicMetrics bean = this.context.getBean(CachePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "cache.books.size", "cache.speakers.size"); - } - - @Test - public void multipleCacheManagers() { - load(MultipleCacheConfiguration.class); - CachePublicMetrics bean = this.context.getBean(CachePublicMetrics.class); - Collection> metrics = bean.metrics(); - assertMetrics(metrics, "cache.books.size", "cache.second_speakers.size", - "cache.first_speakers.size", "cache.users.size"); - } - - private void assertHasMetric(Collection> metrics, Metric metric) { - for (Metric m : metrics) { - if (m.getValue().equals(metric.getValue()) - && m.getName().equals(metric.getName())) { - return; - } - } - fail("Metric " + metric.toString() + " not found in " + metrics.toString()); - } - - private void assertMetrics(Collection> metrics, String... keys) { - Map content = new HashMap<>(); - for (Metric metric : metrics) { - content.put(metric.getName(), metric.getValue()); - } - for (String key : keys) { - assertThat(content).containsKey(key); - } - } - - private void loadWeb(Class... config) { - AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(); - if (config.length > 0) { - context.register(config); - } - context.register(DataSourcePoolMetadataProvidersConfiguration.class, - CacheStatisticsAutoConfiguration.class, - PublicMetricsAutoConfiguration.class, MockServletWebServerFactory.class); - context.refresh(); - this.context = context; - } - - private void load(Class... config) { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - if (config.length > 0) { - context.register(config); - } - context.register(DataSourcePoolMetadataProvidersConfiguration.class, - CacheStatisticsAutoConfiguration.class, - PublicMetricsAutoConfiguration.class); - context.refresh(); - this.context = context; - } - - @Configuration - static class MultipleDataSourcesConfig { - - @Bean - public DataSource tomcatDataSource() { - return InitializedBuilder.create() - .type(org.apache.tomcat.jdbc.pool.DataSource.class).build(); - } - - @Bean - public DataSource hikariDS() { - return InitializedBuilder.create().type(HikariDataSource.class).build(); - } - - @Bean - public DataSource commonsDbcpDataSource() { - return InitializedBuilder.create().type(BasicDataSource.class).build(); - } - - } - - @Configuration - static class MultipleDataSourcesWithPrimaryConfig { - - @Bean - @Primary - public DataSource myDataSource() { - return InitializedBuilder.create() - .type(org.apache.tomcat.jdbc.pool.DataSource.class).build(); - } - - @Bean - public DataSource commonsDbcpDataSource() { - return InitializedBuilder.create().type(BasicDataSource.class).build(); - } - - } - - @Configuration - static class MultipleDataSourcesWithCustomPrimaryConfig { - - @Bean - @Primary - public DataSource myDataSource() { - return InitializedBuilder.create() - .type(org.apache.tomcat.jdbc.pool.DataSource.class).build(); - } - - @Bean - public DataSource dataSource() { - return InitializedBuilder.create().type(BasicDataSource.class).build(); - } - - } - - @Configuration - static class CustomDataSourcePublicMetrics { - - @Bean - public DataSourcePublicMetrics myDataSourcePublicMetrics() { - return new DataSourcePublicMetrics() { - @Override - protected String createPrefix(String dataSourceName, - DataSource dataSource, boolean primary) { - return (primary ? "ds.first." : "ds.second"); - } - }; - } - - } - - @Configuration - static class RichGaugeReaderConfig { - - @Bean - public RichGaugeReader richGaugeReader() { - return mock(RichGaugeReader.class); - } - - } - - @Configuration - static class TomcatConfiguration { - - @Bean - public TomcatServletWebServerFactory webServerFactory() { - return new TomcatServletWebServerFactory(0); - } - - } - - @Configuration - static class CacheConfiguration { - - @Bean - public CacheManager cacheManager() { - return new ConcurrentMapCacheManager("books", "speakers"); - } - - } - - @Configuration - static class MultipleCacheConfiguration { - - @Bean - @Order(1) - public CacheManager first() { - return new ConcurrentMapCacheManager("books", "speakers"); - } - - @Bean - @Order(2) - public CacheManager second() { - return new ConcurrentMapCacheManager("users", "speakers"); - } - - } - - private static class InitializedBuilder { - - public static DataSourceBuilder create() { - return DataSourceBuilder.create() - .driverClassName("org.hsqldb.jdbc.JDBCDriver") - .url("jdbc:hsqldb:mem:test").username("sa"); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/CachePublicMetricsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/CachePublicMetricsTests.java deleted file mode 100644 index fbeaac45d1ff..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/CachePublicMetricsTests.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.boot.actuate.cache.CacheStatisticsProvider; -import org.springframework.boot.actuate.cache.CaffeineCacheStatisticsProvider; -import org.springframework.boot.actuate.cache.ConcurrentMapCacheStatisticsProvider; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCache; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.springframework.cache.support.SimpleCacheManager; -import org.springframework.cache.transaction.TransactionAwareCacheDecorator; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; - -/** - * Tests for {@link CachePublicMetrics} - * - * @author Stephane Nicoll - */ -public class CachePublicMetricsTests { - - private Map cacheManagers = new HashMap<>(); - - @Before - public void setup() { - this.cacheManagers.put("cacheManager", - new ConcurrentMapCacheManager("foo", "bar")); - } - - @Test - public void cacheMetricsWithMatchingProvider() { - CachePublicMetrics cpm = new CachePublicMetrics(this.cacheManagers, - providers(new ConcurrentMapCacheStatisticsProvider())); - Map metrics = metrics(cpm); - assertThat(metrics).containsOnly(entry("cache.foo.size", 0L), - entry("cache.bar.size", 0L)); - } - - @Test - public void cacheMetricsWithNoMatchingProvider() { - CachePublicMetrics cpm = new CachePublicMetrics(this.cacheManagers, - providers(new CaffeineCacheStatisticsProvider())); - Map metrics = metrics(cpm); - assertThat(metrics).isEmpty(); - } - - @Test - public void cacheMetricsWithMultipleCacheManagers() { - this.cacheManagers.put("anotherCacheManager", - new ConcurrentMapCacheManager("foo")); - CachePublicMetrics cpm = new CachePublicMetrics(this.cacheManagers, - providers(new ConcurrentMapCacheStatisticsProvider())); - Map metrics = metrics(cpm); - assertThat(metrics).containsOnly(entry("cache.cacheManager_foo.size", 0L), - entry("cache.bar.size", 0L), - entry("cache.anotherCacheManager_foo.size", 0L)); - } - - @Test - public void cacheMetricsWithTransactionAwareCacheDecorator() { - SimpleCacheManager cacheManager = new SimpleCacheManager(); - cacheManager.setCaches(Collections.singletonList( - new TransactionAwareCacheDecorator(new ConcurrentMapCache("foo")))); - cacheManager.afterPropertiesSet(); - this.cacheManagers.put("cacheManager", cacheManager); - CachePublicMetrics cpm = new CachePublicMetrics(this.cacheManagers, - providers(new ConcurrentMapCacheStatisticsProvider())); - Map metrics = metrics(cpm); - assertThat(metrics).containsOnly(entry("cache.foo.size", 0L)); - } - - private Map metrics(CachePublicMetrics cpm) { - Collection> metrics = cpm.metrics(); - assertThat(metrics).isNotNull(); - Map result = new HashMap<>(); - for (Metric metric : metrics) { - result.put(metric.getName(), metric.getValue()); - } - return result; - } - - private Collection> providers( - CacheStatisticsProvider... providers) { - return Arrays.asList(providers); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetricsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetricsTests.java deleted file mode 100644 index 1f6652811ce2..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricReaderPublicMetricsTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.endpoint; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.reader.MetricReader; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link MetricReaderPublicMetrics}. - * - * @author Phillip Webb - */ -public class MetricReaderPublicMetricsTests { - - @Test - public void exposesMetrics() { - List> metrics = new ArrayList<>(); - metrics.add(mock(Metric.class)); - metrics.add(mock(Metric.class)); - MetricReader reader = mock(MetricReader.class); - given(reader.findAll()).willReturn(metrics); - MetricReaderPublicMetrics publicMetrics = new MetricReaderPublicMetrics(reader); - assertThat(publicMetrics.metrics()).isEqualTo(metrics); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java deleted file mode 100644 index 041a852ccdae..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.core.Ordered; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MetricsEndpoint}. - * - * @author Phillip Webb - * @author Andy Wilkinson - */ -public class MetricsEndpointTests { - - private Metric metric1 = new Metric<>("a", 1); - - private Metric metric2 = new Metric<>("b", 2); - - private Metric metric3 = new Metric<>("c", 3); - - @Test - public void basicMetrics() throws Exception { - MetricsEndpoint endpoint = new MetricsEndpoint( - Collections.singletonList(() -> Arrays.asList(new Metric("a", 5), - new Metric("b", 4)))); - Map metrics = endpoint.metrics(null); - assertThat(metrics.get("a")).isEqualTo(5); - assertThat(metrics.get("b")).isEqualTo(4); - } - - @Test - public void metricsOrderingIsReflectedInOutput() { - List publicMetrics = Arrays.asList( - new TestPublicMetrics(2, this.metric2, this.metric2, this.metric3), - new TestPublicMetrics(1, this.metric1)); - Map metrics = new MetricsEndpoint(publicMetrics).metrics(null); - assertThat(metrics.keySet()).containsExactly("a", "b", "c"); - assertThat(metrics).hasSize(3); - } - - @Test - public void singleSelectedMetric() { - List publicMetrics = Arrays.asList( - new TestPublicMetrics(2, this.metric2, this.metric2, this.metric3), - new TestPublicMetrics(1, this.metric1)); - Map selected = new MetricsEndpoint(publicMetrics) - .metricNamed("a"); - assertThat(selected).hasSize(1); - assertThat(selected).containsEntry("a", 1); - } - - @Test - public void multipleSelectedMetrics() { - List publicMetrics = Arrays.asList( - new TestPublicMetrics(2, this.metric2, this.metric2, this.metric3), - new TestPublicMetrics(1, this.metric1)); - Map selected = new MetricsEndpoint(publicMetrics).metrics("[ab]"); - assertThat(selected).hasSize(2); - assertThat(selected).containsEntry("a", 1); - assertThat(selected).containsEntry("b", 2); - } - - @Test - public void noMetricMatchingName() { - List publicMetrics = Arrays.asList( - new TestPublicMetrics(2, this.metric2, this.metric2, this.metric3), - new TestPublicMetrics(1, this.metric1)); - assertThat(new MetricsEndpoint(publicMetrics).metricNamed("z")).isNull(); - } - - @Test - public void noMetricMatchingPattern() { - List publicMetrics = Arrays.asList( - new TestPublicMetrics(2, this.metric2, this.metric2, this.metric3), - new TestPublicMetrics(1, this.metric1)); - assertThat(new MetricsEndpoint(publicMetrics).metrics("[z]")).isEmpty(); - } - - private static class TestPublicMetrics implements PublicMetrics, Ordered { - - private final int order; - - private final List> metrics; - - TestPublicMetrics(int order, Metric... metrics) { - this.order = order; - this.metrics = Arrays.asList(metrics); - } - - @Override - public int getOrder() { - return this.order; - } - - @Override - public Collection> metrics() { - return this.metrics; - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetricsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetricsTests.java deleted file mode 100644 index 356b5d73340d..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/RichGaugeReaderPublicMetricsTests.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.rich.InMemoryRichGaugeRepository; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link RichGaugeReaderPublicMetrics}. - * - * @author Johannes Edmeier - */ -public class RichGaugeReaderPublicMetricsTests { - - @Test - public void testMetrics() throws Exception { - InMemoryRichGaugeRepository repository = new InMemoryRichGaugeRepository(); - - repository.set(new Metric<>("a", 0.d, new Date())); - repository.set(new Metric<>("a", 0.5d, new Date())); - - RichGaugeReaderPublicMetrics metrics = new RichGaugeReaderPublicMetrics( - repository); - - Map> results = new HashMap<>(); - for (Metric metric : metrics.metrics()) { - results.put(metric.getName(), metric); - } - assertThat(results.containsKey("a.val")).isTrue(); - assertThat(results.get("a.val").getValue().doubleValue()).isEqualTo(0.5d); - - assertThat(results.containsKey("a.avg")).isTrue(); - assertThat(results.get("a.avg").getValue().doubleValue()).isEqualTo(0.25d); - - assertThat(results.containsKey("a.min")).isTrue(); - assertThat(results.get("a.min").getValue().doubleValue()).isEqualTo(0.0d); - - assertThat(results.containsKey("a.max")).isTrue(); - assertThat(results.get("a.max").getValue().doubleValue()).isEqualTo(0.5d); - - assertThat(results.containsKey("a.count")).isTrue(); - assertThat(results.get("a.count").getValue().longValue()).isEqualTo(2L); - - assertThat(results.containsKey("a.alpha")).isTrue(); - assertThat(results.get("a.alpha").getValue().doubleValue()).isEqualTo(-1.d); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SystemPublicMetricsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SystemPublicMetricsTests.java deleted file mode 100644 index 085cb1c43b10..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SystemPublicMetricsTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.endpoint; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SystemPublicMetrics} - * - * @author Stephane Nicoll - */ -public class SystemPublicMetricsTests { - - @Test - public void testSystemMetrics() throws Exception { - SystemPublicMetrics publicMetrics = new SystemPublicMetrics(); - Map> results = new HashMap<>(); - for (Metric metric : publicMetrics.metrics()) { - results.put(metric.getName(), metric); - } - assertThat(results).containsKey("mem"); - assertThat(results).containsKey("mem.free"); - assertThat(results).containsKey("processors"); - assertThat(results).containsKey("uptime"); - assertThat(results).containsKey("systemload.average"); - assertThat(results).containsKey("heap.committed"); - assertThat(results).containsKey("heap.init"); - assertThat(results).containsKey("heap.used"); - assertThat(results).containsKey("heap"); - assertThat(results).containsKey("nonheap.committed"); - assertThat(results).containsKey("nonheap.init"); - assertThat(results).containsKey("nonheap.used"); - assertThat(results).containsKey("nonheap"); - assertThat(results).containsKey("threads.peak"); - assertThat(results).containsKey("threads.daemon"); - assertThat(results).containsKey("threads.totalStarted"); - assertThat(results).containsKey("threads"); - assertThat(results).containsKey("classes.loaded"); - assertThat(results).containsKey("classes.unloaded"); - assertThat(results).containsKey("classes"); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetricsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetricsTests.java deleted file mode 100644 index 9e0f31ee803b..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TomcatPublicMetricsTests.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.endpoint; - -import java.util.Iterator; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link TomcatPublicMetrics} - * - * @author Johannes Edmeier - * @author Phillip Webb - */ -public class TomcatPublicMetricsTests { - - @Test - public void tomcatMetrics() throws Exception { - try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext( - Config.class)) { - TomcatPublicMetrics tomcatMetrics = context - .getBean(TomcatPublicMetrics.class); - Iterator> metrics = tomcatMetrics.metrics().iterator(); - assertThat(metrics.next().getName()).isEqualTo("httpsessions.max"); - assertThat(metrics.next().getName()).isEqualTo("httpsessions.active"); - assertThat(metrics.hasNext()).isFalse(); - } - } - - @Configuration - static class Config { - - @Bean - public TomcatServletWebServerFactory webServerFactory() { - return new TomcatServletWebServerFactory(0); - } - - @Bean - public TomcatPublicMetrics metrics() { - return new TomcatPublicMetrics(); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/MetricsEndpointMvcIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/MetricsEndpointMvcIntegrationTests.java deleted file mode 100644 index 27d8f1fd6e6e..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/MetricsEndpointMvcIntegrationTests.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.endpoint.web; - -import java.util.Arrays; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.endpoint.MetricsEndpoint; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * Integration tests for {@link MetricsEndpoint} when exposed via Spring MVC - * - * @author Andy Wilkinson - * @author Sergei Egorov - */ -@RunWith(WebEndpointsRunner.class) -public class MetricsEndpointMvcIntegrationTests { - - private static WebTestClient client; - - @Test - public void home() { - client.get().uri("/application/metrics").exchange().expectStatus().isOk() - .expectBody().jsonPath("foo").isEqualTo(1); - } - - @Test - public void specificMetric() { - client.get().uri("/application/metrics/foo").exchange().expectStatus().isOk() - .expectBody().jsonPath("foo").isEqualTo(1); - } - - @Test - public void specificMetricWithDot() throws Exception { - client.get().uri("/application/metrics/group2.a").exchange().expectStatus().isOk() - .expectBody().jsonPath("$.length()").isEqualTo(1).jsonPath("['group2.a']") - .isEqualTo("1"); - } - - @Test - public void specificMetricWithNameThatCouldBeMistakenForAPathExtension() { - client.get().uri("/application/metrics/bar.png").exchange().expectStatus().isOk() - .expectBody().jsonPath("['bar.png']").isEqualTo(1); - } - - @Test - public void specificMetricThatDoesNotExist() throws Exception { - client.get().uri("/application/metrics/bar").exchange().expectStatus() - .isNotFound(); - } - - @Test - public void regexAll() throws Exception { - client.get().uri("/application/metrics?pattern=.*").exchange().expectStatus() - .isOk().expectBody().jsonPath("$.length()").isEqualTo(6).jsonPath("foo") - .isEqualTo(1).jsonPath("['bar.png']").isEqualTo(1) - .jsonPath("['group1.a']").isEqualTo(1).jsonPath("['group1.b']") - .isEqualTo(1).jsonPath("['group2.a']").isEqualTo(1).jsonPath("group2_a") - .isEqualTo(1); - } - - @Test - public void regexGroupDot() throws Exception { - client.get().uri("/application/metrics?pattern=group%5B0-9%5D%5C..*").exchange() - .expectStatus().isOk().expectBody().jsonPath("$.length()").isEqualTo(3) - .jsonPath("['group1.a']").isEqualTo(1).jsonPath("['group1.b']") - .isEqualTo(1).jsonPath("['group2.a']").isEqualTo(1); - } - - @Test - public void regexGroup1() throws Exception { - client.get().uri("/application/metrics?pattern=group1%5C..*").exchange() - .expectStatus().isOk().expectBody().jsonPath("['group1.a']").isEqualTo(1) - .jsonPath("['group1.b']").isEqualTo(1).jsonPath("$.length()") - .isEqualTo(2); - } - - @Configuration - static class TestConfiguration { - - @Bean - public MetricsEndpoint endpoint() { - return new MetricsEndpoint(() -> Arrays.asList(new Metric<>("foo", 1), - new Metric<>("bar.png", 1), new Metric<>("group1.a", 1), - new Metric<>("group1.b", 1), new Metric<>("group2.a", 1), - new Metric<>("group2_a", 1), new Metric("baz", null))); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/Iterables.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/Iterables.java deleted file mode 100644 index 6f9562365b95..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/Iterables.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.metrics; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author Dave Syer - */ -public abstract class Iterables { - - public static Collection collection(Iterable iterable) { - if (iterable instanceof Collection) { - return (Collection) iterable; - } - ArrayList list = new ArrayList<>(); - for (T t : iterable) { - list.add(t); - } - return list; - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReaderTests.java deleted file mode 100644 index 870fd9d4abc2..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/aggregate/AggregateMetricReaderTests.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.metrics.aggregate; - -import java.util.Date; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link AggregateMetricReader}. - * - * @author Dave Syer - */ -public class AggregateMetricReaderTests { - - private InMemoryMetricRepository source = new InMemoryMetricRepository(); - - private AggregateMetricReader reader = new AggregateMetricReader(this.source); - - @Test - public void writeAndReadDefaults() { - this.source.set(new Metric<>("foo.bar.spam", 2.3)); - assertThat(this.reader.findOne("aggregate.spam").getValue()).isEqualTo(2.3); - } - - @Test - public void defaultKeyPattern() { - this.source.set(new Metric<>("foo.bar.spam.bucket.wham", 2.3)); - assertThat(this.reader.findOne("aggregate.spam.bucket.wham").getValue()) - .isEqualTo(2.3); - } - - @Test - public void addKeyPattern() { - this.source.set(new Metric<>("foo.bar.spam.bucket.wham", 2.3)); - this.reader.setKeyPattern("d.d.k.d"); - assertThat(this.reader.findOne("aggregate.spam.wham").getValue()).isEqualTo(2.3); - } - - @Test - public void addPrefix() { - this.source.set(new Metric<>("foo.bar.spam.bucket.wham", 2.3)); - this.source.set(new Metric<>("off.bar.spam.bucket.wham", 2.4)); - this.reader.setPrefix("www"); - this.reader.setKeyPattern("k.d.k.d"); - assertThat(this.reader.findOne("www.foo.spam.wham").getValue()).isEqualTo(2.3); - assertThat(this.reader.count()).isEqualTo(2); - } - - @Test - public void writeAndReadExtraLong() { - this.source.set(new Metric<>("blee.foo.bar.spam", 2.3)); - this.reader.setKeyPattern("d.d.d.k"); - assertThat(this.reader.findOne("aggregate.spam").getValue()).isEqualTo(2.3); - } - - @Test - public void writeAndReadLatestValue() { - this.source.set(new Metric<>("foo.bar.spam", 2.3, new Date(100L))); - this.source.set(new Metric<>("oof.rab.spam", 2.4, new Date(0L))); - assertThat(this.reader.findOne("aggregate.spam").getValue()).isEqualTo(2.3); - } - - @Test - public void onlyPrefixed() { - this.source.set(new Metric<>("foo.bar.spam", 2.3)); - assertThat(this.reader.findOne("spam")).isNull(); - } - - @Test - public void incrementCounter() { - this.source.increment(new Delta<>("foo.bar.counter.spam", 2L)); - this.source.increment(new Delta<>("oof.rab.counter.spam", 3L)); - assertThat(this.reader.findOne("aggregate.counter.spam").getValue()) - .isEqualTo(5L); - } - - @Test - public void countGauges() { - this.source.set(new Metric<>("foo.bar.spam", 2.3)); - this.source.set(new Metric<>("oof.rab.spam", 2.4)); - assertThat(this.reader.count()).isEqualTo(1); - } - - @Test - public void countGaugesAndCounters() { - this.source.set(new Metric<>("foo.bar.spam", 2.3)); - this.source.set(new Metric<>("oof.rab.spam", 2.4)); - this.source.increment(new Delta<>("foo.bar.counter.spam", 2L)); - this.source.increment(new Delta<>("oof.rab.counter.spam", 3L)); - assertThat(this.reader.count()).isEqualTo(2); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeServiceSpeedTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeServiceSpeedTests.java deleted file mode 100644 index 7aa995718a83..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferGaugeServiceSpeedTests.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.DoubleAdder; -import java.util.concurrent.atomic.LongAdder; -import java.util.regex.Pattern; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.experimental.theories.DataPoints; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.util.StopWatch; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Speed tests for {@link BufferGaugeService}. - * - * @author Dave Syer - */ -@RunWith(Theories.class) -public class BufferGaugeServiceSpeedTests { - - @DataPoints - public static String[] values = new String[10]; - - public static String[] names = new String[] { "foo", "bar", "spam", "bucket" }; - - public static String[] sample = new String[1000]; - - private GaugeBuffers gauges = new GaugeBuffers(); - - private GaugeService service = new BufferGaugeService(this.gauges); - - private BufferMetricReader reader = new BufferMetricReader(new CounterBuffers(), - this.gauges); - - private static int threadCount = 2; - - private static final int number = Boolean.getBoolean("performance.test") ? 10000000 - : 1000000; - - private static StopWatch watch = new StopWatch("count"); - - private static int count; - - private static PrintWriter err; - - @BeforeClass - public static void prime() throws FileNotFoundException { - err = new NullPrintWriter(); - Random random = new Random(); - for (int i = 0; i < 1000; i++) { - sample[i] = names[random.nextInt(names.length)]; - } - } - - @AfterClass - public static void washup() { - System.err.println(watch); - } - - @Theory - public void raw(String input) throws Exception { - iterate("writeRaw"); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Rate(" + count + ")=" + rate + ", " + watch); - watch.start("readRaw" + count); - for (String name : names) { - this.gauges.forEach(Pattern.compile(name).asPredicate(), - (key, value) -> err.println(key + "=" + value)); - } - DoubleAdder total = new DoubleAdder(); - this.gauges.forEach(Pattern.compile(".*").asPredicate(), - (name, value) -> total.add(value.getValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(number * threadCount < total.longValue()).isTrue(); - } - - @Theory - public void reader(String input) throws Exception { - iterate("writeReader"); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Rate(" + count + ")=" + rate + ", " + watch); - watch.start("readReader" + count); - this.reader.findAll().forEach((metric) -> err.println(metric)); - LongAdder total = new LongAdder(); - this.reader.findAll().forEach((value) -> total.add(value.getValue().intValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(0 < total.longValue()).isTrue(); - } - - private void iterate(String taskName) throws Exception { - watch.start(taskName + count++); - ExecutorService pool = Executors.newFixedThreadPool(threadCount); - Runnable task = () -> { - for (int i = 0; i < number; i++) { - String name = sample[i % sample.length]; - BufferGaugeServiceSpeedTests.this.service.submit(name, count + i); - } - }; - Collection> futures = new HashSet<>(); - for (int i = 0; i < threadCount; i++) { - futures.add(pool.submit(task)); - } - for (Future future : futures) { - future.get(); - } - watch.stop(); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReaderTests.java deleted file mode 100644 index 1e3ce1cd38dc..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/BufferMetricReaderTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.buffer; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link BufferMetricReader}. - * - * @author Dave Syer - */ -public class BufferMetricReaderTests { - - private CounterBuffers counters = new CounterBuffers(); - - private GaugeBuffers gauges = new GaugeBuffers(); - - private BufferMetricReader reader = new BufferMetricReader(this.counters, - this.gauges); - - @Test - public void countReflectsNumberOfMetrics() { - this.gauges.set("foo", 1); - this.counters.increment("bar", 2); - assertThat(this.reader.count()).isEqualTo(2); - } - - @Test - public void findGauge() { - this.gauges.set("foo", 1); - assertThat(this.reader.findOne("foo")).isNotNull(); - assertThat(this.reader.count()).isEqualTo(1); - } - - @Test - public void findCounter() { - this.counters.increment("foo", 1); - assertThat(this.reader.findOne("foo")).isNotNull(); - assertThat(this.reader.count()).isEqualTo(1); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffersTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffersTests.java deleted file mode 100644 index 72b4a0f07f5e..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterBuffersTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.metrics.buffer; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link CounterBuffers}. - * - * @author Dave Syer - */ -public class CounterBuffersTests { - - private CounterBuffers buffers = new CounterBuffers(); - - private long value; - - @Test - public void inAndOut() { - this.buffers.increment("foo", 2); - this.buffers.doWith("foo", - (buffer) -> CounterBuffersTests.this.value = buffer.getValue()); - assertThat(this.value).isEqualTo(2); - } - - @Test - public void getNonExistent() { - this.buffers.doWith("foo", - (buffer) -> CounterBuffersTests.this.value = buffer.getValue()); - assertThat(this.value).isEqualTo(0); - } - - @Test - public void findNonExistent() { - assertThat(this.buffers.find("foo")).isNull(); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterServiceSpeedTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterServiceSpeedTests.java deleted file mode 100644 index e3e93546495e..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/CounterServiceSpeedTests.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.LongAdder; -import java.util.regex.Pattern; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.experimental.theories.DataPoints; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.util.StopWatch; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Speed tests for {@link CounterService}. - * - * @author Dave Syer - */ -@RunWith(Theories.class) -public class CounterServiceSpeedTests { - - @DataPoints - public static String[] values = new String[10]; - - public static String[] names = new String[] { "foo", "bar", "spam", "bucket" }; - - public static String[] sample = new String[1000]; - - private CounterBuffers counters = new CounterBuffers(); - - private CounterService service = new BufferCounterService(this.counters); - - private BufferMetricReader reader = new BufferMetricReader(this.counters, - new GaugeBuffers()); - - private static int threadCount = 2; - - private static final int number = Boolean.getBoolean("performance.test") ? 10000000 - : 1000000; - - private static StopWatch watch = new StopWatch("count"); - - private static int count; - - private static PrintWriter err; - - @BeforeClass - public static void prime() throws FileNotFoundException { - err = new NullPrintWriter(); - Random random = new Random(); - for (int i = 0; i < 1000; i++) { - sample[i] = names[random.nextInt(names.length)]; - } - } - - @AfterClass - public static void washup() { - System.err.println(watch); - } - - @Theory - public void raw(String input) throws Exception { - iterate("writeRaw"); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Rate(" + count + ")=" + rate + ", " + watch); - watch.start("readRaw" + count); - for (String name : names) { - this.counters.forEach(Pattern.compile(name).asPredicate(), - (key, value) -> err.println(key + "=" + value)); - } - LongAdder total = new LongAdder(); - this.counters.forEach(Pattern.compile(".*").asPredicate(), - (name, value) -> total.add(value.getValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(total.longValue()).isEqualTo(number * threadCount); - } - - @Theory - public void reader(String input) throws Exception { - iterate("writeReader"); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Rate(" + count + ")=" + rate + ", " + watch); - watch.start("readReader" + count); - this.reader.findAll().forEach(err::println); - LongAdder total = new LongAdder(); - this.reader.findAll().forEach((value) -> total.add(value.getValue().intValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(total.longValue()).isEqualTo(number * threadCount); - } - - private void iterate(String taskName) throws Exception { - watch.start(taskName + count++); - ExecutorService pool = Executors.newFixedThreadPool(threadCount); - Runnable task = () -> { - for (int i = 0; i < number; i++) { - String name = sample[i % sample.length]; - CounterServiceSpeedTests.this.service.increment(name); - } - }; - Collection> futures = new HashSet<>(); - for (int i = 0; i < threadCount; i++) { - futures.add(pool.submit(task)); - } - for (Future future : futures) { - future.get(); - } - watch.stop(); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultCounterServiceSpeedTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultCounterServiceSpeedTests.java deleted file mode 100644 index d4e6b37f812b..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultCounterServiceSpeedTests.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.LongAdder; - -import org.junit.BeforeClass; -import org.junit.experimental.theories.DataPoints; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.boot.actuate.metrics.writer.DefaultCounterService; -import org.springframework.util.StopWatch; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Speed tests for {@link DefaultCounterService}. - * - * @author Dave Syer - */ -@RunWith(Theories.class) -public class DefaultCounterServiceSpeedTests { - - @DataPoints - public static String[] values = new String[10]; - - public static String[] names = new String[] { "foo", "bar", "spam", "bucket" }; - - public static String[] sample = new String[1000]; - - private InMemoryMetricRepository repository = new InMemoryMetricRepository(); - - private CounterService counterService = new DefaultCounterService(this.repository); - - private MetricReader reader = this.repository; - - private static int threadCount = 2; - - private static final int number = Boolean.getBoolean("performance.test") ? 2000000 - : 1000000; - - private static int count; - - private static StopWatch watch = new StopWatch("count"); - - private static PrintWriter err; - - @BeforeClass - public static void prime() throws FileNotFoundException { - err = new NullPrintWriter(); - final Random random = new Random(); - for (int i = 0; i < 1000; i++) { - sample[i] = names[random.nextInt(names.length)]; - } - } - - @Theory - public void counters(String input) throws Exception { - watch.start("counters" + count++); - ExecutorService pool = Executors.newFixedThreadPool(threadCount); - Runnable task = () -> { - for (int i = 0; i < number; i++) { - String name = sample[i % sample.length]; - DefaultCounterServiceSpeedTests.this.counterService.increment(name); - } - }; - Collection> futures = new HashSet<>(); - for (int i = 0; i < threadCount; i++) { - futures.add(pool.submit(task)); - } - for (Future future : futures) { - future.get(); - } - watch.stop(); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Counters rate(" + count + ")=" + rate + ", " + watch); - watch.start("read" + count); - this.reader.findAll().forEach(err::println); - LongAdder total = new LongAdder(); - this.reader.findAll().forEach((value) -> total.add(value.getValue().intValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(total.longValue()).isEqualTo(number * threadCount); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultGaugeServiceSpeedTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultGaugeServiceSpeedTests.java deleted file mode 100644 index b8d8398d9dfb..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DefaultGaugeServiceSpeedTests.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.LongAdder; - -import org.junit.BeforeClass; -import org.junit.experimental.theories.DataPoints; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.metrics.GaugeService; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.boot.actuate.metrics.writer.DefaultGaugeService; -import org.springframework.util.StopWatch; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Speed tests for {@link DefaultGaugeService}. - * - * @author Dave Syer - */ -@RunWith(Theories.class) -public class DefaultGaugeServiceSpeedTests { - - @DataPoints - public static String[] values = new String[10]; - - public static String[] names = new String[] { "foo", "bar", "spam", "bucket" }; - - public static String[] sample = new String[1000]; - - private InMemoryMetricRepository repository = new InMemoryMetricRepository(); - - private GaugeService gaugeService = new DefaultGaugeService(this.repository); - - private MetricReader reader = this.repository; - - private static int threadCount = 2; - - private static final int number = Boolean.getBoolean("performance.test") ? 5000000 - : 1000000; - - private static int count; - - private static StopWatch watch = new StopWatch("count"); - - private static PrintWriter err; - - @BeforeClass - public static void prime() throws FileNotFoundException { - err = new NullPrintWriter(); - Random random = new Random(); - for (int i = 0; i < 1000; i++) { - sample[i] = names[random.nextInt(names.length)]; - } - } - - @Theory - public void gauges(String input) throws Exception { - watch.start("gauges" + count++); - ExecutorService pool = Executors.newFixedThreadPool(threadCount); - Runnable task = () -> { - for (int i = 0; i < number; i++) { - String name = sample[i % sample.length]; - DefaultGaugeServiceSpeedTests.this.gaugeService.submit(name, count + i); - } - }; - Collection> futures = new HashSet<>(); - for (int i = 0; i < threadCount; i++) { - futures.add(pool.submit(task)); - } - for (Future future : futures) { - future.get(); - } - watch.stop(); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Gauges rate(" + count + ")=" + rate + ", " + watch); - watch.start("read" + count); - this.reader.findAll().forEach(err::println); - LongAdder total = new LongAdder(); - this.reader.findAll().forEach((value) -> total.add(value.getValue().intValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(0 < total.longValue()).isTrue(); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DropwizardCounterServiceSpeedTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DropwizardCounterServiceSpeedTests.java deleted file mode 100644 index bb1c9588612f..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/DropwizardCounterServiceSpeedTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.metrics.buffer; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.HashSet; -import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.LongAdder; - -import com.codahale.metrics.MetricRegistry; -import org.junit.BeforeClass; -import org.junit.experimental.theories.DataPoints; -import org.junit.experimental.theories.Theories; -import org.junit.experimental.theories.Theory; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices; -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.reader.MetricRegistryMetricReader; -import org.springframework.util.StopWatch; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Speeds tests for {@link DropwizardMetricServices DropwizardMetricServices'} - * {@link CounterService}. - * - * @author Dave Syer - */ -@RunWith(Theories.class) -public class DropwizardCounterServiceSpeedTests { - - @DataPoints - public static String[] values = new String[10]; - - public static String[] names = new String[] { "foo", "bar", "spam", "bucket" }; - - public static String[] sample = new String[1000]; - - private MetricRegistry registry = new MetricRegistry(); - - private CounterService counterService = new DropwizardMetricServices(this.registry); - - private MetricReader reader = new MetricRegistryMetricReader(this.registry); - - private static int threadCount = 2; - - private static final int number = Boolean.getBoolean("performance.test") ? 10000000 - : 1000000; - - private static int count; - - private static StopWatch watch = new StopWatch("count"); - - private static PrintWriter err; - - @BeforeClass - public static void prime() throws FileNotFoundException { - err = new NullPrintWriter(); - Random random = new Random(); - for (int i = 0; i < 1000; i++) { - sample[i] = names[random.nextInt(names.length)]; - } - } - - @Theory - public void counters(String input) throws Exception { - watch.start("counters" + count++); - ExecutorService pool = Executors.newFixedThreadPool(threadCount); - Runnable task = () -> { - for (int i = 0; i < number; i++) { - String name = sample[i % sample.length]; - DropwizardCounterServiceSpeedTests.this.counterService.increment(name); - } - }; - Collection> futures = new HashSet<>(); - for (int i = 0; i < threadCount; i++) { - futures.add(pool.submit(task)); - } - for (Future future : futures) { - future.get(); - } - watch.stop(); - double rate = number / watch.getLastTaskTimeMillis() * 1000; - System.err.println("Counters rate(" + count + ")=" + rate + ", " + watch); - watch.start("read" + count); - this.reader.findAll().forEach(err::println); - LongAdder total = new LongAdder(); - this.reader.findAll().forEach((value) -> total.add(value.getValue().intValue())); - watch.stop(); - System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms"); - assertThat(total.longValue()).isEqualTo(number * threadCount); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/NullPrintWriter.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/NullPrintWriter.java deleted file mode 100644 index 39cc92f8b6c6..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/buffer/NullPrintWriter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 org.springframework.boot.actuate.metrics.buffer; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; - -/** - * A {@link PrintWriter} that writes to {@code NUL} on Windows and {@code /dev/null} on - * all other platforms. - * - * @author Andy Wilkinson - */ -public class NullPrintWriter extends PrintWriter { - - public NullPrintWriter() throws FileNotFoundException { - super(isWindows() ? "NUL" : "/dev/null"); - } - - private static boolean isWindows() { - return File.separatorChar == '\\'; - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java deleted file mode 100644 index 83485f2aa3b7..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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.metrics.dropwizard; - -import java.util.ArrayList; -import java.util.List; - -import com.codahale.metrics.Gauge; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.Timer; -import com.codahale.metrics.UniformReservoir; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import org.springframework.test.util.ReflectionTestUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; - -/** - * Tests for {@link DropwizardMetricServices}. - * - * @author Dave Syer - * @author Lucas Saldanha - */ -public class DropwizardMetricServicesTests { - - private MetricRegistry registry = new MetricRegistry(); - - @Mock - private ReservoirFactory reservoirFactory; - - private DropwizardMetricServices writer; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - this.writer = new DropwizardMetricServices(this.registry, this.reservoirFactory); - } - - @Test - public void incrementCounter() { - this.writer.increment("foo"); - this.writer.increment("foo"); - this.writer.increment("foo"); - assertThat(this.registry.counter("counter.foo").getCount()).isEqualTo(3); - } - - @Test - public void updatePredefinedMeter() { - this.writer.increment("meter.foo"); - this.writer.increment("meter.foo"); - this.writer.increment("meter.foo"); - assertThat(this.registry.meter("meter.foo").getCount()).isEqualTo(3); - } - - @Test - public void updatePredefinedCounter() { - this.writer.increment("counter.foo"); - this.writer.increment("counter.foo"); - this.writer.increment("counter.foo"); - assertThat(this.registry.counter("counter.foo").getCount()).isEqualTo(3); - } - - @Test - public void setGauge() { - this.writer.submit("foo", 2.1); - @SuppressWarnings("unchecked") - Gauge gauge = (Gauge) this.registry.getMetrics().get("gauge.foo"); - assertThat(gauge.getValue()).isEqualTo(new Double(2.1)); - this.writer.submit("foo", 2.3); - assertThat(gauge.getValue()).isEqualTo(new Double(2.3)); - } - - @Test - public void setPredefinedTimer() { - this.writer.submit("timer.foo", 200); - this.writer.submit("timer.foo", 300); - assertThat(this.registry.timer("timer.foo").getCount()).isEqualTo(2); - } - - @Test - public void setCustomReservoirTimer() { - given(this.reservoirFactory.getReservoir(anyString())) - .willReturn(new UniformReservoir()); - this.writer.submit("timer.foo", 200); - this.writer.submit("timer.foo", 300); - assertThat(this.registry.timer("timer.foo").getCount()).isEqualTo(2); - Timer timer = (Timer) this.registry.getMetrics().get("timer.foo"); - Histogram histogram = (Histogram) ReflectionTestUtils.getField(timer, - "histogram"); - assertThat(ReflectionTestUtils.getField(histogram, "reservoir").getClass() - .equals(UniformReservoir.class)).isTrue(); - } - - @Test - public void setPredefinedHistogram() { - this.writer.submit("histogram.foo", 2.1); - this.writer.submit("histogram.foo", 2.3); - assertThat(this.registry.histogram("histogram.foo").getCount()).isEqualTo(2); - } - - @Test - public void setCustomReservoirHistogram() { - given(this.reservoirFactory.getReservoir(anyString())) - .willReturn(new UniformReservoir()); - this.writer.submit("histogram.foo", 2.1); - this.writer.submit("histogram.foo", 2.3); - assertThat(this.registry.histogram("histogram.foo").getCount()).isEqualTo(2); - assertThat(ReflectionTestUtils - .getField(this.registry.getMetrics().get("histogram.foo"), "reservoir") - .getClass().equals(UniformReservoir.class)).isTrue(); - } - - /** - * Test the case where a given writer is used amongst several threads where each - * thread is updating the same set of metrics. This would be an example case of the - * writer being used with the MetricsFilter handling several requests/sec to the same - * URL. - * @throws Exception if an error occurs - */ - @Test - public void testParallelism() throws Exception { - List threads = new ArrayList<>(); - ThreadGroup group = new ThreadGroup("threads"); - for (int i = 0; i < 10; i++) { - WriterThread thread = new WriterThread(group, i, this.writer); - threads.add(thread); - thread.start(); - } - - while (group.activeCount() > 0) { - Thread.sleep(1000); - } - - for (WriterThread thread : threads) { - assertThat(thread.isFailed()) - .as("expected thread caused unexpected exception").isFalse(); - } - } - - public static class WriterThread extends Thread { - - private int index; - - private boolean failed; - - private DropwizardMetricServices writer; - - public WriterThread(ThreadGroup group, int index, - DropwizardMetricServices writer) { - super(group, "Writer-" + index); - this.index = index; - this.writer = writer; - } - - public boolean isFailed() { - return this.failed; - } - - @Override - public void run() { - for (int i = 0; i < 10000; i++) { - try { - this.writer.submit("timer.test.service", this.index); - this.writer.submit("histogram.test.service", this.index); - this.writer.submit("gauge.test.service", this.index); - } - catch (IllegalArgumentException ex) { - this.failed = true; - throw ex; - } - } - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporterTests.java deleted file mode 100644 index 40b61f6bbebe..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricCopyExporterTests.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.Date; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MetricCopyExporter}. - * - * @author Dave Syer - */ -public class MetricCopyExporterTests { - - private final InMemoryMetricRepository writer = new InMemoryMetricRepository(); - - private final InMemoryMetricRepository reader = new InMemoryMetricRepository(); - - private final MetricCopyExporter exporter = new MetricCopyExporter(this.reader, - this.writer); - - @Test - public void export() { - this.reader.set(new Metric("foo", 2.3)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - } - - @Test - public void counter() { - this.reader.increment(new Delta("counter.foo", 2)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - this.reader.increment(new Delta("counter.foo", 3)); - this.exporter.export(); - this.exporter.flush(); - assertThat(this.writer.findOne("counter.foo").getValue()).isEqualTo(5L); - } - - @Test - public void counterWithGaugeWriter() throws Exception { - SimpleGaugeWriter writer = new SimpleGaugeWriter(); - try (MetricCopyExporter customExporter = new MetricCopyExporter(this.reader, - writer)) { - this.reader.increment(new Delta("counter.foo", 2)); - customExporter.export(); - this.reader.increment(new Delta("counter.foo", 3)); - customExporter.export(); - customExporter.flush(); - assertThat(writer.getValue().getValue()).isEqualTo(5L); - } - } - - @Test - public void exportIncludes() { - this.exporter.setIncludes("*"); - this.reader.set(new Metric("foo", 2.3)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - } - - @Test - public void exportExcludesWithIncludes() { - this.exporter.setIncludes("*"); - this.exporter.setExcludes("foo"); - this.reader.set(new Metric("foo", 2.3)); - this.reader.set(new Metric("bar", 2.4)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - } - - @Test - public void exportExcludesDefaultIncludes() { - this.exporter.setExcludes("foo"); - this.reader.set(new Metric("foo", 2.3)); - this.reader.set(new Metric("bar", 2.4)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - } - - @Test - public void timestamp() { - this.reader.set(new Metric("foo", 2.3)); - this.exporter.setEarliestTimestamp(new Date(System.currentTimeMillis() + 10000)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(0); - } - - @Test - public void ignoreTimestamp() { - this.reader.set(new Metric("foo", 2.3)); - this.exporter.setIgnoreTimestamps(true); - this.exporter.setEarliestTimestamp(new Date(System.currentTimeMillis() + 10000)); - this.exporter.export(); - assertThat(this.writer.count()).isEqualTo(1); - } - - private static class SimpleGaugeWriter implements GaugeWriter { - - private Metric value; - - @Override - public void set(Metric value) { - this.value = value; - } - - public Metric getValue() { - return this.value; - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricExportersTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricExportersTests.java deleted file mode 100644 index 200a46439280..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/MetricExportersTests.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.boot.actuate.metrics.writer.GaugeWriter; -import org.springframework.boot.actuate.metrics.writer.MetricWriter; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link MetricExporters}. - * - * @author Dave Syer - */ -public class MetricExportersTests { - - private MetricExporters exporters; - - private MetricExportProperties export = new MetricExportProperties(); - - private Map writers = new LinkedHashMap<>(); - - private MetricReader reader = mock(MetricReader.class); - - private MetricWriter writer = mock(MetricWriter.class); - - @Test - public void emptyWriters() { - this.exporters = new MetricExporters(this.export); - this.exporters.setReader(this.reader); - this.exporters.setWriters(this.writers); - this.exporters.configureTasks(new ScheduledTaskRegistrar()); - assertThat(this.exporters.getExporters()).isNotNull(); - assertThat(this.exporters.getExporters()).isEmpty(); - } - - @Test - public void oneWriter() { - this.export.setUpDefaults(); - this.writers.put("foo", this.writer); - this.exporters = new MetricExporters(this.export); - this.exporters.setReader(this.reader); - this.exporters.setWriters(this.writers); - this.exporters.configureTasks(new ScheduledTaskRegistrar()); - assertThat(this.exporters.getExporters()).isNotNull(); - assertThat(this.exporters.getExporters()).hasSize(1); - } - - @Test - public void exporter() { - this.export.setUpDefaults(); - this.exporters = new MetricExporters(this.export); - this.exporters.setExporters(Collections.singletonMap("foo", - new MetricCopyExporter(this.reader, this.writer))); - this.exporters.configureTasks(new ScheduledTaskRegistrar()); - assertThat(this.exporters.getExporters()).isNotNull(); - assertThat(this.exporters.getExporters()).hasSize(1); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java deleted file mode 100644 index 164801ca64af..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.metrics.export; - -import java.util.Arrays; -import java.util.Collections; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Iterables; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.InMemoryMultiMetricRepository; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link PrefixMetricGroupExporter}. - * - * @author Dave Syer - */ -public class PrefixMetricGroupExporterTests { - - private final InMemoryMultiMetricRepository reader = new InMemoryMultiMetricRepository(); - - private final InMemoryMultiMetricRepository writer = new InMemoryMultiMetricRepository(); - - private final PrefixMetricGroupExporter exporter = new PrefixMetricGroupExporter( - this.reader, this.writer); - - @Test - public void prefixedMetricsCopied() { - this.reader.set("foo", Arrays.>asList(new Metric("bar", 2.3), - new Metric("spam", 1.3))); - this.exporter.setGroups(Collections.singleton("foo")); - this.exporter.export(); - assertThat(Iterables.collection(this.writer.groups())).hasSize(1); - } - - @Test - public void countersIncremented() { - this.writer.increment("counter.foo", new Delta<>("bar", 1L)); - this.reader.set("counter", Collections - .>singletonList(new Metric("counter.foo.bar", 1))); - this.exporter.setGroups(Collections.singleton("counter.foo")); - this.exporter.export(); - assertThat(this.writer.findAll("counter.foo").iterator().next().getValue()) - .isEqualTo(2L); - } - - @Test - public void unprefixedMetricsNotCopied() { - this.reader.set("foo", Arrays.>asList( - new Metric("foo.bar", 2.3), new Metric("foo.spam", 1.3))); - this.exporter.setGroups(Collections.singleton("bar")); - this.exporter.export(); - assertThat(Iterables.collection(this.writer.groups())).isEmpty(); - } - - @Test - public void multiMetricGroupsCopiedAsDefault() { - this.reader.set("foo", Arrays.>asList(new Metric("bar", 2.3), - new Metric("spam", 1.3))); - this.exporter.export(); - assertThat(this.writer.countGroups()).isEqualTo(1); - assertThat(Iterables.collection(this.writer.findAll("foo"))).hasSize(2); - } - - @Test - public void onlyPrefixedMetricsCopied() { - this.reader.set("foo", Arrays.>asList( - new Metric("foo.bar", 2.3), new Metric("foo.spam", 1.3))); - this.reader.set("foobar", Collections - .>singletonList(new Metric("foobar.spam", 1.3))); - this.exporter.setGroups(Collections.singleton("foo")); - this.exporter.export(); - assertThat(Iterables.collection(this.writer.groups())).hasSize(1); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java deleted file mode 100644 index d77b10ea9345..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.export; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Iterables; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.InMemoryMultiMetricRepository; -import org.springframework.boot.actuate.metrics.rich.InMemoryRichGaugeRepository; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link RichGaugeExporter}. - * - * @author Dave Syer - */ -public class RichGaugeExporterTests { - - private final InMemoryRichGaugeRepository reader = new InMemoryRichGaugeRepository(); - - private final InMemoryMultiMetricRepository writer = new InMemoryMultiMetricRepository(); - - private final RichGaugeExporter exporter = new RichGaugeExporter(this.reader, - this.writer); - - @Test - public void prefixedMetricsCopied() { - this.reader.set(new Metric("foo", 2.3)); - this.exporter.export(); - assertThat(Iterables.collection(this.writer.groups())).hasSize(1); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java deleted file mode 100644 index 0d03bf6d81fe..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.metrics.integration; - -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.autoconfigure.metrics.PublicMetricsAutoConfiguration; -import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; -import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SpringIntegrationMetricReader}. - * - * @author Artem Bilan - */ -@RunWith(SpringRunner.class) -@SpringBootTest("spring.jmx.enabled=false") -@DirtiesContext -public class SpringIntegrationMetricReaderNoJmxTests { - - @Autowired - @Qualifier("springIntegrationPublicMetrics") - private MetricReaderPublicMetrics integrationMetricReader; - - @Test - public void test() { - assertThat(this.integrationMetricReader.metrics().size() > 0).isTrue(); - } - - @Configuration - @Import({ IntegrationAutoConfiguration.class, PublicMetricsAutoConfiguration.class }) - protected static class TestConfiguration { - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java deleted file mode 100644 index f8a01b0903d3..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.integration; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; -import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.integration.support.management.IntegrationManagementConfigurer; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SpringIntegrationMetricReader}. - * - * @author Dave Syer - * @author Artem Bilan - */ -@RunWith(SpringRunner.class) -@SpringBootTest("spring.jmx.enabled=true") -@DirtiesContext -public class SpringIntegrationMetricReaderTests { - - @Autowired - private SpringIntegrationMetricReader reader; - - @Test - public void test() { - assertThat(this.reader.count() > 0).isTrue(); - } - - @Configuration - @Import({ JmxAutoConfiguration.class, IntegrationAutoConfiguration.class }) - protected static class TestConfiguration { - - @Bean - public SpringIntegrationMetricReader reader( - IntegrationManagementConfigurer managementConfigurer) { - return new SpringIntegrationMetricReader(managementConfigurer); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategyTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategyTests.java deleted file mode 100644 index a9b09f16abbf..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/jmx/DefaultMetricNamingStrategyTests.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.jmx; - -import javax.management.ObjectName; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link DefaultMetricNamingStrategy}. - * - * @author Dave Syer - */ -public class DefaultMetricNamingStrategyTests { - - private DefaultMetricNamingStrategy strategy = new DefaultMetricNamingStrategy(); - - @Test - public void simpleName() throws Exception { - ObjectName name = this.strategy.getObjectName(null, - "domain:type=MetricValue,name=foo"); - assertThat(name.getDomain()).isEqualTo("domain"); - assertThat(name.getKeyProperty("type")).isEqualTo("foo"); - } - - @Test - public void onePeriod() throws Exception { - ObjectName name = this.strategy.getObjectName(null, - "domain:type=MetricValue,name=foo.bar"); - assertThat(name.getDomain()).isEqualTo("domain"); - assertThat(name.getKeyProperty("type")).isEqualTo("foo"); - assertThat(name.getKeyProperty("value")).isEqualTo("bar"); - } - - @Test - public void twoPeriods() throws Exception { - ObjectName name = this.strategy.getObjectName(null, - "domain:type=MetricValue,name=foo.bar.spam"); - assertThat(name.getDomain()).isEqualTo("domain"); - assertThat(name.getKeyProperty("type")).isEqualTo("foo"); - assertThat(name.getKeyProperty("name")).isEqualTo("bar"); - assertThat(name.getKeyProperty("value")).isEqualTo("spam"); - } - - @Test - public void threePeriods() throws Exception { - ObjectName name = this.strategy.getObjectName(null, - "domain:type=MetricValue,name=foo.bar.spam.bucket"); - assertThat(name.getDomain()).isEqualTo("domain"); - assertThat(name.getKeyProperty("type")).isEqualTo("foo"); - assertThat(name.getKeyProperty("name")).isEqualTo("bar"); - assertThat(name.getKeyProperty("value")).isEqualTo("spam.bucket"); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriterTests.java deleted file mode 100644 index 45d8a44dd9cd..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/opentsdb/OpenTsdbGaugeWriterTests.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.metrics.opentsdb; - -import java.util.Collections; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestOperations; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link OpenTsdbGaugeWriter}. - * - * @author Dave Syer - */ -public class OpenTsdbGaugeWriterTests { - - private OpenTsdbGaugeWriter writer; - - private RestOperations restTemplate = mock(RestOperations.class); - - @Before - public void init() { - this.writer = new OpenTsdbGaugeWriter(); - this.writer.setRestTemplate(this.restTemplate); - } - - @Test - public void postSuccessfullyOnFlush() { - this.writer.set(new Metric<>("foo", 2.4)); - given(this.restTemplate.postForEntity(anyString(), any(Object.class), anyMap())) - .willReturn(emptyResponse()); - this.writer.flush(); - verify(this.restTemplate).postForEntity(anyString(), any(Object.class), anyMap()); - } - - @Test - public void flushAutomatically() { - given(this.restTemplate.postForEntity(anyString(), any(Object.class), anyMap())) - .willReturn(emptyResponse()); - this.writer.setBufferSize(0); - this.writer.set(new Metric<>("foo", 2.4)); - verify(this.restTemplate).postForEntity(anyString(), any(Object.class), anyMap()); - } - - @SuppressWarnings("rawtypes") - private ResponseEntity emptyResponse() { - return new ResponseEntity<>(Collections.emptyMap(), HttpStatus.OK); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private Class anyMap() { - return any(Class.class); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java deleted file mode 100644 index c69eee736f00..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.metrics.reader; - -import java.util.HashSet; -import java.util.Set; - -import com.codahale.metrics.Gauge; -import com.codahale.metrics.MetricRegistry; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MetricRegistryMetricReader}. - * - * @author Andy Wilkinson - */ -public class MetricRegistryMetricReaderTests { - - private final MetricRegistry metricRegistry = new MetricRegistry(); - - private final MetricRegistryMetricReader metricReader = new MetricRegistryMetricReader( - this.metricRegistry); - - @Test - public void nonNumberGaugesAreTolerated() { - this.metricRegistry.register("test", (Gauge>) HashSet::new); - assertThat(this.metricReader.findOne("test")).isNull(); - this.metricRegistry.remove("test"); - assertThat(this.metricReader.findOne("test")).isNull(); - } - - @Test - @SuppressWarnings("unchecked") - public void numberGauge() { - this.metricRegistry.register("test", (Gauge) () -> Integer.valueOf(5)); - Metric metric = (Metric) this.metricReader.findOne("test"); - assertThat(metric.getValue()).isEqualTo(Integer.valueOf(5)); - this.metricRegistry.remove("test"); - assertThat(this.metricReader.findOne("test")).isNull(); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepositoryTests.java deleted file mode 100644 index 25cf51063b61..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepositoryTests.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.metrics.repository; - -import java.util.Date; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.offset; - -/** - * Tests for {@link InMemoryMetricRepository}. - * - * @author Dave Syer - */ -public class InMemoryMetricRepositoryTests { - - private final InMemoryMetricRepository repository = new InMemoryMetricRepository(); - - @Test - public void increment() { - this.repository.increment(new Delta<>("foo", 1, new Date())); - assertThat(this.repository.findOne("foo").getValue().doubleValue()).isEqualTo(1.0, - offset(0.01)); - } - - @Test - public void set() { - this.repository.set(new Metric<>("foo", 2.5, new Date())); - assertThat(this.repository.findOne("foo").getValue().doubleValue()).isEqualTo(2.5, - offset(0.01)); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java deleted file mode 100644 index 501691c6bc5c..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.metrics.repository; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link InMemoryMultiMetricRepository}. - * - * @author Dave Syer - */ -public class InMemoryMultiMetricRepositoryTests { - - private final InMemoryMultiMetricRepository repository = new InMemoryMultiMetricRepository(); - - @Test - public void registeredPrefixCounted() { - this.repository.increment("foo", new Delta("bar", 1)); - this.repository.increment("foo", new Delta("bar", 1)); - this.repository.increment("foo", new Delta("spam", 1)); - Set names = new HashSet<>(); - for (Metric metric : this.repository.findAll("foo")) { - names.add(metric.getName()); - } - assertThat(names).hasSize(2); - assertThat(names.contains("foo.bar")).isTrue(); - } - - @Test - public void prefixWithWildcard() { - this.repository.increment("foo", new Delta("bar", 1)); - Set names = new HashSet<>(); - for (Metric metric : this.repository.findAll("foo.*")) { - names.add(metric.getName()); - } - assertThat(names).hasSize(1); - assertThat(names.contains("foo.bar")).isTrue(); - } - - @Test - public void prefixWithPeriod() { - this.repository.increment("foo", new Delta("bar", 1)); - Set names = new HashSet<>(); - for (Metric metric : this.repository.findAll("foo.")) { - names.add(metric.getName()); - } - assertThat(names).hasSize(1); - assertThat(names.contains("foo.bar")).isTrue(); - } - - @Test - public void onlyRegisteredPrefixCounted() { - this.repository.increment("foo", new Delta("bar", 1)); - this.repository.increment("foobar", new Delta("spam", 1)); - Set names = new HashSet<>(); - for (Metric metric : this.repository.findAll("foo")) { - names.add(metric.getName()); - } - assertThat(names).hasSize(1); - assertThat(names.contains("foo.bar")).isTrue(); - } - - @Test - public void incrementGroup() { - this.repository.increment("foo", new Delta("foo.bar", 1)); - this.repository.increment("foo", new Delta("foo.bar", 2)); - this.repository.increment("foo", new Delta("foo.spam", 1)); - Map> metrics = new HashMap<>(); - for (Metric metric : this.repository.findAll("foo")) { - metrics.put(metric.getName(), metric); - } - assertThat(metrics).hasSize(2); - assertThat(metrics).containsKeys("foo.bar", "foo.spam"); - assertThat(metrics.get("foo.bar").getValue()).isEqualTo(3L); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepositoryTests.java deleted file mode 100644 index a281adbed6f5..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepositoryTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.metrics.repository.redis; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Iterables; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.testsupport.rule.RedisTestServer; -import org.springframework.data.redis.core.StringRedisTemplate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.offset; - -/** - * Tests for {@link RedisMetricRepository}. - * - * @author Dave Syer - */ -public class RedisMetricRepositoryTests { - - @Rule - public RedisTestServer redis = new RedisTestServer(); - - private RedisMetricRepository repository; - - private String prefix; - - @Before - public void init() { - this.prefix = "spring.test." + System.currentTimeMillis(); - this.repository = new RedisMetricRepository(this.redis.getConnectionFactory(), - this.prefix); - } - - @After - public void clear() { - assertThat(new StringRedisTemplate(this.redis.getConnectionFactory()) - .opsForValue().get(this.prefix + ".foo")).isNotNull(); - this.repository.reset("foo"); - this.repository.reset("bar"); - assertThat(new StringRedisTemplate(this.redis.getConnectionFactory()) - .opsForValue().get(this.prefix + ".foo")).isNull(); - } - - @Test - public void setAndGet() { - this.repository.set(new Metric("foo", 12.3)); - Metric metric = this.repository.findOne("foo"); - assertThat(metric.getName()).isEqualTo("foo"); - assertThat(metric.getValue().doubleValue()).isEqualTo(12.3, offset(0.01)); - } - - @Test - public void incrementAndGet() { - this.repository.increment(new Delta<>("foo", 3L)); - assertThat(this.repository.findOne("foo").getValue().longValue()).isEqualTo(3); - } - - @Test - public void setIncrementAndGet() { - this.repository.set(new Metric("foo", 12.3)); - this.repository.increment(new Delta<>("foo", 3L)); - Metric metric = this.repository.findOne("foo"); - assertThat(metric.getName()).isEqualTo("foo"); - assertThat(metric.getValue().doubleValue()).isEqualTo(15.3, offset(0.01)); - } - - @Test - public void findAll() { - this.repository.increment(new Delta<>("foo", 3L)); - this.repository.set(new Metric("bar", 12.3)); - assertThat(Iterables.collection(this.repository.findAll())).hasSize(2); - } - - @Test - public void findOneWithAll() { - this.repository.increment(new Delta<>("foo", 3L)); - Metric metric = this.repository.findAll().iterator().next(); - assertThat(metric.getName()).isEqualTo("foo"); - } - - @Test - public void count() { - this.repository.increment(new Delta<>("foo", 3L)); - this.repository.set(new Metric("bar", 12.3)); - assertThat(this.repository.count()).isEqualTo(2); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java deleted file mode 100644 index f4537dcd4a6e..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.metrics.repository.redis; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -import org.springframework.boot.actuate.metrics.Iterables; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; -import org.springframework.boot.testsupport.rule.RedisTestServer; -import org.springframework.data.redis.core.StringRedisTemplate; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link RedisMultiMetricRepository}. - * - * @author Dave Syer - */ -@RunWith(Parameterized.class) -public class RedisMultiMetricRepositoryTests { - - @Rule - public RedisTestServer redis = new RedisTestServer(); - - private RedisMultiMetricRepository repository; - - @Parameter(0) - public String prefix; - - @Parameters - public static List parameters() { - return Arrays.asList(new Object[] { null }, new Object[] { "test" }); - } - - @Before - public void init() { - if (this.prefix == null) { - this.prefix = "spring.groups"; - this.repository = new RedisMultiMetricRepository( - this.redis.getConnectionFactory()); - } - else { - this.repository = new RedisMultiMetricRepository( - this.redis.getConnectionFactory(), this.prefix); - } - } - - @After - public void clear() { - assertThat(new StringRedisTemplate(this.redis.getConnectionFactory()).opsForZSet() - .size("keys." + this.prefix)).isGreaterThan(0); - this.repository.reset("foo"); - this.repository.reset("bar"); - assertThat(new StringRedisTemplate(this.redis.getConnectionFactory()) - .opsForValue().get(this.prefix + ".foo")).isNull(); - assertThat(new StringRedisTemplate(this.redis.getConnectionFactory()) - .opsForValue().get(this.prefix + ".bar")).isNull(); - } - - @Test - public void setAndGet() { - this.repository.set("foo", - Arrays.>asList(new Metric("foo.bar", 12.3))); - this.repository.set("foo", - Arrays.>asList(new Metric("foo.bar", 15.3))); - assertThat(Iterables.collection(this.repository.findAll("foo")).iterator().next() - .getValue()).isEqualTo(15.3); - } - - @Test - public void setAndGetMultiple() { - this.repository.set("foo", - Arrays.>asList(new Metric("foo.val", 12.3), - new Metric("foo.bar", 11.3))); - assertThat(Iterables.collection(this.repository.findAll("foo"))).hasSize(2); - } - - @Test - public void groups() { - this.repository.set("foo", - Arrays.>asList(new Metric("foo.val", 12.3), - new Metric("foo.bar", 11.3))); - this.repository.set("bar", - Arrays.>asList(new Metric("bar.val", 12.3), - new Metric("bar.foo", 11.3))); - Collection groups = Iterables.collection(this.repository.groups()); - assertThat(groups).hasSize(2).contains("foo"); - } - - @Test - public void count() { - this.repository.set("foo", - Arrays.>asList(new Metric("foo.val", 12.3), - new Metric("foo.bar", 11.3))); - this.repository.set("bar", - Arrays.>asList(new Metric("bar.val", 12.3), - new Metric("bar.foo", 11.3))); - assertThat(this.repository.countGroups()).isEqualTo(2); - } - - @Test - public void increment() { - this.repository.increment("foo", new Delta("foo.bar", 1)); - this.repository.increment("foo", new Delta("foo.bar", 2)); - this.repository.increment("foo", new Delta("foo.spam", 1)); - Metric bar = null; - Set names = new HashSet<>(); - for (Metric metric : this.repository.findAll("foo")) { - names.add(metric.getName()); - if (metric.getName().equals("foo.bar")) { - bar = metric; - } - } - assertThat(names).hasSize(2).contains("foo.bar"); - assertThat(bar.getValue()).isEqualTo(3d); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepositoryTests.java deleted file mode 100644 index 6af63795f8c0..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/InMemoryRichGaugeRepositoryTests.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.metrics.rich; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.offset; - -/** - * Tests for {@link InMemoryRichGaugeRepository}. - * - * @author Dave Syer - * @author Andy Wilkinson - */ -public class InMemoryRichGaugeRepositoryTests { - - private final InMemoryRichGaugeRepository repository = new InMemoryRichGaugeRepository(); - - @Test - public void writeAndRead() { - this.repository.set(new Metric<>("foo", 1d)); - this.repository.set(new Metric<>("foo", 2d)); - assertThat(this.repository.findOne("foo").getCount()).isEqualTo(2L); - assertThat(this.repository.findOne("foo").getValue()).isEqualTo(2d, offset(0.01)); - } - - @Test - public void incrementExisting() { - this.repository.set(new Metric<>("foo", 1d)); - this.repository.increment(new Delta<>("foo", 2d)); - assertThat(this.repository.findOne("foo").getCount()).isEqualTo(2L); - assertThat(this.repository.findOne("foo").getValue()).isEqualTo(3d, offset(0.01)); - } - - @Test - public void incrementNew() { - this.repository.increment(new Delta<>("foo", 2d)); - assertThat(this.repository.findOne("foo").getCount()).isEqualTo(1L); - assertThat(this.repository.findOne("foo").getValue()).isEqualTo(2d, offset(0.01)); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java deleted file mode 100644 index df4b7bcd557e..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.metrics.rich; - -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.export.RichGaugeExporter; -import org.springframework.boot.actuate.metrics.repository.InMemoryMultiMetricRepository; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MultiMetricRichGaugeReader}. - * - * @author Dave Syer - */ -public class MultiMetricRichGaugeReaderTests { - - private InMemoryMultiMetricRepository repository = new InMemoryMultiMetricRepository(); - - private MultiMetricRichGaugeReader reader = new MultiMetricRichGaugeReader( - this.repository); - - private InMemoryRichGaugeRepository data = new InMemoryRichGaugeRepository(); - - private RichGaugeExporter exporter = new RichGaugeExporter(this.data, - this.repository); - - @Test - public void countOne() { - this.data.set(new Metric<>("foo", 1)); - this.data.set(new Metric<>("foo", 1)); - this.exporter.export(); - // Check the exporter worked - assertThat(this.repository.countGroups()).isEqualTo(1); - assertThat(this.reader.count()).isEqualTo(1); - RichGauge one = this.reader.findOne("foo"); - assertThat(one).isNotNull(); - assertThat(one.getCount()).isEqualTo(2); - } - - @Test - public void countTwo() { - this.data.set(new Metric<>("foo", 1)); - this.data.set(new Metric<>("bar", 1)); - this.exporter.export(); - assertThat(this.reader.count()).isEqualTo(2); - RichGauge one = this.reader.findOne("foo"); - assertThat(one).isNotNull(); - assertThat(one.getCount()).isEqualTo(1); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriterTests.java deleted file mode 100644 index 936d4586f86a..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/statsd/StatsdMetricWriterTests.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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.metrics.statsd; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.SocketException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import org.junit.After; -import org.junit.Test; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.writer.Delta; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link StatsdMetricWriter}. - * - * @author Dave Syer - * @author OdĂ­n del RĂ­o - */ -public class StatsdMetricWriterTests { - - private DummyStatsDServer server = new DummyStatsDServer(0); - - private StatsdMetricWriter writer = new StatsdMetricWriter("me", "localhost", - this.server.getPort()); - - @After - public void close() { - this.server.stop(); - this.writer.close(); - } - - @Test - public void increment() { - this.writer.increment(new Delta<>("counter.foo", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("me.counter.foo:3|c"); - } - - @Test - public void setLongMetric() throws Exception { - this.writer.set(new Metric<>("gauge.foo", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("me.gauge.foo:3|g"); - } - - @Test - public void setDoubleMetric() throws Exception { - this.writer.set(new Metric<>("gauge.foo", 3.7)); - this.server.waitForMessage(); - // Doubles are truncated - assertThat(this.server.messagesReceived().get(0)).isEqualTo("me.gauge.foo:3.7|g"); - } - - @Test - public void setTimerMetric() throws Exception { - this.writer.set(new Metric<>("timer.foo", 37L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("me.timer.foo:37|ms"); - } - - @Test - public void nullPrefix() throws Exception { - this.writer = new StatsdMetricWriter("localhost", this.server.getPort()); - this.writer.set(new Metric<>("gauge.foo", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("gauge.foo:3|g"); - } - - @Test - public void periodPrefix() throws Exception { - this.writer = new StatsdMetricWriter("my.", "localhost", this.server.getPort()); - this.writer.set(new Metric<>("gauge.foo", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("my.gauge.foo:3|g"); - } - - @Test - public void incrementMetricWithInvalidCharsInName() throws Exception { - this.writer.increment(new Delta<>("counter.fo:o", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)) - .isEqualTo("me.counter.fo-o:3|c"); - } - - @Test - public void setMetricWithInvalidCharsInName() throws Exception { - this.writer.set(new Metric<>("gauge.f:o:o", 3L)); - this.server.waitForMessage(); - assertThat(this.server.messagesReceived().get(0)).isEqualTo("me.gauge.f-o-o:3|g"); - } - - private static final class DummyStatsDServer implements Runnable { - - private final List messagesReceived = new ArrayList<>(); - - private final DatagramSocket server; - - DummyStatsDServer(int port) { - try { - this.server = new DatagramSocket(port); - } - catch (SocketException ex) { - throw new IllegalStateException(ex); - } - new Thread(this).start(); - } - - int getPort() { - return this.server.getLocalPort(); - } - - public void stop() { - this.server.close(); - } - - @Override - public void run() { - try { - DatagramPacket packet = new DatagramPacket(new byte[256], 256); - this.server.receive(packet); - this.messagesReceived.add( - new String(packet.getData(), Charset.forName("UTF-8")).trim()); - } - catch (Exception ex) { - // Ignore - } - } - - public void waitForMessage() { - while (this.messagesReceived.isEmpty()) { - try { - Thread.sleep(50L); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - - public List messagesReceived() { - return new ArrayList<>(this.messagesReceived); - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepositoryTests.java deleted file mode 100755 index dd80db3f3fe1..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/util/SimpleInMemoryRepositoryTests.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.metrics.util; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SimpleInMemoryRepository}. - * - * @author Dave Syer - */ -public class SimpleInMemoryRepositoryTests { - - private final SimpleInMemoryRepository repository = new SimpleInMemoryRepository<>(); - - @Test - public void setAndGet() { - this.repository.set("foo", "bar"); - assertThat(this.repository.findOne("foo")).isEqualTo("bar"); - } - - @Test - public void updateExisting() { - this.repository.set("foo", "spam"); - this.repository.update("foo", (current) -> "bar"); - assertThat(this.repository.findOne("foo")).isEqualTo("bar"); - } - - @Test - public void updateNonexistent() { - this.repository.update("foo", (current) -> "bar"); - assertThat(this.repository.findOne("foo")).isEqualTo("bar"); - } - - @Test - public void findWithPrefix() { - this.repository.set("foo", "bar"); - this.repository.set("foo.bar", "one"); - this.repository.set("foo.min", "two"); - this.repository.set("foo.max", "three"); - assertThat(((Collection) this.repository.findAllWithPrefix("foo"))).hasSize(3); - } - - @Test - public void patternsAcceptedForRegisteredPrefix() { - this.repository.set("foo.bar", "spam"); - Iterator iterator = this.repository.findAllWithPrefix("foo.*").iterator(); - assertThat(iterator.next()).isEqualTo("spam"); - assertThat(iterator.hasNext()).isFalse(); - } - - @Test - public void updateConcurrent() throws Exception { - SimpleInMemoryRepository repository = new SimpleInMemoryRepository<>(); - Collection> tasks = new ArrayList<>(); - for (int i = 0; i < 1000; i++) { - tasks.add(new RepositoryUpdate(repository, 1)); - tasks.add(new RepositoryUpdate(repository, -1)); - } - List> all = Executors.newFixedThreadPool(10).invokeAll(tasks); - for (Future future : all) { - assertThat(future.get(1, TimeUnit.SECONDS)).isTrue(); - } - assertThat(repository.findOne("foo")).isEqualTo(0); - } - - private static class RepositoryUpdate implements Callable { - - private final SimpleInMemoryRepository repository; - - private final int delta; - - RepositoryUpdate(SimpleInMemoryRepository repository, int delta) { - this.repository = repository; - this.delta = delta; - } - - @Override - public Boolean call() throws Exception { - this.repository.update("foo", (current) -> { - if (current == null) { - return RepositoryUpdate.this.delta; - } - return current + RepositoryUpdate.this.delta; - }); - return true; - } - - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterServiceTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterServiceTests.java deleted file mode 100644 index 0aa4ada20216..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultCounterServiceTests.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.writer; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.MockitoAnnotations; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link DefaultCounterService}. - * - * @author Dave Syer - */ -public class DefaultCounterServiceTests { - - private final MetricWriter repository = mock(MetricWriter.class); - - private final DefaultCounterService service = new DefaultCounterService( - this.repository); - - @Captor - private ArgumentCaptor> captor; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void incrementWithExistingCounter() { - this.service.increment("counter.foo"); - verify(this.repository).increment(this.captor.capture()); - assertThat(this.captor.getValue().getName()).isEqualTo("counter.foo"); - assertThat(this.captor.getValue().getValue()).isEqualTo(1L); - } - - @Test - public void incrementWithExistingNearCounter() { - this.service.increment("counter-foo"); - verify(this.repository).increment(this.captor.capture()); - assertThat(this.captor.getValue().getName()).isEqualTo("counter.counter-foo"); - assertThat(this.captor.getValue().getValue()).isEqualTo(1L); - } - - @Test - public void incrementPrependsCounter() { - this.service.increment("foo"); - verify(this.repository).increment(this.captor.capture()); - assertThat(this.captor.getValue().getName()).isEqualTo("counter.foo"); - assertThat(this.captor.getValue().getValue()).isEqualTo(1L); - } - - @Test - public void decrementPrependsCounter() { - this.service.decrement("foo"); - verify(this.repository).increment(this.captor.capture()); - assertThat(this.captor.getValue().getName()).isEqualTo("counter.foo"); - assertThat(this.captor.getValue().getValue()).isEqualTo(-1L); - } - - @Test - public void resetResetsCounter() throws Exception { - this.service.reset("foo"); - verify(this.repository).reset("counter.foo"); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeServiceTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeServiceTests.java deleted file mode 100644 index d9d874023cad..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/DefaultGaugeServiceTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012-2016 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.metrics.writer; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import org.springframework.boot.actuate.metrics.Metric; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link DefaultGaugeService}. - * - * @author Dave Syer - */ -public class DefaultGaugeServiceTests { - - private final MetricWriter repository = mock(MetricWriter.class); - - private final DefaultGaugeService service = new DefaultGaugeService(this.repository); - - @Test - public void setPrependsGauge() { - this.service.submit("foo", 2.3); - @SuppressWarnings("rawtypes") - ArgumentCaptor captor = ArgumentCaptor.forClass(Metric.class); - verify(this.repository).set(captor.capture()); - assertThat(captor.getValue().getName()).isEqualTo("gauge.foo"); - assertThat(captor.getValue().getValue()).isEqualTo(2.3); - } - -} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriterTests.java deleted file mode 100644 index 2f42dee70741..000000000000 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/writer/MessageChannelMetricWriterTests.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.metrics.writer; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link MessageChannelMetricWriter} and {@link MetricWriterMessageHandler}. - * - * @author Dave Syer - */ -public class MessageChannelMetricWriterTests { - - @Mock - private MessageChannel channel; - - @Mock - private MetricWriter observer; - - private MessageChannelMetricWriter writer; - - private MetricWriterMessageHandler handler; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - given(this.channel.send(any(Message.class))).willAnswer((invocation) -> { - MessageChannelMetricWriterTests.this.handler - .handleMessage(invocation.getArgument(0)); - return true; - }); - this.writer = new MessageChannelMetricWriter(this.channel); - this.handler = new MetricWriterMessageHandler(this.observer); - } - - @Test - public void messageSentOnAdd() { - this.writer.increment(new Delta<>("foo", 1)); - verify(this.channel).send(any(Message.class)); - verify(this.observer).increment(any(Delta.class)); - } - - @Test - public void messageSentOnSet() { - this.writer.set(new Metric<>("foo", 1d)); - verify(this.channel).send(any(Message.class)); - verify(this.observer).set(any(Metric.class)); - } - - @Test - public void messageSentOnReset() throws Exception { - this.writer.reset("foo"); - verify(this.channel).send(any(Message.class)); - verify(this.observer).reset("foo"); - } - -} From 010833817a3276085ac44ab6f60afc8a8d888a4c Mon Sep 17 00:00:00 2001 From: Jon Schneider Date: Sun, 10 Sep 2017 23:35:53 -0500 Subject: [PATCH 2/2] Add micrometer metrics --- spring-boot-actuator/pom.xml | 49 ++++ .../endpoint/EndpointAutoConfiguration.java | 15 +- .../metrics/MeterRegistryConfigurer.java | 36 +++ .../actuate/metrics/MetricsConfiguration.java | 135 ++++++++++ .../MetricsConfigurationProperties.java | 115 +++++++++ .../boot/actuate/metrics/MetricsEndpoint.java | 97 +++++++ .../metrics/RecommendedMeterBinders.java | 51 ++++ .../boot/actuate/metrics/SpringMeters.java | 132 ++++++++++ .../metrics/binder/DataSourceMetrics.java | 65 +++++ .../binder/SpringIntegrationMetrics.java | 127 ++++++++++ .../metrics/export/DurationConverter.java | 33 +++ .../metrics/export/MetricsExporter.java | 26 ++ .../RegistryConfigurationProperties.java | 36 +++ .../StepRegistryConfigurationProperties.java | 50 ++++ .../atlas/AtlasConfigurationProperties.java | 87 +++++++ .../atlas/AtlasExportConfiguration.java | 53 ++++ .../DatadogConfigurationProperties.java | 45 ++++ .../datadog/DatadogExportConfiguration.java | 52 ++++ .../GangliaConfigurationProperties.java | 73 ++++++ .../ganglia/GangliaExportConfiguration.java | 59 +++++ .../GraphiteConfigurationProperties.java | 60 +++++ .../graphite/GraphiteExportConfiguration.java | 59 +++++ .../influx/InfluxConfigurationProperties.java | 62 +++++ .../influx/InfluxExportConfiguration.java | 52 ++++ .../export/jmx/JmxExportConfiguration.java | 53 ++++ .../PrometheusConfigurationProperties.java | 50 ++++ .../PrometheusExportConfiguration.java | 65 +++++ .../prometheus/PrometheusScrapeEndpoint.java | 55 ++++ .../simple/SimpleConfigurationProperties.java | 37 +++ .../simple/SimpleExportConfiguration.java | 43 ++++ .../scheduling/ScheduledMethodMetrics.java | 120 +++++++++ .../metrics/web/ControllerMetrics.java | 191 ++++++++++++++ .../web/MetricsHandlerInterceptor.java | 49 ++++ .../web/MetricsRestTemplateConfiguration.java | 107 ++++++++ .../web/MetricsRestTemplateInterceptor.java | 72 ++++++ .../MetricsServletRequestConfiguration.java | 68 +++++ .../actuate/metrics/web/MetricsWebFilter.java | 60 +++++ .../MetricsWebfluxRequestConfiguration.java | 47 ++++ .../web/RestTemplateTagConfigurer.java | 81 ++++++ .../web/RestTemplateUrlTemplateCapturing.java | 54 ++++ .../web/RestTemplateUrlTemplateHolder.java | 42 ++++ .../metrics/web/RouterFunctionMetrics.java | 94 +++++++ .../metrics/web/WebServletTagConfigurer.java | 93 +++++++ .../metrics/web/WebfluxTagConfigurer.java | 66 +++++ .../main/resources/META-INF/spring.factories | 10 +- .../metrics/MeterRegistryConfigurerTest.java | 63 +++++ .../MetricsConfigurationCompositeTest.java | 55 ++++ .../metrics/MetricsConfigurationTest.java | 125 +++++++++ .../actuate/metrics/MetricsEndpointTest.java | 84 +++++++ .../metrics/binder/DataSourceMetricsTest.java | 85 +++++++ .../PrometheusScrapeEndpointTest.java | 72 ++++++ .../simple/SimpleExportConfigurationTest.java | 57 +++++ .../ExecutorServiceMetricsTest.java | 64 +++++ .../ScheduledMethodMetricsTest.java | 120 +++++++++ .../metrics/web/ControllerMetricsTest.java | 116 +++++++++ ...etricsHandlerInterceptorAutoTimedTest.java | 84 +++++++ .../web/MetricsHandlerInterceptorTest.java | 238 ++++++++++++++++++ .../MetricsRestTemplateInterceptorTest.java | 73 ++++++ .../RestTemplateUrlTemplateCapturingTest.java | 86 +++++++ .../src/test/resources/application.properties | 1 + spring-boot-dependencies/pom.xml | 41 +++ 61 files changed, 4376 insertions(+), 14 deletions(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurer.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsEndpoint.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/RecommendedMeterBinders.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/SpringMeters.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetrics.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/SpringIntegrationMetrics.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/DurationConverter.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricsExporter.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RegistryConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/StepRegistryConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/jmx/JmxExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleConfigurationProperties.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetrics.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/ControllerMetrics.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptor.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptor.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsServletRequestConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebFilter.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebfluxRequestConfiguration.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateTagConfigurer.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturing.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateHolder.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RouterFunctionMetrics.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebServletTagConfigurer.java create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebfluxTagConfigurer.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurerTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationCompositeTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsEndpointTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetricsTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfigurationTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ExecutorServiceMetricsTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetricsTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/ControllerMetricsTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorAutoTimedTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptorTest.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturingTest.java create mode 100644 spring-boot-actuator/src/test/resources/application.properties diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index 37f4d6f366a2..11fa6a42a556 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -33,6 +33,10 @@ com.fasterxml.jackson.core jackson-databind + + io.micrometer + micrometer-core + org.springframework spring-core @@ -62,6 +66,41 @@ lettuce-core true + + io.micrometer + micrometer-atlas-starter + true + + + io.micrometer + micrometer-datadog-starter + true + + + io.micrometer + micrometer-ganglia-starter + true + + + io.micrometer + micrometer-graphite-starter + true + + + io.micrometer + micrometer-influx-starter + true + + + io.micrometer + micrometer-jmx-starter + true + + + io.micrometer + micrometer-prometheus-starter + true + io.searchbox jest @@ -108,6 +147,11 @@ tomcat-jdbc true + + org.aspectj + aspectjweaver + true + org.elasticsearch elasticsearch @@ -314,6 +358,11 @@ jsonassert test + + org.springframework.boot + spring-boot-test-autoconfigure + test + org.springframework.data spring-data-elasticsearch diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java index e5398a1e7c97..c7c98aabdf3e 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java @@ -22,12 +22,14 @@ import java.util.Map; import java.util.function.Supplier; +import io.micrometer.core.instrument.MeterRegistry; import org.flywaydb.core.Flyway; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.audit.AuditEventRepository; import org.springframework.boot.actuate.endpoint.*; import org.springframework.boot.actuate.health.*; import org.springframework.boot.actuate.info.InfoContributor; +import org.springframework.boot.actuate.metrics.MetricsEndpoint; import org.springframework.boot.actuate.trace.InMemoryTraceRepository; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -97,12 +99,13 @@ public LoggersEndpoint loggersEndpoint(LoggingSystem loggingSystem) { return new LoggersEndpoint(loggingSystem); } - // FIXME replace with micrometer metrics endpoint -// @Bean -// @ConditionalOnMissingBean -// @ConditionalOnEnabledEndpoint -// public MetricsEndpoint metricsEndpoint() { -// } + @Bean + @ConditionalOnBean(MeterRegistry.class) + @ConditionalOnMissingBean + @ConditionalOnEnabledEndpoint + public MetricsEndpoint metricsEndpoint(MeterRegistry registry) { + return new MetricsEndpoint(registry); + } @Bean @ConditionalOnMissingBean diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurer.java new file mode 100644 index 000000000000..dd428d0523a5 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurer.java @@ -0,0 +1,36 @@ +/** + * 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.metrics; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * Defines callback methods to customize the Java-based configuration for + * {@link MeterRegistry} implementations. + *

+ * + * Add one or more of these configurers to the application context to customize + * a registry. + * + * Configurers are guaranteed to be applied before any {@link io.micrometer.core.instrument.Meter} + * is registered with the registry. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public interface MeterRegistryConfigurer { + void configureRegistry(MeterRegistry registry); +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfiguration.java new file mode 100644 index 000000000000..926a587a6c00 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfiguration.java @@ -0,0 +1,135 @@ +/** + * 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.metrics; + +import java.util.Collection; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.actuate.metrics.binder.SpringIntegrationMetrics; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.actuate.metrics.export.atlas.AtlasExportConfiguration; +import org.springframework.boot.actuate.metrics.export.datadog.DatadogExportConfiguration; +import org.springframework.boot.actuate.metrics.export.ganglia.GangliaExportConfiguration; +import org.springframework.boot.actuate.metrics.export.graphite.GraphiteExportConfiguration; +import org.springframework.boot.actuate.metrics.export.influx.InfluxExportConfiguration; +import org.springframework.boot.actuate.metrics.export.jmx.JmxExportConfiguration; +import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusExportConfiguration; +import org.springframework.boot.actuate.metrics.export.simple.SimpleExportConfiguration; +import org.springframework.boot.actuate.metrics.scheduling.ScheduledMethodMetrics; +import org.springframework.boot.actuate.metrics.web.MetricsRestTemplateConfiguration; +import org.springframework.boot.actuate.metrics.web.MetricsServletRequestConfiguration; +import org.springframework.boot.actuate.metrics.web.MetricsWebfluxRequestConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.integration.support.management.IntegrationManagementConfigurer; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.binder.MeterBinder; +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; + +/** + * Metrics configuration for Spring 4/Boot 1.x + * + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@EnableConfigurationProperties(MetricsConfigurationProperties.class) +@Import({ + RecommendedMeterBinders.class, + MetricsServletRequestConfiguration.class, + MetricsWebfluxRequestConfiguration.class, + MetricsRestTemplateConfiguration.class, + + // supported monitoring systems + AtlasExportConfiguration.class, + DatadogExportConfiguration.class, + GangliaExportConfiguration.class, + GraphiteExportConfiguration.class, + InfluxExportConfiguration.class, + JmxExportConfiguration.class, + PrometheusExportConfiguration.class, + SimpleExportConfiguration.class, +}) +class MetricsConfiguration { + @ConditionalOnMissingBean(MeterRegistry.class) + @Bean + public CompositeMeterRegistry compositeMeterRegistry(ObjectProvider> exportersProvider) { + CompositeMeterRegistry composite = new CompositeMeterRegistry(); + + if (exportersProvider.getIfAvailable() != null) { + exportersProvider.getIfAvailable().forEach(exporter -> composite.add(exporter.registry())); + } + + return composite; + } + + @Configuration + static class MeterRegistryConfigurationSupport { + public MeterRegistryConfigurationSupport(MeterRegistry registry, + MetricsConfigurationProperties config, + ObjectProvider> binders, + ObjectProvider> registryConfigurers) { + if (registryConfigurers.getIfAvailable() != null) { + registryConfigurers.getIfAvailable().forEach(conf -> conf.configureRegistry(registry)); + } + + if (binders.getIfAvailable() != null) { + binders.getIfAvailable().forEach(binder -> binder.bindTo(registry)); + } + + if (config.getUseGlobalRegistry()) { + Metrics.addRegistry(registry); + } + } + } + + /** + * If AOP is not enabled, scheduled interception will not work. + */ + @Bean + @ConditionalOnClass(name = "org.aspectj.lang.ProceedingJoinPoint") + @ConditionalOnProperty(value = "spring.aop.enabled", havingValue = "true", matchIfMissing = true) + public ScheduledMethodMetrics metricsSchedulingAspect(MeterRegistry registry) { + return new ScheduledMethodMetrics(registry); + } + + @Configuration + @ConditionalOnClass(name = "org.springframework.integration.config.EnableIntegrationManagement") + static class MetricsIntegrationConfiguration { + + @Bean(name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME) + @ConditionalOnMissingBean(value = IntegrationManagementConfigurer.class, name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME, search = SearchStrategy.CURRENT) + public IntegrationManagementConfigurer managementConfigurer() { + IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer(); + configurer.setDefaultCountsEnabled(true); + configurer.setDefaultStatsEnabled(true); + return configurer; + } + + @Bean + public SpringIntegrationMetrics springIntegrationMetrics(IntegrationManagementConfigurer configurer) { + return new SpringIntegrationMetrics(configurer); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfigurationProperties.java new file mode 100644 index 000000000000..eb5b2519d740 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsConfigurationProperties.java @@ -0,0 +1,115 @@ +/** + * 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.metrics; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties("metrics") +public class MetricsConfigurationProperties { + private Web web = new Web(); + + /** + * Determines whether {@link MeterRegistry} implementations configured by Spring should be + * bound to the global static registry on {@link io.micrometer.core.instrument.Metrics}. + * For Spring Boot tests involving metrics, set this to {@code false} to maximize test independence. + * Otherwise, it can be left to {@code true}. + */ + private Boolean useGlobalRegistry = true; + + public Boolean getUseGlobalRegistry() { + return useGlobalRegistry; + } + + public void setUseGlobalRegistry(Boolean useGlobalRegistry) { + this.useGlobalRegistry = useGlobalRegistry; + } + + public static class Web { + /** + * Determines whether every request mapping (WebMVC or Webflux) should be automatically timed. + * If the number of time series emitted from a Spring application grows too large on account + * of request mapping timings, disable this and use {@link io.micrometer.core.annotation.Timed} + * on a per request mapping basis as needed. + */ + private Boolean autoTimeServerRequests = true; + + private String serverRequestsName = "http.server.requests"; + + /** + * Determines whether instrumented server requests ship percentiles histogram buckets by default. + * The default can be overriden by adding {@link io.micrometer.core.annotation.Timed} to a request + * endpoint and setting {@code percentiles} to true. + */ + private Boolean serverRequestPercentiles = false; + + private String clientRequestsName = "http.client.requests"; + + /** + * Determines whether instrumented client requests ship percentiles histogram buckets by default. + */ + private Boolean clientRequestPercentiles = false; + + public Boolean getAutoTimeServerRequests() { + return autoTimeServerRequests; + } + + public void setAutoTimeServerRequests(Boolean autoTimeServerRequests) { + this.autoTimeServerRequests = autoTimeServerRequests; + } + + public void setServerRequestsName(String serverRequestsName) { + this.serverRequestsName = serverRequestsName; + } + + public String getServerRequestsName() { + return serverRequestsName; + } + + public void setClientRequestsName(String clientRequestsName) { + this.clientRequestsName = clientRequestsName; + } + + public String getClientRequestsName() { + return clientRequestsName; + } + + public void setServerRequestPercentiles(Boolean serverRequestPercentiles) { + this.serverRequestPercentiles = serverRequestPercentiles; + } + + public Boolean getServerRequestPercentiles() { + return serverRequestPercentiles; + } + + public void setClientRequestPercentiles(Boolean clientRequestPercentiles) { + this.clientRequestPercentiles = clientRequestPercentiles; + } + + public Boolean getClientRequestPercentiles() { + return clientRequestPercentiles; + } + } + + public Web getWeb() { + return web; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsEndpoint.java new file mode 100644 index 000000000000..6e603af0035e --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/MetricsEndpoint.java @@ -0,0 +1,97 @@ +/** + * 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.metrics; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.StreamSupport.stream; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.boot.endpoint.Endpoint; +import org.springframework.boot.endpoint.ReadOperation; +import org.springframework.boot.endpoint.Selector; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.util.HierarchicalNameMapper; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Endpoint(id = "metrics") +public class MetricsEndpoint { + private final MeterRegistry registry; + private final HierarchicalNameMapper nameMapper = HierarchicalNameMapper.DEFAULT; + + public MetricsEndpoint(MeterRegistry registry) { + this.registry = registry; + } + + @ReadOperation + public List listNames() { + return registry.getMeters().stream().map(m -> m.getId().getName()).collect(toList()); + } + + @ReadOperation + public Map> metric(@Selector String requiredMetricName) { + return registry.find(requiredMetricName).meters() + .stream() + .collect(Collectors.toMap(meter -> nameMapper.toHierarchicalName(meter.getId()), + meter -> stream(meter.measure().spliterator(), false) + .map(ms -> new MeasurementSample(ms.getStatistic(), ms.getValue())) + .collect(toList()))); + } + + static class MeasurementSample { + private Statistic statistic; + private Double value; + + MeasurementSample() { } // for jackson in test + + MeasurementSample(Statistic statistic, Double value) { + this.statistic = statistic; + this.value = value; + } + + public Statistic getStatistic() { + return statistic; + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + this.value = value; + } + + public void setStatistic(Statistic statistic) { + this.statistic = statistic; + } + + @Override + public String toString() { + return "MeasurementSample{" + + "statistic=" + statistic + + ", value=" + value + + '}'; + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/RecommendedMeterBinders.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/RecommendedMeterBinders.java new file mode 100644 index 000000000000..9afaa4858aad --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/RecommendedMeterBinders.java @@ -0,0 +1,51 @@ +/** + * 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.metrics; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.binder.JvmMemoryMetrics; +import io.micrometer.core.instrument.binder.LogbackMetrics; +import io.micrometer.core.instrument.binder.UptimeMetrics; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +class RecommendedMeterBinders { + @Bean + @ConditionalOnMissingBean(JvmMemoryMetrics.class) + public JvmMemoryMetrics jvmMemoryMetrics() { + return new JvmMemoryMetrics(); + } + + @Bean + @ConditionalOnMissingBean(LogbackMetrics.class) + @ConditionalOnClass(name = "ch.qos.logback.classic.Logger") + public LogbackMetrics logbackMetrics() { + return new LogbackMetrics(); + } + + @Bean + @ConditionalOnMissingBean(UptimeMetrics.class) + public UptimeMetrics uptimeMetrics() { + return new UptimeMetrics(); + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/SpringMeters.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/SpringMeters.java new file mode 100644 index 000000000000..e727c3a4fe09 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/SpringMeters.java @@ -0,0 +1,132 @@ +/** + * 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.metrics; + +import static java.util.Arrays.asList; + +import java.util.Collection; + +import javax.sql.DataSource; + +import org.springframework.boot.actuate.metrics.binder.DataSourceMetrics; +import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.binder.ExecutorServiceMetrics; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public class SpringMeters { + /** + * Record metrics on active connections and connection pool utilization. + * + * @param registry The registry to bind metrics to. + * @param dataSource The data source to instrument. + * @param metadataProviders A list of providers from which the instrumentation can look up information about pool usage. + * @param name The name prefix of the metrics. + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented data source, unchanged. The original data source + * is not wrapped or proxied in any way. + */ + public static DataSource monitor(MeterRegistry registry, + DataSource dataSource, + Collection metadataProviders, + String name, + Iterable tags) { + new DataSourceMetrics(dataSource, metadataProviders, name, tags).bindTo(registry); + return dataSource; + } + + /** + * Record metrics on active connections and connection pool utilization. + * + * @param registry The registry to bind metrics to. + * @param dataSource The data source to instrument. + * @param metadataProviders A list of providers from which the instrumentation can look up information about pool usage. + * @param name The name prefix of the metrics + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented data source, unchanged. The original data source + * is not wrapped or proxied in any way. + */ + public static DataSource monitor(MeterRegistry registry, + DataSource dataSource, + Collection metadataProviders, + String name, + Tag... tags) { + return monitor(registry, dataSource, metadataProviders, name, asList(tags)); + } + + /** + * Record metrics on the use of a {@link ThreadPoolTaskExecutor}. + * + * @param registry The registry to bind metrics to. + * @param executor The task executor to instrument. + * @param name The name prefix of the metrics. + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented executor, proxied. + */ + public static ThreadPoolTaskExecutor monitor(MeterRegistry registry, ThreadPoolTaskExecutor executor, String name, Iterable tags) { + ExecutorServiceMetrics.monitor(registry, executor.getThreadPoolExecutor(), name, tags); + return executor; + } + + /** + * Record metrics on the use of a {@link ThreadPoolTaskExecutor}. + * + * @param registry The registry to bind metrics to. + * @param executor The executor to instrument. + * @param name The name prefix of the metrics. + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented executor, proxied. + */ + public static ThreadPoolTaskExecutor monitor(MeterRegistry registry, ThreadPoolTaskExecutor executor, String name, Tag... tags) { + ExecutorServiceMetrics.monitor(registry, executor.getThreadPoolExecutor(), name, tags); + return executor; + } + + /** + * Record metrics on the use of a {@link ThreadPoolTaskExecutor}. + * + * @param registry The registry to bind metrics to. + * @param scheduler The task scheduler to instrument. + * @param name The name prefix of the metrics. + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented scheduler, proxied. + */ + public static ThreadPoolTaskScheduler monitor(MeterRegistry registry, ThreadPoolTaskScheduler scheduler, String name, Iterable tags) { + ExecutorServiceMetrics.monitor(registry, scheduler.getScheduledExecutor(), name, tags); + return scheduler; + } + + /** + * Record metrics on the use of a {@link ThreadPoolTaskExecutor}. + * + * @param registry The registry to bind metrics to. + * @param scheduler The scheduler to instrument. + * @param name The name prefix of the metrics. + * @param tags Tags to apply to all recorded metrics. + * @return The instrumented scheduler, proxied. + */ + public static ThreadPoolTaskScheduler monitor(MeterRegistry registry, ThreadPoolTaskScheduler scheduler, String name, Tag... tags) { + ExecutorServiceMetrics.monitor(registry, scheduler.getScheduledExecutor(), name, tags); + return scheduler; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetrics.java new file mode 100644 index 000000000000..2fb8ab3734a2 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetrics.java @@ -0,0 +1,65 @@ +/** + * 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.metrics.binder; + +import java.util.ArrayList; +import java.util.Collection; + +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadata; +import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; +import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProviders; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.binder.MeterBinder; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public class DataSourceMetrics implements MeterBinder { + private final String name; + private final Iterable tags; + private final DataSourcePoolMetadata poolMetadata; + + // prevents the poolMetadata that we base the gauges on from being garbage collected + private static Collection instrumentedPools = new ArrayList<>(); + + public DataSourceMetrics(DataSource dataSource, Collection metadataProviders, String name, Iterable tags) { + this.name = name; + this.tags = tags; + + DataSourcePoolMetadataProvider provider = new DataSourcePoolMetadataProviders(metadataProviders); + poolMetadata = provider.getDataSourcePoolMetadata(dataSource); + instrumentedPools.add(poolMetadata); + } + + @Override + public void bindTo(MeterRegistry registry) { + if (poolMetadata != null) { + if(poolMetadata.getActive() != null) + registry.gauge(name + ".active.connections", tags, poolMetadata, DataSourcePoolMetadata::getActive); + + if(poolMetadata.getMax() != null) + registry.gauge(name + ".max.connections", tags, poolMetadata, DataSourcePoolMetadata::getMax); + + if(poolMetadata.getMin() != null) + registry.gauge(name + ".min.connections", tags, poolMetadata, DataSourcePoolMetadata::getMin); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/SpringIntegrationMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/SpringIntegrationMetrics.java new file mode 100644 index 000000000000..39de3483f220 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/binder/SpringIntegrationMetrics.java @@ -0,0 +1,127 @@ +/** + * 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.metrics.binder; + +import static java.util.Collections.emptyList; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.integration.support.management.*; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.binder.MeterBinder; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public class SpringIntegrationMetrics implements MeterBinder, SmartInitializingSingleton { + private final Iterable tags; + private Collection registries = new ArrayList<>(); + + private final IntegrationManagementConfigurer configurer; + + public SpringIntegrationMetrics(IntegrationManagementConfigurer configurer) { + this(configurer, emptyList()); + } + + public SpringIntegrationMetrics(IntegrationManagementConfigurer configurer, Iterable tags) { + this.configurer = configurer; + this.tags = tags; + } + + @Override + public void bindTo(MeterRegistry registry) { + registry.gauge(registry.createId("spring.integration.channelNames", tags, "The number of spring integration channels"), + configurer, c -> c.getChannelNames().length); + + registry.gauge(registry.createId("spring.integration.handlerNames", tags, "The number of spring integration handlers"), + configurer, c -> c.getHandlerNames().length); + + registry.gauge(registry.createId("spring.integration.sourceNames", tags, "The number of spring integration sources"), + configurer, c -> c.getSourceNames().length); + + registries.add(registry); + } + + private void addSourceMetrics(MeterRegistry registry) { + for (String source : configurer.getSourceNames()) { + MessageSourceMetrics sourceMetrics = configurer.getSourceMetrics(source); + Iterable tagsWithSource = Tags.concat(tags, "source", source); + registry.more().counter(registry.createId("spring.integration.source.messages", tagsWithSource, "The number of successful handler calls"), + sourceMetrics, MessageSourceMetrics::getMessageCount); + } + } + + private void addHandlerMetrics(MeterRegistry registry) { + for (String handler : configurer.getHandlerNames()) { + MessageHandlerMetrics handlerMetrics = configurer.getHandlerMetrics(handler); + + // TODO could use improvement to dynamically commute the handler name with its ID, which can change after + // creation as shown in the SpringIntegrationApplication sample. + Iterable tagsWithHandler = Tags.concat(tags, "handler", handler); + + registry.more().timeGauge(registry.createId("spring.integration.handler.duration.max", tagsWithHandler, "The maximum handler duration"), + handlerMetrics, TimeUnit.MILLISECONDS, MessageHandlerMetrics::getMaxDuration); + + registry.more().timeGauge(registry.createId("spring.integration.handler.duration.min", tagsWithHandler, "The minimum handler duration"), + handlerMetrics, TimeUnit.MILLISECONDS, MessageHandlerMetrics::getMinDuration); + + registry.more().timeGauge(registry.createId("spring.integration.handler.duration.mean", tagsWithHandler, "The mean handler duration"), + handlerMetrics, TimeUnit.MILLISECONDS, MessageHandlerMetrics::getMeanDuration); + + registry.gauge(registry.createId("spring.integration.handler.activeCount", tagsWithHandler, "The number of active handlers"), + handlerMetrics, MessageHandlerMetrics::getActiveCount); + } + } + + private void addChannelMetrics(MeterRegistry registry) { + for (String channel : configurer.getChannelNames()) { + MessageChannelMetrics channelMetrics = configurer.getChannelMetrics(channel); + Iterable tagsWithChannel = Tags.concat(tags, "channel", channel); + + registry.more().counter(registry.createId("spring.integration.channel.sendErrors", tagsWithChannel, + "The number of failed sends (either throwing an exception or rejected by the channel)"), + channelMetrics, MessageChannelMetrics::getSendErrorCount); + + registry.more().counter(registry.createId("spring.integration.channel.sends", tagsWithChannel, + "The number of successful sends"), + channelMetrics, MessageChannelMetrics::getSendCount); + + if (channelMetrics instanceof PollableChannelManagement) { + registry.more().counter(registry.createId("spring.integration.receives", tagsWithChannel, + "The number of messages received"), + (PollableChannelManagement) channelMetrics, PollableChannelManagement::getReceiveCount); + } + } + } + + @Override + public void afterSingletonsInstantiated() { + // TODO better would be to use a BeanPostProcessor + configurer.afterSingletonsInstantiated(); + registries.forEach(registry -> { + addChannelMetrics(registry); + addHandlerMetrics(registry); + addSourceMetrics(registry); + }); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/DurationConverter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/DurationConverter.java new file mode 100644 index 000000000000..e08896f4f8b5 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/DurationConverter.java @@ -0,0 +1,33 @@ +/** + * 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.metrics.export; + +import java.time.Duration; + +import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; +import org.springframework.core.convert.converter.Converter; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationPropertiesBinding +public class DurationConverter implements Converter { + @Override + public Duration convert(String source) { + return Duration.parse(source); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricsExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricsExporter.java new file mode 100644 index 000000000000..1803fa2875b2 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricsExporter.java @@ -0,0 +1,26 @@ +/** + * 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.metrics.export; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public interface MetricsExporter { + MeterRegistry registry(); +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RegistryConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RegistryConfigurationProperties.java new file mode 100644 index 000000000000..428767bde1a0 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/RegistryConfigurationProperties.java @@ -0,0 +1,36 @@ +/** + * 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.metrics.export; + +import java.util.Properties; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public abstract class RegistryConfigurationProperties { + private Properties props = new Properties(); + + protected abstract String prefix(); + + public String get(String k) { + return props.getProperty(k); + } + + protected void set(String k, Object v) { + props.put(prefix() + "." + k, v.toString()); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/StepRegistryConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/StepRegistryConfigurationProperties.java new file mode 100644 index 000000000000..20a6bdcdcbef --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/StepRegistryConfigurationProperties.java @@ -0,0 +1,50 @@ +/** + * 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.metrics.export; + +import java.time.Duration; + +import io.micrometer.core.instrument.spectator.step.StepRegistryConfig; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public abstract class StepRegistryConfigurationProperties extends RegistryConfigurationProperties implements StepRegistryConfig { + public void setStep(Duration step) { + set("step", step); + } + + public void setEnabled(Boolean enabled) { + set("enabled", enabled); + } + + public void setBatchSize(Integer batchSize) { + set("batchSize", batchSize); + } + + public void setConnectTimeout(Duration connectTimeout) { + set("connectTimeout", connectTimeout); + } + + public void setReadTimeout(Duration readTimeout) { + set("readTimeout", readTimeout); + } + + public void setNumThreads(Integer numThreads) { + set("numThreads", numThreads); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasConfigurationProperties.java new file mode 100644 index 000000000000..7a934e913aed --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasConfigurationProperties.java @@ -0,0 +1,87 @@ +/** + * 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.metrics.export.atlas; + +import java.time.Duration; + +import org.springframework.boot.actuate.metrics.export.RegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import com.netflix.spectator.atlas.AtlasConfig; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.atlas") +public class AtlasConfigurationProperties extends RegistryConfigurationProperties implements AtlasConfig { + public void setStep(Duration step) { + set("step", step); + } + + public void setMeterTTL(Duration meterTTL) { + set("meterTTL", meterTTL); + } + + public void setEnabled(Boolean enabled) { + set("enabled", enabled); + } + + public void setNumThreads(Integer numThreads) { + set("numThreads", numThreads); + } + + public void setUri(String uri) { + set("uri", uri); + } + + public void setLwcEnabled(boolean lwcEnabled) { + set("lwcEnabled", lwcEnabled); + } + + public void setConfigRefreshFrequency(Duration configRefreshFrequency) { + set("configRefreshFrequency", configRefreshFrequency); + } + + public void setConfigTTL(Duration configTTL) { + set("configTTL", configTTL); + } + + public void setConfigUri(String configUri) { + set("configUri", configUri); + } + + public void setEvalUri(String evalUri) { + set("evalUri", evalUri); + } + + public void setConnectTimeout(Duration connectTimeout) { + set("connectTimeout", connectTimeout); + } + + public void setReadTimeout(Duration readTimeout) { + set("readTimeout", readTimeout); + } + + public void setBatchSize(Integer batchSize) { + set("batchSize", batchSize); + } + + @Override + protected String prefix() { + return "atlas"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasExportConfiguration.java new file mode 100644 index 000000000000..a284fb4731b8 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/atlas/AtlasExportConfiguration.java @@ -0,0 +1,53 @@ +/** + * 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.metrics.export.atlas; + +import org.springframework.boot.actuate.metrics.export.DurationConverter; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import com.netflix.spectator.atlas.AtlasConfig; + +import io.micrometer.atlas.AtlasMeterRegistry; +import io.micrometer.core.instrument.Clock; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.atlas.AtlasMeterRegistry") +@Import(DurationConverter.class) +@EnableConfigurationProperties(AtlasConfigurationProperties.class) +public class AtlasExportConfiguration { + @ConditionalOnProperty(value = "metrics.atlas.enabled", matchIfMissing = true) + @Bean + public MetricsExporter atlasExporter(AtlasConfig config, Clock clock) { + return () -> new AtlasMeterRegistry(config, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogConfigurationProperties.java new file mode 100644 index 000000000000..c0214620c723 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogConfigurationProperties.java @@ -0,0 +1,45 @@ +/** + * 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.metrics.export.datadog; + +import org.springframework.boot.actuate.metrics.export.StepRegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import io.micrometer.datadog.DatadogConfig; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.datadog") +public class DatadogConfigurationProperties extends StepRegistryConfigurationProperties implements DatadogConfig { + public DatadogConfigurationProperties() { + set("apiKey", "dummyKey"); // FIXME otherwise tests fail + } + + public void setApiKey(String apiKey) { + set("apiKey", apiKey); + } + + public void setHostTag(String hostTag) { + set("hostTag", hostTag); + } + + @Override + public String prefix() { + return "metrics.datadog"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogExportConfiguration.java new file mode 100644 index 000000000000..6e2c72508d1c --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/datadog/DatadogExportConfiguration.java @@ -0,0 +1,52 @@ +/** + * 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.metrics.export.datadog; + +import org.springframework.boot.actuate.metrics.export.DurationConverter; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.datadog.DatadogConfig; +import io.micrometer.datadog.DatadogMeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.datadog.DatadogMeterRegistry") +@Import(DurationConverter.class) +@EnableConfigurationProperties(DatadogConfigurationProperties.class) +public class DatadogExportConfiguration { + @ConditionalOnProperty(value = "metrics.datadog.enabled", matchIfMissing = true) + @Bean + public MetricsExporter datadogExporter(DatadogConfig config, Clock clock) { + return () -> new DatadogMeterRegistry(config, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaConfigurationProperties.java new file mode 100644 index 000000000000..68497aaa7d03 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaConfigurationProperties.java @@ -0,0 +1,73 @@ +/** + * 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.metrics.export.ganglia; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +import org.springframework.boot.actuate.metrics.export.RegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import info.ganglia.gmetric4j.gmetric.GMetric; +import io.micrometer.ganglia.GangliaConfig; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.ganglia") +public class GangliaConfigurationProperties extends RegistryConfigurationProperties implements GangliaConfig { + public void setStep(Duration step) { + set("step", step); + } + + public void setRateUnits(TimeUnit rateUnits) { + set("rateUnits", rateUnits); + } + + public void setDurationUnits(TimeUnit durationUnits) { + set("durationUnits", durationUnits); + } + + public void setProtocolVersion(String protocolVersion) { + set("protocolVersion", protocolVersion); + } + + public void setAddressingMode(GMetric.UDPAddressingMode addressingMode) { + set("addressingMode", addressingMode); + } + + public void setTtl(Integer ttl) { + set("ttl", ttl); + } + + public void setHost(String host) { + set("host", host); + } + + public void setPort(Integer port) { + set("port", port); + } + + public void setEnabled(Boolean enabled) { + set("enabled", enabled); + } + + @Override + public String prefix() { + return "metrics.ganglia"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaExportConfiguration.java new file mode 100644 index 000000000000..45f3a3cc9e6d --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/ganglia/GangliaExportConfiguration.java @@ -0,0 +1,59 @@ +/** + * 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.metrics.export.ganglia; + +import org.springframework.boot.actuate.metrics.export.DurationConverter; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.util.HierarchicalNameMapper; +import io.micrometer.ganglia.GangliaConfig; +import io.micrometer.ganglia.GangliaMeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.ganglia.GangliaMeterRegistry") +@Import(DurationConverter.class) +@EnableConfigurationProperties(GangliaConfigurationProperties.class) +public class GangliaExportConfiguration { + @ConditionalOnProperty(value = "metrics.ganglia.enabled", matchIfMissing = true) + @Bean + public MetricsExporter gangliaExporter(GangliaConfig config, HierarchicalNameMapper nameMapper, Clock clock) { + return () -> new GangliaMeterRegistry(config, nameMapper, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } + + @ConditionalOnMissingBean + @Bean + public HierarchicalNameMapper hierarchicalNameMapper() { + return HierarchicalNameMapper.DEFAULT; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteConfigurationProperties.java new file mode 100644 index 000000000000..149e994fd49c --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteConfigurationProperties.java @@ -0,0 +1,60 @@ +/** + * 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.metrics.export.graphite; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +import org.springframework.boot.actuate.metrics.export.RegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import io.micrometer.graphite.GraphiteConfig; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.graphite") +public class GraphiteConfigurationProperties extends RegistryConfigurationProperties implements GraphiteConfig { + public void setStep(Duration step) { + set("step", step); + } + + public void setRateUnits(TimeUnit rateUnits) { + set("rateUnits", rateUnits); + } + + public void setDurationUnits(TimeUnit durationUnits) { + set("durationUnits", durationUnits); + } + + public void setHost(String host) { + set("host", host); + } + + public void setPort(Integer port) { + set("port", port); + } + + public void setEnabled(Boolean enabled) { + set("enabled", enabled); + } + + @Override + public String prefix() { + return "metrics.graphite"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteExportConfiguration.java new file mode 100644 index 000000000000..2e2d6979263c --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/graphite/GraphiteExportConfiguration.java @@ -0,0 +1,59 @@ +/** + * 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.metrics.export.graphite; + +import org.springframework.boot.actuate.metrics.export.DurationConverter; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.util.HierarchicalNameMapper; +import io.micrometer.graphite.GraphiteConfig; +import io.micrometer.graphite.GraphiteMeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.graphite.GraphiteMeterRegistry") +@Import(DurationConverter.class) +@EnableConfigurationProperties(GraphiteConfigurationProperties.class) +public class GraphiteExportConfiguration { + @ConditionalOnProperty(value = "metrics.graphite.enabled", matchIfMissing = true) + @Bean + public MetricsExporter graphiteExporter(GraphiteConfig config, HierarchicalNameMapper nameMapper, Clock clock) { + return () -> new GraphiteMeterRegistry(config, nameMapper, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } + + @ConditionalOnMissingBean + @Bean + public HierarchicalNameMapper hierarchicalNameMapper() { + return HierarchicalNameMapper.DEFAULT; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxConfigurationProperties.java new file mode 100644 index 000000000000..63b3edd9ef56 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxConfigurationProperties.java @@ -0,0 +1,62 @@ +/** + * 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.metrics.export.influx; + +import org.springframework.boot.actuate.metrics.export.StepRegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import io.micrometer.influx.InfluxConfig; +import io.micrometer.influx.InfluxConsistency; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.influx") +public class InfluxConfigurationProperties extends StepRegistryConfigurationProperties implements InfluxConfig { + public void setDb(String db) { + set("db", db); + } + + public void setConsistency(InfluxConsistency consistency) { + set("consistency", consistency); + } + + public void setUserName(String userName) { + set("userName", userName); + } + + public void setPassword(String password) { + set("password", password); + } + + public void setRetentionPolicy(String retentionPolicy) { + set("retentionPolicy", retentionPolicy); + } + + public void setUri(String uri) { + set("uri", uri); + } + + public void setCompressed(Boolean compressed) { + set("compressed", compressed); + } + + @Override + public String prefix() { + return "metrics.influx"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxExportConfiguration.java new file mode 100644 index 000000000000..76080157c6e7 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/influx/InfluxExportConfiguration.java @@ -0,0 +1,52 @@ +/** + * 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.metrics.export.influx; + +import org.springframework.boot.actuate.metrics.export.DurationConverter; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.influx.InfluxConfig; +import io.micrometer.influx.InfluxMeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.influx.InfluxMeterRegistry") +@Import(DurationConverter.class) +@EnableConfigurationProperties(InfluxConfigurationProperties.class) +public class InfluxExportConfiguration { + @ConditionalOnProperty(value = "metrics.influx.enabled", matchIfMissing = true) + @Bean + public MetricsExporter influxExporter(InfluxConfig config, Clock clock) { + return () -> new InfluxMeterRegistry(config, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/jmx/JmxExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/jmx/JmxExportConfiguration.java new file mode 100644 index 000000000000..9f4c597a94e7 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/jmx/JmxExportConfiguration.java @@ -0,0 +1,53 @@ +/** + * 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.metrics.export.jmx; + +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.util.HierarchicalNameMapper; +import io.micrometer.jmx.JmxMeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.jmx.JmxMeterRegistry") +public class JmxExportConfiguration { + @ConditionalOnProperty(value = "metrics.jmx.enabled", matchIfMissing = true) + @Bean + public MetricsExporter jmxExporter(HierarchicalNameMapper nameMapper, Clock clock) { + return () -> new JmxMeterRegistry(nameMapper, clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } + + @ConditionalOnMissingBean + @Bean + public HierarchicalNameMapper hierarchicalNameMapper() { + return HierarchicalNameMapper.DEFAULT; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusConfigurationProperties.java new file mode 100644 index 000000000000..077abf81205f --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusConfigurationProperties.java @@ -0,0 +1,50 @@ +/** + * 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.metrics.export.prometheus; + + +import org.springframework.boot.actuate.metrics.export.RegistryConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import io.micrometer.prometheus.PrometheusConfig; + +/** + * Exists solely to aid in autocompletion of Prometheus enablement in .properties and .yml. + * + * @since 2.0.0 + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.prometheus") +public class PrometheusConfigurationProperties extends RegistryConfigurationProperties implements PrometheusConfig { + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setDescriptions(Boolean descriptions) { + set("descriptions", descriptions); + } + + @Override + public String prefix() { + return "metrics.prometheus"; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusExportConfiguration.java new file mode 100644 index 000000000000..b4bdee1153db --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusExportConfiguration.java @@ -0,0 +1,65 @@ +/** + * 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.metrics.export.prometheus; + +import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration; +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import io.prometheus.client.CollectorRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "io.micrometer.prometheus.PrometheusMeterRegistry") +@EnableConfigurationProperties(PrometheusConfigurationProperties.class) +public class PrometheusExportConfiguration { + @ConditionalOnProperty(value = "metrics.prometheus.enabled", matchIfMissing = true) + @Bean + public MetricsExporter prometheusExporter(PrometheusConfig config, CollectorRegistry collectorRegistry, Clock clock) { + return () -> new PrometheusMeterRegistry(config, collectorRegistry, clock); + } + + @ConditionalOnMissingBean + @Bean + public CollectorRegistry collectorRegistry() { + return new CollectorRegistry(true); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } + + @ManagementContextConfiguration + public static class PrometheusScrapeEndpointConfiguration { + @Bean + public PrometheusScrapeEndpoint prometheusEndpoint(CollectorRegistry collectorRegistry) { + return new PrometheusScrapeEndpoint(collectorRegistry); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java new file mode 100644 index 000000000000..9204f72bf3b8 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java @@ -0,0 +1,55 @@ +/** + * 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.metrics.export.prometheus; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +import org.springframework.boot.endpoint.Endpoint; +import org.springframework.boot.endpoint.EndpointExposure; +import org.springframework.boot.endpoint.ReadOperation; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.exporter.common.TextFormat; + +/** + * @since 2.0.0 + * @author Jon Schneider + * + * Spring Boot Actuator endpoint that outputs Prometheus metrics in a format that + * can be scraped by the Prometheus server + */ +@Endpoint(id = "prometheus", exposure = EndpointExposure.WEB) +public class PrometheusScrapeEndpoint { + private final CollectorRegistry collectorRegistry; + + PrometheusScrapeEndpoint(CollectorRegistry collectorRegistry) { + this.collectorRegistry = collectorRegistry; + } + + @ReadOperation(produces = TextFormat.CONTENT_TYPE_004) + public String scrape() { + try { + Writer writer = new StringWriter(); + TextFormat.write004(writer, collectorRegistry.metricFamilySamples()); + return writer.toString(); + } catch (IOException e) { + // This actually never happens since StringWriter::write() doesn't throw any IOException + throw new RuntimeException("Writing metrics failed", e); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleConfigurationProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleConfigurationProperties.java new file mode 100644 index 000000000000..ddf515369758 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleConfigurationProperties.java @@ -0,0 +1,37 @@ +/** + * 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.metrics.export.simple; + + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Exists solely to aid in autocompletion of simple registry enablement in .properties and .yml. + * + * @author Jon Schneider + */ +@ConfigurationProperties(prefix = "metrics.simple") +public class SimpleConfigurationProperties { + private boolean enabled = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfiguration.java new file mode 100644 index 000000000000..6099e487ebf9 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfiguration.java @@ -0,0 +1,43 @@ +/** + * 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.metrics.export.simple; + +import org.springframework.boot.actuate.metrics.export.MetricsExporter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +@Configuration +@EnableConfigurationProperties(SimpleConfigurationProperties.class) +public class SimpleExportConfiguration { + @ConditionalOnProperty(value = "metrics.simple.enabled", matchIfMissing = true) + @ConditionalOnMissingBean(MetricsExporter.class) // steps out of the way the moment any other monitoring system is configured + @Bean + public MetricsExporter simpleExporter(Clock clock) { + return () -> new SimpleMeterRegistry(clock); + } + + @ConditionalOnMissingBean + @Bean + public Clock clock() { + return Clock.SYSTEM; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetrics.java new file mode 100644 index 000000000000..450a7b1866ce --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetrics.java @@ -0,0 +1,120 @@ +/** + * 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.metrics.scheduling; + +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.LongTaskTimer; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.stats.quantile.WindowSketchQuantiles; +import io.micrometer.core.instrument.util.AnnotationUtils; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Aspect +public class ScheduledMethodMetrics { + private static final Log logger = LogFactory.getLog(ScheduledMethodMetrics.class); + + private final MeterRegistry registry; + + public ScheduledMethodMetrics(MeterRegistry registry) { + this.registry = registry; + } + + @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") + public Object timeScheduledOperation(ProceedingJoinPoint pjp) throws Throwable { + Method method = ((MethodSignature) pjp.getSignature()).getMethod(); + String signature = pjp.getSignature().toShortString(); + + if (method.getDeclaringClass().isInterface()) { + try { + method = pjp.getTarget().getClass().getDeclaredMethod(pjp.getSignature().getName(), + method.getParameterTypes()); + } catch (final SecurityException | NoSuchMethodException e) { + logger.warn("Unable to perform metrics timing on " + signature, e); + return pjp.proceed(); + } + } + + Timer shortTaskTimer = null; + LongTaskTimer longTaskTimer = null; + + for (Timed timed : AnnotationUtils.findTimed(method).toArray(Timed[]::new)) { + if(timed.longTask()) + longTaskTimer = registry.more().longTaskTimer(registry.createId(timed.value(), Tags.zip(timed.extraTags()), + "Timer of @Scheduled long task")); + else { + Timer.Builder timerBuilder = Timer.builder(timed.value()) + .tags(timed.extraTags()) + .description("Timer of @Scheduled task"); + + if(timed.quantiles().length > 0) { + timerBuilder = timerBuilder.quantiles(WindowSketchQuantiles.quantiles(timed.quantiles()).create()); + } + + shortTaskTimer = timerBuilder.register(registry); + } + } + + if(shortTaskTimer != null && longTaskTimer != null) { + final Timer finalTimer = shortTaskTimer; + return recordThrowable(longTaskTimer, () -> recordThrowable(finalTimer, pjp::proceed)); + } + else if(shortTaskTimer != null) { + return recordThrowable(shortTaskTimer, pjp::proceed); + } + else if(longTaskTimer != null) { + return recordThrowable(longTaskTimer, pjp::proceed); + } + + return pjp.proceed(); + } + + private Object recordThrowable(LongTaskTimer timer, ThrowableCallable f) throws Throwable { + long id = timer.start(); + try { + return f.call(); + } finally { + timer.stop(id); + } + } + + private Object recordThrowable(Timer timer, ThrowableCallable f) throws Throwable { + long start = registry.config().clock().monotonicTime(); + try { + return f.call(); + } finally { + timer.record(registry.config().clock().monotonicTime() - start, TimeUnit.NANOSECONDS); + } + } + + private interface ThrowableCallable { + Object call() throws Throwable; + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/ControllerMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/ControllerMetrics.java new file mode 100644 index 000000000000..95e066363496 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/ControllerMetrics.java @@ -0,0 +1,191 @@ +/** + * 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.metrics.web; + +import static java.util.stream.Collectors.toSet; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.method.HandlerMethod; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.*; +import io.micrometer.core.instrument.stats.hist.Histogram; +import io.micrometer.core.instrument.stats.quantile.WindowSketchQuantiles; +import io.micrometer.core.instrument.util.AnnotationUtils; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public class ControllerMetrics { + private static final String TIMING_REQUEST_ATTRIBUTE = "micrometer.requestStartTime"; + private static final String HANDLER_REQUEST_ATTRIBUTE = "micrometer.requestHandler"; + private static final String EXCEPTION_ATTRIBUTE = "micrometer.requestException"; + + private static final Log logger = LogFactory.getLog(ControllerMetrics.class); + + private final MeterRegistry registry; + private MetricsConfigurationProperties properties; + private final WebServletTagConfigurer tagConfigurer; + + private final Map longTaskTimerIds = Collections.synchronizedMap(new IdentityHashMap<>()); + + public ControllerMetrics(MeterRegistry registry, + MetricsConfigurationProperties properties, + WebServletTagConfigurer tagConfigurer) { + this.registry = registry; + this.properties = properties; + this.tagConfigurer = tagConfigurer; + } + + public void tagWithException(Throwable t) { + RequestContextHolder.getRequestAttributes().setAttribute(EXCEPTION_ATTRIBUTE, t, RequestAttributes.SCOPE_REQUEST); + } + + public void preHandle(HttpServletRequest request, Object handler) { + request.setAttribute(TIMING_REQUEST_ATTRIBUTE, System.nanoTime()); + request.setAttribute(HANDLER_REQUEST_ATTRIBUTE, handler); + + longTaskTimed(handler).forEach(t -> { + if (t.name == null) { + if (handler instanceof HandlerMethod) { + logger.warn("Unable to perform metrics timing on " + ((HandlerMethod) handler).getShortLogMessage() + ": @Timed annotation must have a value used to name the metric"); + } else { + logger.warn("Unable to perform metrics timing for request " + request.getRequestURI() + ": @Timed annotation must have a value used to name the metric"); + } + return; + } + longTaskTimerIds.put(request, longTaskTimer(t, request, handler).start()); + }); + } + + public void record(HttpServletRequest request, HttpServletResponse response, Throwable ex) { + Long startTime = (Long) request.getAttribute(TIMING_REQUEST_ATTRIBUTE); + Object handler = request.getAttribute(HANDLER_REQUEST_ATTRIBUTE); + + long endTime = System.nanoTime(); + Throwable thrown = ex != null ? ex : (Throwable) request.getAttribute(EXCEPTION_ATTRIBUTE); + + // complete any LongTaskTimer tasks running for this method + longTaskTimed(handler).forEach(t -> { + if (t.name != null) { + longTaskTimer(t, request, handler).stop(longTaskTimerIds.remove(request)); + } + }); + + // record Timer values + timed(handler).forEach(t -> { + Timer.Builder timerBuilder = Timer.builder(t.name) + .tags(tagConfigurer.httpRequestTags(request, response, thrown)) + .tags(t.extraTags) + .description("Timer of servlet request"); + + if (t.quantiles.length > 0) { + timerBuilder = timerBuilder.quantiles(WindowSketchQuantiles.quantiles(t.quantiles).create()); + } + + if (t.percentiles) { + timerBuilder = timerBuilder.histogram(Histogram.percentilesTime()); + } + + timerBuilder.register(registry).record(endTime - startTime, TimeUnit.NANOSECONDS); + }); + } + + private LongTaskTimer longTaskTimer(TimerConfig t, HttpServletRequest request, Object handler) { + Iterable tags = Tags.concat(tagConfigurer.httpLongRequestTags(request, handler), t.extraTags); + return registry.more().longTaskTimer(registry.createId(t.name, tags, "Timer of long servlet request")); + } + + private Set longTaskTimed(Object m) { + if (!(m instanceof HandlerMethod)) + return Collections.emptySet(); + + Set timed = AnnotationUtils.findTimed(((HandlerMethod) m).getMethod()).filter(Timed::longTask) + .map(this::fromAnnotation).collect(toSet()); + if (timed.isEmpty()) { + return AnnotationUtils.findTimed(((HandlerMethod) m).getBeanType()).filter(Timed::longTask) + .map(this::fromAnnotation).collect(toSet()); + } + return timed; + } + + private Set timed(Object m) { + if (!(m instanceof HandlerMethod)) + return Collections.emptySet(); + + Set timed = AnnotationUtils.findTimed(((HandlerMethod) m).getMethod()).filter(t -> !t.longTask()) + .map(this::fromAnnotation).collect(toSet()); + if (timed.isEmpty()) { + timed = AnnotationUtils.findTimed(((HandlerMethod) m).getBeanType()).filter(t -> !t.longTask()) + .map(this::fromAnnotation).collect(toSet()); + if (timed.isEmpty() && properties.getWeb().getAutoTimeServerRequests()) { + return Collections.singleton(new TimerConfig()); + } + } + + return timed; + } + + private class TimerConfig { + String name = properties.getWeb().getServerRequestsName(); + Iterable extraTags = Collections.emptyList(); + boolean longTask = false; + double[] quantiles = new double[0]; + boolean percentiles = properties.getWeb().getServerRequestPercentiles(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TimerConfig that = (TimerConfig) o; + + return name != null ? name.equals(that.name) : that.name == null; + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + } + + private TimerConfig fromAnnotation(Timed timed) { + TimerConfig c = new TimerConfig(); + c.name = timed.value().isEmpty() ? properties.getWeb().getServerRequestsName() : timed.value(); + if(c.longTask && timed.value().isEmpty()) + c.name = null; // the user MUST name long task timers, we don't lump them in with regular timers with the same name + + c.extraTags = Tags.zip(timed.extraTags()); + c.longTask = timed.longTask(); + c.quantiles = timed.quantiles(); + c.percentiles = timed.percentiles(); + return c; + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptor.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptor.java new file mode 100644 index 000000000000..9622436fc2b0 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptor.java @@ -0,0 +1,49 @@ +/** + * 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.metrics.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +/** + * Intercepts incoming HTTP requests and records metrics about execution time and results. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter { + private final ControllerMetrics controllerMetrics; + + public MetricsHandlerInterceptor(ControllerMetrics controllerMetrics) { + this.controllerMetrics = controllerMetrics; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + controllerMetrics.preHandle(request, handler); + return super.preHandle(request, response, handler); + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, + Object handler, Exception ex) throws Exception { + controllerMetrics.record(request, response, ex); + super.afterCompletion(request, response, handler, ex); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateConfiguration.java new file mode 100644 index 000000000000..7227008def0d --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateConfiguration.java @@ -0,0 +1,107 @@ +/** + * 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.metrics.web; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestTemplate; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") +public class MetricsRestTemplateConfiguration { + @Bean + @ConditionalOnMissingBean(RestTemplateTagConfigurer.class) + public RestTemplateTagConfigurer restTemplateTagConfigurer() { + return new RestTemplateTagConfigurer(); + } + + @Bean + public MetricsRestTemplateInterceptor clientHttpRequestInterceptor(MeterRegistry meterRegistry, + RestTemplateTagConfigurer restTemplateTagConfigurer, + MetricsConfigurationProperties properties) { + return new MetricsRestTemplateInterceptor(meterRegistry, restTemplateTagConfigurer, properties); + } + + @Bean + public static BeanPostProcessor restTemplateInterceptorPostProcessor() { + return new MetricsInterceptorPostProcessor(); + } + + private static class MetricsInterceptorPostProcessor + implements BeanPostProcessor, ApplicationContextAware { + private ApplicationContext context; + private MetricsRestTemplateInterceptor interceptor; + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof RestTemplate) { + if (this.interceptor == null) { + this.interceptor = this.context + .getBean(MetricsRestTemplateInterceptor.class); + } + RestTemplate restTemplate = (RestTemplate) bean; + // create a new list as the old one may be unmodifiable (ie Arrays.asList()) + List interceptors = new ArrayList<>(); + interceptors.add(interceptor); + interceptors.addAll(restTemplate.getInterceptors()); + restTemplate.setInterceptors(interceptors); + } + return bean; + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + this.context = context; + } + } + + /** + * If AOP is not enabled, client request interception will still work, but the URI tag + * will always be evaluated to "none". + */ + @Configuration + @ConditionalOnClass(name = {"org.aspectj.lang.ProceedingJoinPoint"}) + @ConditionalOnProperty(value = "spring.aop.enabled", havingValue = "true", matchIfMissing = true) + public static class MetricsRestTemplateAspectConfiguration { + @Bean + public RestTemplateUrlTemplateCapturing restTemplateUrlTemplateCapturingAspect() { + return new RestTemplateUrlTemplateCapturing(); + } + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptor.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptor.java new file mode 100644 index 000000000000..26f50f669bb5 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptor.java @@ -0,0 +1,72 @@ +/** + * 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.metrics.web; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.stats.hist.Histogram; + +/** + * Intercepts RestTemplate requests and records metrics about execution time and results. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public class MetricsRestTemplateInterceptor implements ClientHttpRequestInterceptor { + private final MeterRegistry meterRegistry; + private final RestTemplateTagConfigurer tagProvider; + private final MetricsConfigurationProperties properties; + + public MetricsRestTemplateInterceptor(MeterRegistry meterRegistry, + RestTemplateTagConfigurer tagProvider, + MetricsConfigurationProperties properties) { + this.tagProvider = tagProvider; + this.meterRegistry = meterRegistry; + this.properties = properties; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { + long startTime = System.nanoTime(); + + ClientHttpResponse response = null; + try { + response = execution.execute(request, body); + return response; + } finally { + Timer.Builder builder = Timer.builder(properties.getWeb().getClientRequestsName()) + .tags(tagProvider.clientHttpRequestTags(request, response)) + .description("Timer of RestTemplate operation"); + + if(properties.getWeb().getClientRequestPercentiles()) + builder = builder.histogram(Histogram.percentiles()); + + builder + .register(meterRegistry) + .record(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsServletRequestConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsServletRequestConfiguration.java new file mode 100644 index 000000000000..a9927ae5fe10 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsServletRequestConfiguration.java @@ -0,0 +1,68 @@ +/** + * 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.metrics.web; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * Configures instrumentation of Spring Web MVC servlet-based request mappings. + * + * @since 2.0.0 + * @author Jon Schneider + */ +@Configuration +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +@EnableConfigurationProperties(MetricsConfigurationProperties.class) +public class MetricsServletRequestConfiguration implements WebMvcConfigurer { + @Bean + @ConditionalOnMissingBean(WebServletTagConfigurer.class) + public WebServletTagConfigurer webmvcTagConfigurer() { + return new WebServletTagConfigurer(); + } + + @Bean + public ControllerMetrics controllerMetrics(MeterRegistry registry, + MetricsConfigurationProperties properties, + WebServletTagConfigurer configurer) { + return new ControllerMetrics(registry, properties, configurer); + } + + @Bean + public MetricsHandlerInterceptor webMetricsInterceptor(ControllerMetrics controllerMetrics) { + return new MetricsHandlerInterceptor(controllerMetrics); + } + + @Configuration + public class MetricsServletRequestInterceptorConfiguration implements WebMvcConfigurer { + @Autowired + MetricsHandlerInterceptor handlerInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(handlerInterceptor); + } + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebFilter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebFilter.java new file mode 100644 index 000000000000..e3b8f00a5558 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebFilter.java @@ -0,0 +1,60 @@ +/** + * 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.metrics.web; + +import java.util.concurrent.TimeUnit; + +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; + +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Mono; + +/** + * Intercepts incoming HTTP requests modeled with the Webflux annotation-based programming model. + * + * @author Jon Schneider + */ +public class MetricsWebFilter implements WebFilter { + private final MeterRegistry registry; + private final WebfluxTagConfigurer tagConfigurer; + private final String metricName; + + public MetricsWebFilter(MeterRegistry registry, + WebfluxTagConfigurer tagConfigurer, + String metricName) { + this.registry = registry; + this.tagConfigurer = tagConfigurer; + this.metricName = metricName; + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + return chain.filter(exchange). compose(f -> { + long start = System.nanoTime(); + return f + .doOnSuccess(done -> + registry.timer(metricName, tagConfigurer.httpRequestTags(exchange, null)) + .record(System.nanoTime() - start, TimeUnit.NANOSECONDS) + ) + .doOnError(t -> + registry.timer(metricName, tagConfigurer.httpRequestTags(exchange, t)) + .record(System.nanoTime() - start, TimeUnit.NANOSECONDS) + ); + }); + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebfluxRequestConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebfluxRequestConfiguration.java new file mode 100644 index 000000000000..33f0fa407e99 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/MetricsWebfluxRequestConfiguration.java @@ -0,0 +1,47 @@ +/** + * 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.metrics.web; + +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.MeterRegistry; + +/** + * Configures instrumentation of Spring Webflux MVC annotation-based programming model request mappings. + * + * @since 2.0.0 + * @author Jon Schneider + */ +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) +@Configuration +public class MetricsWebfluxRequestConfiguration { + @Bean + @ConditionalOnMissingBean(WebfluxTagConfigurer.class) + public WebfluxTagConfigurer webfluxTagConfigurer() { + return new WebfluxTagConfigurer(); + } + + @Bean + public MetricsWebFilter webfluxMetrics(MeterRegistry registry, + WebfluxTagConfigurer tagConfigurer, + MetricsConfigurationProperties properties) { + return new MetricsWebFilter(registry, tagConfigurer, properties.getWeb().getServerRequestsName()); + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateTagConfigurer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateTagConfigurer.java new file mode 100644 index 000000000000..c47f255c714e --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateTagConfigurer.java @@ -0,0 +1,81 @@ +/** + * 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.metrics.web; + +import static java.util.Arrays.asList; + +import java.io.IOException; + +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpResponse; + +import io.micrometer.core.instrument.Tag; + +/** + * Defines the default set of tags added to instrumented web requests. It is only necessary to implement + * providers for the programming model(s) you are using. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public class RestTemplateTagConfigurer { + /** + * Supplies default tags to timers monitoring RestTemplate requests. + * + * @param request RestTemplate client HTTP request + * @param response may be null in the event of a client error + * @return a set of tags added to every client HTTP request metric + */ + Iterable clientHttpRequestTags(HttpRequest request, + ClientHttpResponse response) { + return asList(method(request), uri(), status(response), clientName(request)); + } + + public Tag method(HttpRequest request) { + return Tag.of("method", request.getMethod().name()); + } + + public Tag uri() { + String urlTemplate = RestTemplateUrlTemplateHolder.getRestTemplateUrlTemplate(); + if (urlTemplate == null) { + urlTemplate = "none"; + } + + String strippedUrlTemplate = urlTemplate.replaceAll("^https?://[^/]+/", ""); + return Tag.of("uri", strippedUrlTemplate); + } + + public Tag status(ClientHttpResponse response) { + String status; + try { + status = (response == null) ? "CLIENT_ERROR" : ((Integer) response + .getRawStatusCode()).toString(); + } catch (IOException e) { + status = "IO_ERROR"; + } + + return Tag.of("status", status); + } + + public Tag clientName(HttpRequest request) { + String host = request.getURI().getHost(); + if (host == null) { + host = "none"; + } + + return Tag.of("clientName", host); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturing.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturing.java new file mode 100644 index 000000000000..b0de904c243e --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturing.java @@ -0,0 +1,54 @@ +/** + * 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.metrics.web; + +import java.net.URI; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; + +/** + * Captures the still-templated URI because currently the ClientHttpRequestInterceptor + * currently only gives us the means to retrieve the substituted URI. + * + * @since 2.0.0 + * @author Jon Schneider + */ +@Aspect +public class RestTemplateUrlTemplateCapturing { + @Around("execution(* org.springframework.web.client.RestOperations+.*(String, ..))") + Object captureUrlTemplate(ProceedingJoinPoint joinPoint) throws Throwable { + try { + String urlTemplate = (String) joinPoint.getArgs()[0]; + RestTemplateUrlTemplateHolder.setRestTemplateUrlTemplate(urlTemplate); + return joinPoint.proceed(); + } finally { + RestTemplateUrlTemplateHolder.clear(); + } + } + + @Around("execution(* org.springframework.web.client.RestOperations+.*(java.net.URI, ..))") + Object captureUrlTemplateFromURI(ProceedingJoinPoint joinPoint) throws Throwable { + try { + URI urlTemplate = (URI) joinPoint.getArgs()[0]; + RestTemplateUrlTemplateHolder.setRestTemplateUrlTemplate(urlTemplate.toString()); + return joinPoint.proceed(); + } finally { + RestTemplateUrlTemplateHolder.clear(); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateHolder.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateHolder.java new file mode 100644 index 000000000000..728e73e03a6c --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateHolder.java @@ -0,0 +1,42 @@ +/** + * 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.metrics.web; + +import org.springframework.core.NamedThreadLocal; + +/** + * Holding area for the still-templated URI because currently the + * ClientHttpRequestInterceptor only gives us the means to retrieve the substituted URI. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public class RestTemplateUrlTemplateHolder { + private static final ThreadLocal restTemplateUrlTemplateHolder = new NamedThreadLocal( + "Rest Template URL Template"); + + public static String getRestTemplateUrlTemplate() { + return restTemplateUrlTemplateHolder.get(); + } + + public static void setRestTemplateUrlTemplate(String urlTemplate) { + restTemplateUrlTemplateHolder.set(urlTemplate); + } + + public static void clear() { + restTemplateUrlTemplateHolder.remove(); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RouterFunctionMetrics.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RouterFunctionMetrics.java new file mode 100644 index 000000000000..6af40a0ec853 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/RouterFunctionMetrics.java @@ -0,0 +1,94 @@ +/** + * 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.metrics.web; + +import static java.util.Collections.emptyList; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; + +import org.springframework.web.reactive.function.server.HandlerFilterFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; + +/** + * @author Jon Schneider + */ +public class RouterFunctionMetrics { + private final MeterRegistry registry; + private BiFunction> defaultTags = (ServerRequest request, ServerResponse response) -> + response != null ? Arrays.asList(method(request), status(response)) : Collections.singletonList(method(request)); + + public RouterFunctionMetrics(MeterRegistry registry) { + this.registry = registry; + } + + /** + * @param defaultTags Generate a list of tags to apply to the timer. {@code ServerResponse} may be null. + */ + public RouterFunctionMetrics defaultTags(BiFunction> defaultTags) { + this.defaultTags = defaultTags; + return this; + } + + public HandlerFilterFunction timer(String name) { + return timer(name, emptyList()); + } + + public HandlerFilterFunction timer(String name, String... tags) { + return timer(name, Tags.zip(tags)); + } + + public HandlerFilterFunction timer(String name, Iterable tags) { + return (request, next) -> { + final long start = System.nanoTime(); + return next + .handle(request) + .doOnSuccess(response -> { + Iterable allTags = Tags.concat(tags, defaultTags.apply(request, response)); + registry.timer(name, allTags).record(System.nanoTime() - start, TimeUnit.NANOSECONDS); + }) + .doOnError(error -> { + // FIXME how do we get the response under an error condition? + Iterable allTags = Tags.concat(tags, defaultTags.apply(request, null)); + registry.timer(name, allTags).record(System.nanoTime() - start, TimeUnit.NANOSECONDS); + }); + }; + } + + /** + * @param request The HTTP request. + * @return A "method" tag whose value is a capitalized method (e.g. GET). + */ + public static Tag method(ServerRequest request) { + return Tag.of("method", request.method().toString()); + } + + /** + * @param response The HTTP response. + * @return A "status" tag whose value is the numeric status code. + */ + public static Tag status(ServerResponse response) { + return Tag.of("status", response.statusCode().toString()); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebServletTagConfigurer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebServletTagConfigurer.java new file mode 100644 index 000000000000..dd2b3d7f0e90 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebServletTagConfigurer.java @@ -0,0 +1,93 @@ +/** + * 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.metrics.web; + +import static java.util.Arrays.asList; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.HandlerMapping; + +import io.micrometer.core.instrument.Tag; + +/** + * Supplies default tags to meters monitoring the Web MVC server (servlet) programming model. + * + * @since 2.0.0 + * @author Jon Schneider + */ +public class WebServletTagConfigurer { + /** + * Supplies default tags to long task timers. + * + * @param request The HTTP request. + * @param handler The request method that is responsible for handling the request. + * @return A set of tags added to every Spring MVC HTTP request + */ + @SuppressWarnings("unused") // we aren't doing anything with the handler by default + public Iterable httpLongRequestTags(HttpServletRequest request, Object handler) { + return asList(method(request), uri(request)); + } + + /** + * Supplies default tags to the Web MVC server programming model. + * + * @param request The HTTP request. + * @param response The HTTP response. + * @return A set of tags added to every Spring MVC HTTP request. + */ + public Iterable httpRequestTags(HttpServletRequest request, + HttpServletResponse response, + Throwable ex) { + return asList(method(request), uri(request), exception(ex), status(response)); + } + + /** + * @param request The HTTP request. + * @return A "method" tag whose value is a capitalized method (e.g. GET). + */ + public Tag method(HttpServletRequest request) { + return Tag.of("method", request.getMethod()); + } + + /** + * @param response The HTTP response. + * @return A "status" tag whose value is the numeric status code. + */ + public Tag status(HttpServletResponse response) { + return Tag.of("status", ((Integer) response.getStatus()).toString()); + } + + public Tag uri(HttpServletRequest request) { + String uri = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + if (uri == null) { + uri = request.getPathInfo(); + } + if (!StringUtils.hasText(uri)) { + uri = "/"; + } + return Tag.of("uri", uri.isEmpty() ? "root" : uri); + } + + public Tag exception(Throwable exception) { + if (exception != null) { + return Tag.of("exception", exception.getClass().getSimpleName()); + } + return Tag.of("exception", "None"); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebfluxTagConfigurer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebfluxTagConfigurer.java new file mode 100644 index 000000000000..ff4efe042d23 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/WebfluxTagConfigurer.java @@ -0,0 +1,66 @@ +/** + * 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.metrics.web; + +import static java.util.Arrays.asList; + +import org.springframework.http.HttpStatus; +import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.pattern.PathPattern; + +import io.micrometer.core.instrument.Tag; + +/** + * @since 2.0.0 + * @author Jon Schneider + */ +public class WebfluxTagConfigurer { + /** + * Supplies default tags to the WebFlux annotation-based server programming model. + */ + public Iterable httpRequestTags(ServerWebExchange exchange, Throwable exception) { + return asList(method(exchange), uri(exchange), exception(exception), status(exchange)); + } + + public Tag uri(ServerWebExchange exchange) { + PathPattern pathPattern = exchange.getAttributeOrDefault(org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, null); + String rawUri = pathPattern.getPatternString(); + + if (!StringUtils.hasText(rawUri)) { + rawUri = "/"; + } + return Tag.of("uri", rawUri.isEmpty() ? "root" : rawUri); + } + + public Tag method(ServerWebExchange exchange) { + return Tag.of("method", exchange.getRequest().getMethod().toString()); + } + + public Tag status(ServerWebExchange exchange) { + HttpStatus status = exchange.getResponse().getStatusCode(); + if(status == null) + status = HttpStatus.OK; + return Tag.of("status", status.toString()); + } + + public Tag exception(Throwable exception) { + if (exception != null) { + return Tag.of("exception", exception.getClass().getSimpleName()); + } + return Tag.of("exception", "None"); + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/main/resources/META-INF/spring.factories b/spring-boot-actuator/src/main/resources/META-INF/spring.factories index f5f111600357..f93d319fe126 100644 --- a/spring-boot-actuator/src/main/resources/META-INF/spring.factories +++ b/spring-boot-actuator/src/main/resources/META-INF/spring.factories @@ -1,7 +1,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.actuate.autoconfigure.ManagementContextAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.cache.CacheStatisticsAutoConfiguration,\ org.springframework.boot.actuate.cloudfoundry.CloudFoundryActuatorAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.endpoint.infrastructure.EndpointInfrastructureAutoConfiguration,\ @@ -9,15 +8,10 @@ org.springframework.boot.actuate.autoconfigure.endpoint.infrastructure.ServletEn org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.MetricFilterAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.MetricRepositoryAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.MetricsDropwizardAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.MetricsChannelAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.MetricExportAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.metrics.PublicMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.security.ManagementWebSecurityAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.trace.TraceRepositoryAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.trace.TraceWebFilterAutoConfiguration +org.springframework.boot.actuate.autoconfigure.trace.TraceWebFilterAutoConfiguration,\ +org.springframework.boot.actuate.metrics.MetricsConfiguration org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\ org.springframework.boot.actuate.autoconfigure.endpoint.infrastructure.ReactiveEndpointChildManagementContextConfiguration,\ diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurerTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurerTest.java new file mode 100644 index 000000000000..9e1b68eedf00 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MeterRegistryConfigurerTest.java @@ -0,0 +1,63 @@ +/** + * 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.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class MeterRegistryConfigurerTest { + + @Autowired + MeterRegistry registry; + + @Test + public void commonTagsAreAppliedToAutoConfiguredBinders() { + assertThat(registry.find("jvm.memory.used").tags("region", "us-east-1").gauge()).isPresent(); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp { + public static void main(String[] args) { + SpringApplication.run(MetricsApp.class); + } + + @Bean + public MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + + @Bean + public MeterRegistryConfigurer registryConfigurer() { + return registry -> registry.config().commonTags("region", "us-east-1"); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationCompositeTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationCompositeTest.java new file mode 100644 index 000000000000..8d7ae990d131 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationCompositeTest.java @@ -0,0 +1,55 @@ +/** + * 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.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import io.micrometer.graphite.GraphiteMeterRegistry; +import io.micrometer.prometheus.PrometheusMeterRegistry; + +/** + * Validate that the default composite registry is filled with implementations + * available on the classpath + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = { + "metrics.useGlobalRegistry=false", + "metrics.datadog.enabled=false" // this requires an API key +}) +public class MetricsConfigurationCompositeTest { + @Autowired + CompositeMeterRegistry registry; + + @Test + public void compositeContainsImplementationsOnClasspath() { + assertThat(registry.getRegistries()) + .hasAtLeastOneElementOfType(PrometheusMeterRegistry.class) + .hasAtLeastOneElementOfType(GraphiteMeterRegistry.class); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp {} +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationTest.java new file mode 100644 index 000000000000..788421aad6cc --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsConfigurationTest.java @@ -0,0 +1,125 @@ +/** + * 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.metrics; + +import static io.micrometer.core.instrument.Statistic.Count; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.ExpectedCount.once; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.binder.JvmMemoryMetrics; +import io.micrometer.core.instrument.binder.LogbackMetrics; +import io.micrometer.core.instrument.binder.MeterBinder; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class MetricsConfigurationTest { + @Autowired + ApplicationContext context; + + @Autowired + RestTemplate external; + + @Autowired + TestRestTemplate loopback; + + @Autowired + MeterRegistry registry; + + @Test + public void restTemplateIsInstrumented() { + MockRestServiceServer server = MockRestServiceServer.bindTo(external).build(); + server.expect(once(), requestTo("/api/external")).andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess("{\"message\": \"hello\"}", MediaType.APPLICATION_JSON)); + + //noinspection unchecked + assertThat(external.getForObject("/api/external", Map.class)) + .containsKey("message"); + + assertThat(registry.find("http.client.requests").value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void requestMappingIsInstrumented() { + loopback.getForObject("/api/people", Set.class); + + assertThat(registry.find("http.server.requests").value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void automaticallyRegisteredBinders() { + assertThat(context.getBeansOfType(MeterBinder.class).values()) + .hasAtLeastOneElementOfType(LogbackMetrics.class) + .hasAtLeastOneElementOfType(JvmMemoryMetrics.class); + } + + @SpringBootApplication(scanBasePackages = "isolated") + @Import(PersonController.class) + static class MetricsApp { + public static void main(String[] args) { + SpringApplication.run(MetricsApp.class, "--debug"); + } + + @Bean + public MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + } + + @RestController + static class PersonController { + @GetMapping("/api/people") + Set personName() { + return Collections.singleton("Jon"); + } + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsEndpointTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsEndpointTest.java new file mode 100644 index 000000000000..ae841e544b1b --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/MetricsEndpointTest.java @@ -0,0 +1,84 @@ +/** + * 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.metrics; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "metrics.useGlobalRegistry=false", + "endpoints.metrics.web.enabled=true" +}) +public class MetricsEndpointTest { + @Autowired + TestRestTemplate loopback; + + ObjectMapper mapper = new ObjectMapper(); + + @Test + public void listNames() throws IOException { + List names = mapper.readValue(loopback.getForObject("/application/metrics", String.class), + new TypeReference>() {}); + + assertThat(names).contains("jvm.memory.used"); + } + + @Test + public void selectByName() throws IOException { + Map> measurements = mapper.readValue(loopback.getForObject("/application/metrics/jvm.memory.used", String.class), + new TypeReference>>() {}); + + System.out.println(measurements); + + // one entry per tag combination + assertThat(measurements).containsKeys( + "jvm_memory_used.area.nonheap.id.Compressed_Class_Space", + "jvm_memory_used.area.heap.id.PS_Old_Gen"); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp { + @Bean + public MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetricsTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetricsTest.java new file mode 100644 index 000000000000..cdb2c3b7c188 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/binder/DataSourceMetricsTest.java @@ -0,0 +1,85 @@ +/** + * 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.metrics.binder; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.sql.SQLException; +import java.util.Collection; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.metrics.SpringMeters; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = { + "spring.datasource.generate-unique-name=true", + "management.security.enabled=false", + "metrics.useGlobalRegistry=false" +}) +public class DataSourceMetricsTest { + @Autowired + DataSource dataSource; + + @Autowired + MeterRegistry registry; + + @Test + public void dataSourceIsInstrumented() throws SQLException, InterruptedException { + dataSource.getConnection().getMetaData(); + assertThat(registry.find("data.source.max.connections").meter()).isPresent(); + } + + @SpringBootApplication(scanBasePackages = "isolated") + @Import(DataSourceConfig.class) + static class MetricsApp { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + } + + @Configuration + static class DataSourceConfig { + public DataSourceConfig(DataSource dataSource, + Collection metadataProviders, + MeterRegistry registry) { + SpringMeters.monitor( + registry, + dataSource, + metadataProviders, + "data.source"); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointTest.java new file mode 100644 index 000000000000..298a2ccc1412 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointTest.java @@ -0,0 +1,72 @@ +/** + * 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.metrics.export.prometheus; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.springframework.http.HttpHeaders.CONTENT_TYPE; + +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.context.annotation.Bean; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import io.prometheus.client.CollectorRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "metrics.useGlobalRegistry=false", + "endpoints.prometheus.web.enabled=true" +}) +public class PrometheusScrapeEndpointTest { + @Autowired + TestRestTemplate loopback; + + @Test + public void scrapeHasContentTypeText004() { + ResponseEntity response = loopback.getForEntity("/application/prometheus", String.class); + AssertionsForClassTypes.assertThat(response) + .satisfies(r -> AssertionsForClassTypes.assertThat(r.getStatusCode().value()).isEqualTo(200)) + .satisfies(r -> assertThat(r.getHeaders().get(CONTENT_TYPE)) + .hasOnlyOneElementSatisfying(type -> AssertionsForClassTypes.assertThat(type).contains("0.0.4"))); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp { + @Bean + public CollectorRegistry promRegistry() { + return new CollectorRegistry(true); + } + + @Bean + public MeterRegistry registry(CollectorRegistry registry) { + return new PrometheusMeterRegistry(k -> null, registry, Clock.SYSTEM); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfigurationTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfigurationTest.java new file mode 100644 index 000000000000..b761cccecbe1 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/simple/SimpleExportConfigurationTest.java @@ -0,0 +1,57 @@ +/** + * 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.metrics.export.simple; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = { + "metrics.atlas.enabled=false", + "metrics.prometheus.enabled=false", + "metrics.datadog.enabled=false", + "metrics.ganglia.enabled=false", + "metrics.graphite.enabled=false", + "metrics.influx.enabled=false", + "metrics.jmx.enabled=false" +}) +public class SimpleExportConfigurationTest { + @Autowired + CompositeMeterRegistry registry; + + @Test + public void simpleMeterRegistryIsInTheCompositeWhenNoOtherRegistryIs() { + assertThat(registry.getRegistries()) + .hasAtLeastOneElementOfType(SimpleMeterRegistry.class); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp {} +} \ No newline at end of file diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ExecutorServiceMetricsTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ExecutorServiceMetricsTest.java new file mode 100644 index 000000000000..445762ca75e6 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ExecutorServiceMetricsTest.java @@ -0,0 +1,64 @@ +/** + * 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.metrics.scheduling; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.actuate.metrics.SpringMeters; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + * @author Clint Checketts + */ +public class ExecutorServiceMetricsTest { + private MeterRegistry registry; + + @Before + public void before() { + registry = new SimpleMeterRegistry(); + } + + @Test + public void threadPoolTaskExecutor() { + ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor(); + exec.initialize(); + + SpringMeters.monitor(registry, exec, "exec"); + assertThreadPoolExecutorMetrics("exec"); + } + + @Test + public void taskScheduler() { + ThreadPoolTaskScheduler sched = new ThreadPoolTaskScheduler(); + sched.initialize(); + + SpringMeters.monitor(registry, sched, "sched"); + assertThreadPoolExecutorMetrics("sched"); + } + + private void assertThreadPoolExecutorMetrics(String name) { + assertThat(registry.find(name + ".completed").meter()).isPresent(); + assertThat(registry.find(name + ".queued").gauge()).isPresent(); + assertThat(registry.find(name + ".pool").gauge()).isPresent(); + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetricsTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetricsTest.java new file mode 100644 index 000000000000..80d5476ef2fa --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/scheduling/ScheduledMethodMetricsTest.java @@ -0,0 +1,120 @@ +/** + * 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.metrics.scheduling; + +import static io.micrometer.core.instrument.Statistic.Count; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.concurrent.CountDownLatch; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class ScheduledMethodMetricsTest { + + static CountDownLatch longTaskStarted = new CountDownLatch(1); + static CountDownLatch longTaskShouldComplete = new CountDownLatch(1); + + static CountDownLatch shortBeepsExecuted = new CountDownLatch(1); + + @Autowired + MeterRegistry registry; + + @Autowired + ThreadPoolTaskScheduler scheduler; + + @Test + public void shortTasksAreInstrumented() throws InterruptedException { + shortBeepsExecuted.await(); + while(scheduler.getActiveCount() > 0) {} + + assertThat(registry.find("beeper").value(Count, 1.0).timer()).isPresent(); + assertThat(registry.find("beeper").tags("quantile", "0.5").gauge()).isNotEmpty(); + assertThat(registry.find("beeper").tags("quantile", "0.95").gauge()).isNotEmpty(); + } + + @Test + public void longTasksAreInstrumented() throws InterruptedException { + longTaskStarted.await(); + + assertThat(registry.find("long.beep").value(Count, 1.0).longTaskTimer()).isPresent(); + + // make sure longBeep continues running until we have a chance to observe it in the active state + longTaskShouldComplete.countDown(); + while(scheduler.getActiveCount() > 0) {} + + assertThat(registry.find("long.beep").value(Count, 0.0).longTaskTimer()).isPresent(); + } + + @SpringBootApplication + @EnableScheduling + static class MetricsApp { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + + @Bean + ThreadPoolTaskScheduler scheduler() { + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + // this way, executing longBeep doesn't block the short tasks from running + scheduler.setPoolSize(6); + return scheduler; + } + + @Timed(value = "long.beep", longTask = true) + @Scheduled(fixedDelay = 100_000) + void longBeep() throws InterruptedException { + longTaskStarted.countDown(); + longTaskShouldComplete.await(); + System.out.println("beep"); + } + + @Timed(value = "beeper", quantiles = {0.5, 0.95}) + @Scheduled(fixedDelay = 100_000) + void shortBeep() { + shortBeepsExecuted.countDown(); + System.out.println("beep"); + } + + @Timed // not instrumented because @Timed lacks a metric name + @Scheduled(fixedDelay = 100_000) + void noMetricName() { + System.out.println("beep"); + } + + @Scheduled(fixedDelay = 100_000) // not instrumented because it isn't @Timed + void notTimed() { + System.out.println("beep"); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/ControllerMetricsTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/ControllerMetricsTest.java new file mode 100644 index 000000000000..738d8ff988ca --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/ControllerMetricsTest.java @@ -0,0 +1,116 @@ +/** + * 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.metrics.web; + +import static io.micrometer.core.instrument.Statistic.Count; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.annotation.*; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = ControllerMetricsTest.App.class) +@WebMvcTest(ControllerMetricsTest.Controller1.class) +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class ControllerMetricsTest { + @Autowired + private MockMvc mvc; + + @Autowired + private SimpleMeterRegistry registry; + + @Test + public void handledExceptionIsRecordedInMetricTag() throws Exception { + assertThatCode(() -> mvc.perform(get("/api/handledError")).andExpect(status().is5xxServerError())); + assertThat(registry.find("http.server.requests").tags("exception", "Exception1") + .value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void rethrownExceptionIsRecordedInMetricTag() throws Exception { + assertThatCode(() -> mvc.perform(get("/api/rethrownError")).andExpect(status().is5xxServerError())); + assertThat(registry.find("http.server.requests").tags("exception", "Exception2") + .value(Count, 1.0).timer()).isPresent(); + } + + @SpringBootApplication(scanBasePackages = "isolated") + @Import(Controller1.class) + static class App { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + } + + static class Exception1 extends RuntimeException {} + static class Exception2 extends RuntimeException {} + + @ControllerAdvice + static class CustomExceptionHandler { + @Autowired + ControllerMetrics metrics; + + @ExceptionHandler + ResponseEntity handleError(Exception1 ex) throws Throwable { + metrics.tagWithException(ex); + return new ResponseEntity<>("this is a custom exception body", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler + ResponseEntity rethrowError(Exception2 ex) throws Throwable { + throw ex; + } + } + + @RestController + @RequestMapping("/api") + @Timed + static class Controller1 { + @Bean + public CustomExceptionHandler controllerAdvice() { + return new CustomExceptionHandler(); + } + + @GetMapping("/handledError") + public String handledError() { + throw new Exception1(); + } + + @GetMapping("/rethrownError") + public String rethrownError() { + throw new Exception2(); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorAutoTimedTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorAutoTimedTest.java new file mode 100644 index 000000000000..73c33b69f69e --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorAutoTimedTest.java @@ -0,0 +1,84 @@ +/** + * 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.metrics.web; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * Metrics are recorded on server requests when + * {@link MetricsConfigurationProperties.Web#autoTimeServerRequests} is true. + * It is true by default. + * + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = MetricsHandlerInterceptorAutoTimedTest.App.class) +@WebMvcTest({MetricsHandlerInterceptorAutoTimedTest.Controller.class}) +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class MetricsHandlerInterceptorAutoTimedTest { + @Autowired + MockMvc mvc; + + @Autowired + MeterRegistry registry; + + @Test + public void metricsCanBeAutoTimed() throws Exception { + mvc.perform(get("/api/10")).andExpect(status().isOk()); + assertThat(registry.find("http.server.requests").tags("status", "200").timer()) + .hasValueSatisfying(t -> assertThat(t.count()).isEqualTo(1)); + } + + @SpringBootApplication(scanBasePackages = "isolated") + @Import({ Controller.class }) + static class App { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + } + + @RestController + @RequestMapping("/api") + static class Controller { + @GetMapping("/{id}") + public String successful(@PathVariable Long id) { + return id.toString(); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorTest.java new file mode 100644 index 000000000000..293442487561 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsHandlerInterceptorTest.java @@ -0,0 +1,238 @@ +/** + * 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.metrics.web; + +import static io.micrometer.core.instrument.Statistic.Count; +import static java.util.stream.StreamSupport.stream; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = MetricsHandlerInterceptorTest.App.class) +@WebMvcTest({MetricsHandlerInterceptorTest.Controller1.class, MetricsHandlerInterceptorTest.Controller2.class}) +@TestPropertySource(properties = { + "metrics.useGlobalRegistry=false", + "metrics.web.autoTimeServerRequests=false" +}) +public class MetricsHandlerInterceptorTest { + @Autowired + MockMvc mvc; + + @Autowired + MeterRegistry registry; + + static CountDownLatch longRequestCountDown = new CountDownLatch(1); + + @Test + public void timedMethod() throws Exception { + mvc.perform(get("/api/c1/10")).andExpect(status().isOk()); + assertThat(registry.find("http.server.requests").tags("status", "200", "uri", "/api/c1/{id}", "public", "true") + .value(Count, 1.0).timer()).isPresent(); + } + + @SuppressWarnings("unchecked") + @Test + public void untimedMethod() throws Exception { + mvc.perform(get("/api/c1/untimed/10")).andExpect(status().isOk()); + assertThat(registry.find("http.server.requests").tags("uri", "/api/c1/untimed/10").timer()).isEmpty(); + } + + @Test + public void timedControllerClass() throws Exception { + mvc.perform(get("/api/c2/10")).andExpect(status().isOk()); + assertThat(registry.find("http.server.requests").tags("status", "200").timer()) + .hasValueSatisfying(t -> assertThat(t.count()).isEqualTo(1)); + } + + @Test + public void badClientRequest() throws Exception { + mvc.perform(get("/api/c1/oops")).andExpect(status().is4xxClientError()); + assertThat(registry.find("http.server.requests").tags("status", "400").timer()) + .hasValueSatisfying(t -> assertThat(t.count()).isEqualTo(1)); + } + + @Test + public void unhandledError() throws Exception { + assertThatCode(() -> mvc.perform(get("/api/c1/unhandledError/10")).andExpect(status().isOk())) + .hasCauseInstanceOf(RuntimeException.class); + assertThat(registry.find("http.server.requests").tags("exception", "RuntimeException") + .value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void longRunningRequest() throws Exception { + MvcResult result = mvc.perform(get("/api/c1/long/10")) + .andExpect(request().asyncStarted()) + .andReturn(); + + // while the mapping is running, it contributes to the activeTasks count + assertThat(registry.find("my.long.request").tags("region", "test") + .value(Count, 1.0).longTaskTimer()).isPresent(); + + // once the mapping completes, we can gather information about status, etc. + longRequestCountDown.countDown(); + + mvc.perform(asyncDispatch(result)).andExpect(status().isOk()); + + assertThat(registry.find("http.server.requests").tags("status", "200") + .value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void endpointThrowsError() throws Exception { + mvc.perform(get("/api/c1/error/10")).andExpect(status().is4xxClientError()); + assertThat(registry.find("http.server.requests").tags("status", "422") + .value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void regexBasedRequestMapping() throws Exception { + mvc.perform(get("/api/c1/regex/.abc")).andExpect(status().isOk()); + assertThat(registry.find("http.server.requests").tags("uri", "/api/c1/regex/{id:\\.[a-z]+}") + .value(Count, 1.0).timer()).isPresent(); + } + + @Test + public void recordQuantiles() throws Exception { + mvc.perform(get("/api/c1/quantiles/10")).andExpect(status().isOk()); + + assertThat(registry.find("http.server.requests").tags("quantile", "0.5").gauge()).isNotEmpty(); + assertThat(registry.find("http.server.requests").tags("quantile", "0.95").gauge()).isNotEmpty(); + } + + @Test + public void recordPercentiles() throws Exception { + mvc.perform(get("/api/c1/percentiles/10")).andExpect(status().isOk()); + + assertThat(registry.find("http.server.requests").meters().stream() + .flatMap(m -> stream(m.getId().getTags().spliterator(), false)) + .map(Tag::getKey)).contains("bucket"); + } + + @SpringBootApplication(scanBasePackages = "isolated") + @Import({Controller1.class, Controller2.class}) + static class App { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + } + + @RestController + @RequestMapping("/api/c1") + static class Controller1 { + @Timed(extraTags = {"public", "true"}) + @GetMapping("/{id}") + public String successfulWithExtraTags(@PathVariable Long id) { + return id.toString(); + } + + @Timed // contains dimensions for status, etc. that can't be known until after the response is sent + @Timed(value = "my.long.request", extraTags = {"region", "test"}, longTask = true) // in progress metric + @GetMapping("/long/{id}") + public Callable takesLongTimeToSatisfy(@PathVariable Long id) { + return () -> { + try { + longRequestCountDown.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return id.toString(); + }; + } + + @GetMapping("/untimed/{id}") + public String successfulButUntimed(@PathVariable Long id) { + return id.toString(); + } + + @Timed + @GetMapping("/error/{id}") + public String alwaysThrowsException(@PathVariable Long id) { + throw new IllegalStateException("Boom on $id!"); + } + + @Timed + @GetMapping("/unhandledError/{id}") + public String alwaysThrowsUnhandledException(@PathVariable Long id) { + throw new RuntimeException("Boom on $id!"); + } + + @Timed + @GetMapping("/regex/{id:\\.[a-z]+}") + public String successfulRegex(@PathVariable String id) { + return id; + } + + @Timed(quantiles = {0.5, 0.95}) + @GetMapping("/quantiles/{id}") + public String quantiles(@PathVariable String id) { + return id; + } + + @Timed(percentiles = true) + @GetMapping("/percentiles/{id}") + public String percentiles(@PathVariable String id) { + return id; + } + + @ExceptionHandler(value = IllegalStateException.class) + @ResponseStatus(code = HttpStatus.UNPROCESSABLE_ENTITY) + ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) { + return new ModelAndView("myerror"); + } + } + + @RestController + @Timed + @RequestMapping("/api/c2") + static class Controller2 { + @GetMapping("/{id}") + public String successful(@PathVariable Long id) { + return id.toString(); + } + } +} \ No newline at end of file diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptorTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptorTest.java new file mode 100644 index 000000000000..470144afc5a6 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/MetricsRestTemplateInterceptorTest.java @@ -0,0 +1,73 @@ +/** + * 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.metrics.web; + +import static io.micrometer.core.instrument.Statistic.Count; +import static java.util.Collections.singletonList; +import static java.util.stream.StreamSupport.stream; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; +import org.springframework.boot.actuate.metrics.MetricsConfigurationProperties; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.client.match.MockRestRequestMatchers; +import org.springframework.test.web.client.response.MockRestResponseCreators; +import org.springframework.web.client.RestTemplate; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * @author Jon Schneider + */ +public class MetricsRestTemplateInterceptorTest { + @Test + public void interceptRestTemplate() { + MeterRegistry registry = new SimpleMeterRegistry(); + + RestTemplate restTemplate = new RestTemplate(); + + MetricsConfigurationProperties properties = new MetricsConfigurationProperties(); + properties.getWeb().setClientRequestPercentiles(true); + + restTemplate.setInterceptors(singletonList(new MetricsRestTemplateInterceptor( + registry, new RestTemplateTagConfigurer(), + properties + ))); + + MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); + mockServer.expect(MockRestRequestMatchers.requestTo("/test/123")) + .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) + .andRespond(MockRestResponseCreators.withSuccess("OK", MediaType.APPLICATION_JSON)); + + String s = restTemplate.getForObject("/test/{id}", String.class, 123); + + // the uri requires AOP to determine + assertThat(registry.find("http.client.requests").tags("method", "GET", "uri", "none", "status", "200") + .value(Count, 1.0).timer()).isPresent(); + + assertThat(registry.find("http.client.requests").meters().stream() + .flatMap(m -> stream(m.getId().getTags().spliterator(), false)) + .map(Tag::getKey)).contains("bucket"); + + assertThat(s).isEqualTo("OK"); + + mockServer.verify(); + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturingTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturingTest.java new file mode 100644 index 000000000000..7f9d3433e623 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/RestTemplateUrlTemplateCapturingTest.java @@ -0,0 +1,86 @@ +/** + * 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.metrics.web; + +import static io.micrometer.core.instrument.Statistic.Count; +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.client.match.MockRestRequestMatchers; +import org.springframework.test.web.client.response.MockRestResponseCreators; +import org.springframework.web.client.RestTemplate; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = "metrics.useGlobalRegistry=false") +public class RestTemplateUrlTemplateCapturingTest { + @Autowired + RestTemplate restTemplate; + + @Autowired + MeterRegistry registry; + + @Test + public void urlCaptured() throws URISyntaxException { + MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); + mockServer.expect(ExpectedCount.times(2), MockRestRequestMatchers.requestTo("/test/123")) + .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) + .andRespond(MockRestResponseCreators.withSuccess("OK", MediaType.APPLICATION_JSON)); + + restTemplate.getForObject("/test/{id}", String.class, "123"); + + assertThat(registry.find("http.client.requests").tags("uri", "/test/{id}") + .value(Count, 1.0).timer()).isPresent(); + + // this would be an inappropriate way to use RestTemplate, as the unparameterized URI will be used + // as a tag value, potentially causing dimensional explosion + restTemplate.getForObject(new URI("/test/123"), String.class); + + // issue #98 + assertThat(registry.find("http.client.requests").tags("uri", "/test/123") + .value(Count, 1.0).timer()).isPresent(); + } + + @SpringBootApplication(scanBasePackages = "isolated") + static class MetricsApp { + @Bean + public MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + } +} diff --git a/spring-boot-actuator/src/test/resources/application.properties b/spring-boot-actuator/src/test/resources/application.properties new file mode 100644 index 000000000000..9449319d9038 --- /dev/null +++ b/spring-boot-actuator/src/test/resources/application.properties @@ -0,0 +1 @@ +metrics.datadog.apiKey=thisIsAFakeKey \ No newline at end of file diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index b6853d39955f..3c368803f4d3 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -130,6 +130,7 @@ 1.2.3 1.16.18 2.1.1 + 0.11.0.RELEASE 6.2.1.jre8 2.9.0 1.5.0 @@ -826,6 +827,46 @@ lettuce-core ${lettuce.version} + + io.micrometer + micrometer-core + ${micrometer.version} + + + io.micrometer + micrometer-atlas-starter + ${micrometer.version} + + + io.micrometer + micrometer-datadog-starter + ${micrometer.version} + + + io.micrometer + micrometer-influx-starter + ${micrometer.version} + + + io.micrometer + micrometer-ganglia-starter + ${micrometer.version} + + + io.micrometer + micrometer-graphite-starter + ${micrometer.version} + + + io.micrometer + micrometer-jmx-starter + ${micrometer.version} + + + io.micrometer + micrometer-prometheus-starter + ${micrometer.version} + io.netty netty-bom