Refactor annotations for metric export
Users can add @ExportMetric[Reader,Writer] to readers and writers that they want to participate in the default exporter. There is also still an @ActuatorMetricWriter that is used for the legacy (non-Java8) Gauge and CounterServices.
This commit is contained in:
parent
80ff92919c
commit
8a83bd12bd
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.autoconfigure;
|
||||
|
||||
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
|
||||
*/
|
||||
@Qualifier
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
|
||||
ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface ExportMetricReader {
|
||||
|
||||
}
|
||||
|
|
@ -26,8 +26,8 @@ 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).
|
||||
* Qualifier annotation for a metric repository that is to be used to export metrics from
|
||||
* the {@link ExportMetricReader} readers.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
|
@ -37,6 +37,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface ActuatorMetricReader {
|
||||
public @interface ExportMetricWriter {
|
||||
|
||||
}
|
||||
|
|
@ -47,17 +47,14 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
|||
public class MetricExportAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
@ExportMetricWriter
|
||||
private Map<String, MetricWriter> writers = Collections.emptyMap();
|
||||
|
||||
@Autowired
|
||||
private MetricExportProperties metrics;
|
||||
|
||||
@Autowired(required = false)
|
||||
@ActuatorMetricWriter
|
||||
private List<MetricWriter> actuatorMetrics = Collections.emptyList();
|
||||
|
||||
@Autowired(required = false)
|
||||
@ActuatorMetricReader
|
||||
@ExportMetricReader
|
||||
private List<MetricReader> readers;
|
||||
|
||||
@Autowired(required = false)
|
||||
|
|
@ -77,11 +74,6 @@ public class MetricExportAutoConfiguration {
|
|||
|
||||
if (reader != null) {
|
||||
writers.putAll(this.writers);
|
||||
for (String name : this.writers.keySet()) {
|
||||
if (this.actuatorMetrics.contains(writers.get(name))) {
|
||||
writers.remove(name);
|
||||
}
|
||||
}
|
||||
MetricExporters exporters = new MetricExporters(reader, writers, this.metrics);
|
||||
return exporters;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public class MetricRepositoryAutoConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ActuatorMetricReader
|
||||
@ExportMetricReader
|
||||
@ConditionalOnMissingBean
|
||||
public BufferMetricReader actuatorMetricReader(CounterBuffers counters,
|
||||
GaugeBuffers gauges) {
|
||||
|
|
@ -151,7 +151,7 @@ public class MetricRepositoryAutoConfiguration {
|
|||
static class LegacyMetricRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ActuatorMetricReader
|
||||
@ExportMetricReader
|
||||
@ActuatorMetricWriter
|
||||
public InMemoryMetricRepository actuatorMetricRepository() {
|
||||
return new InMemoryMetricRepository();
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ import org.springframework.lang.UsesJava7;
|
|||
public class PublicMetricsAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
@ActuatorMetricReader
|
||||
@ExportMetricReader
|
||||
private List<MetricReader> metricReaders = Collections.emptyList();
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -208,8 +208,14 @@ class Trigger {
|
|||
*/
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ public class MetricExportAutoConfigurationTests {
|
|||
public static class WriterConfig {
|
||||
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
public MetricWriter writer() {
|
||||
return Mockito.mock(MetricWriter.class);
|
||||
}
|
||||
|
|
@ -126,6 +127,7 @@ public class MetricExportAutoConfigurationTests {
|
|||
public static class MetricEndpointConfiguration {
|
||||
|
||||
@Bean
|
||||
@ExportMetricReader
|
||||
public MetricsEndpointMetricReader endpointReader() {
|
||||
return Mockito.mock(MetricsEndpointMetricReader.class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -912,12 +912,18 @@ used by default if you are on Java 8 or if you are using Dropwizard metrics.
|
|||
[[production-ready-metric-writers]]
|
||||
=== Metric writers, exporters and aggregation
|
||||
|
||||
Spring Boot provides a couple of implementations of a marker interface called `Exporter`
|
||||
which can be used to copy metric readings from the in-memory buffers to a place where they
|
||||
can be analysed and displayed. Indeed, if you provide a `@Bean` that implements the
|
||||
`MetricWriter` interface, then it will automatically be hooked up to an `Exporter` and fed
|
||||
metric updates every 5 seconds (configured via `spring.metrics.export.delayMillis`) via a
|
||||
`@Scheduled` annotation in `MetricRepositoryAutoConfiguration`.
|
||||
Spring Boot provides a couple of implementations of a marker interface
|
||||
called `Exporter` which can be used to copy metric readings from the
|
||||
in-memory buffers to a place where they can be analysed and
|
||||
displayed. Indeed, if you provide a `@Bean` that implements the
|
||||
`MetricWriter` interface and mark it `@ExportMetricWriter`, then it
|
||||
will automatically be hooked up to an `Exporter` and fed metric
|
||||
updates every 5 seconds (configured via
|
||||
`spring.metrics.export.delayMillis`) via a `@Scheduled` annotation in
|
||||
`MetricRepositoryAutoConfiguration`. In addition, any `MetricReader`
|
||||
that you define and mark as `@ExportMetricReader` will have its values
|
||||
exported by the default exporter.
|
||||
|
||||
|
||||
The default exporter is a `MetricCopyExporter` which tries to optimize
|
||||
itself by not copying values that haven't changed since it was last
|
||||
|
|
@ -939,19 +945,23 @@ name (or pattern for matching bean names).
|
|||
[[production-ready-metric-writers-export-to-redis]]
|
||||
==== Example: Export to Redis
|
||||
|
||||
If you provide a `@Bean` of type `RedisMetricRepository` the metrics are exported to a
|
||||
Redis cache for aggregation. The `RedisMetricRepository` has 2 important parameters to
|
||||
configure it for this purpose: `prefix` and `key` (passed into its constructor). It is
|
||||
best to use a prefix that is unique to the application instance (e.g. using a random value
|
||||
and maybe the logical name of the application to make it possible to correlate with other
|
||||
instances of the same application). The "key" is used to keep a global index of all
|
||||
metric names, so it should be unique "globally", whatever that means for your system (e.g.
|
||||
2 instances of the same system could share a Redis cache if they have distinct keys).
|
||||
If you provide a `@Bean` of type `RedisMetricRepository` and mark it
|
||||
`@ExportMetricWriter` the metrics are exported to a Redis cache for
|
||||
aggregation. The `RedisMetricRepository` has 2 important parameters to
|
||||
configure it for this purpose: `prefix` and `key` (passed into its
|
||||
constructor). It is best to use a prefix that is unique to the
|
||||
application instance (e.g. using a random value and maybe the logical
|
||||
name of the application to make it possible to correlate with other
|
||||
instances of the same application). The "key" is used to keep a
|
||||
global index of all metric names, so it should be unique "globally",
|
||||
whatever that means for your system (e.g. 2 instances of the same
|
||||
system could share a Redis cache if they have distinct keys).
|
||||
Example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
MetricWriter metricWriter(MetricExportProperties export) {
|
||||
return new RedisMetricRepository(connectionFactory,
|
||||
export.getRedis().getPrefix(), export.getRedis().getKey());
|
||||
|
|
@ -987,15 +997,19 @@ the recommendations.
|
|||
[[production-ready-metric-writers-export-to-open-tdsb]]
|
||||
==== Example: Export to Open TSDB
|
||||
|
||||
If you provide a `@Bean` of type `OpenTsdbHttpMetricWriter` the metrics are exported to
|
||||
http://opentsdb.net/[Open TSDB] for aggregation. The `OpenTsdbHttpMetricWriter` has a
|
||||
`url` property that you need to set to the Open TSDB "/put" endpoint, e.g.
|
||||
`http://localhost:4242/api/put`). It also has a `namingStrategy` that you can customize or
|
||||
configure to make the metrics match the data structure you need on the server. By default
|
||||
it just passes through the metric name as an Open TSDB metric name and adds a tag "domain"
|
||||
with value "org.springframework.metrics" and another tag "process" with value equals to
|
||||
the object hash of the naming strategy. Thus, after running the application and generating
|
||||
some metrics (e.g. by pinging the home page) you can inspect the metrics in the TDB UI
|
||||
If you provide a `@Bean` of type `OpenTsdbHttpMetricWriter` and mark
|
||||
it `@ExportMetricWriter` the metrics are exported to
|
||||
http://opentsdb.net/[Open TSDB] for aggregation. The
|
||||
`OpenTsdbHttpMetricWriter` has a `url` property that you need to set
|
||||
to the Open TSDB "/put" endpoint, e.g.
|
||||
`http://localhost:4242/api/put`). It also has a `namingStrategy` that
|
||||
you can customize or configure to make the metrics match the data
|
||||
structure you need on the server. By default it just passes through
|
||||
the metric name as an Open TSDB metric name and adds a tag "domain"
|
||||
with value "org.springframework.metrics" and another tag "process"
|
||||
with value equals to the object hash of the naming strategy. Thus,
|
||||
after running the application and generating some metrics (e.g. by
|
||||
pinging the home page) you can inspect the metrics in the TDB UI
|
||||
(http://localhost:4242 by default). Example:
|
||||
|
||||
[source,indent=0]
|
||||
|
|
@ -1021,7 +1035,7 @@ curl localhost:4242/api/query?start=1h-ago&m=max:counter.status.200.root
|
|||
|
||||
[[production-ready-metric-writers-export-to-statsd]]
|
||||
==== Example: Export to Statsd
|
||||
If you provide a `@Bean` of type `StatsdMetricWriter` the metrics are exported to a
|
||||
If you provide a `@Bean` of type `StatsdMetricWriter` and mark it `@ExportMetricWriter` the metrics are exported to a
|
||||
statsd server:
|
||||
|
||||
[source,java,indent=0]
|
||||
|
|
@ -1036,6 +1050,7 @@ private String host = "localhost";
|
|||
private int port;
|
||||
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
MetricWriter metricWriter() {
|
||||
return new StatsdMetricWriter(prefix, host, port);
|
||||
}
|
||||
|
|
@ -1044,7 +1059,7 @@ MetricWriter metricWriter() {
|
|||
|
||||
[[production-ready-metric-writers-export-to-jmx]]
|
||||
==== Example: Export to JMX
|
||||
If you provide a `@Bean` of type `JmxMetricWriter` the metrics are exported as MBeans to
|
||||
If you provide a `@Bean` of type `JmxMetricWriter` marked `@ExportMetricWriter` the metrics are exported as MBeans to
|
||||
the local server (the `MBeanExporter` is provided by Spring Boot JMX autoconfiguration as
|
||||
long as it is switched on). Metrics can then be inspected, graphed, alerted etc. using any
|
||||
tool that understands JMX (e.g. JConsole or JVisualVM). Example:
|
||||
|
|
@ -1052,6 +1067,7 @@ tool that understands JMX (e.g. JConsole or JVisualVM). Example:
|
|||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
MetricWriter metricWriter(MBeanExporter exporter) {
|
||||
return new JmxMetricWriter(exporter);
|
||||
}
|
||||
|
|
@ -1084,19 +1100,17 @@ results to the "/metrics" endpoint. Example:
|
|||
|
||||
@Bean
|
||||
public PublicMetrics metricsAggregate() {
|
||||
return new MetricReaderPublicMetrics(aggregates());
|
||||
return new MetricReaderPublicMetrics(aggregatesMetricReader());
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected MetricReader repository(RedisConnectionFactory connectionFactory) {
|
||||
RedisMetricRepository repository = new RedisMetricRepository(connectionFactory,
|
||||
private MetricReader globalMetricsForAggregation() {
|
||||
return new RedisMetricRepository(this.connectionFactory,
|
||||
this.export.getRedis().getAggregatePrefix(), this.export.getRedis().getKey());
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected MetricReader aggregates() {
|
||||
AggregateMetricReader repository = new AggregateMetricReader(repository());
|
||||
private MetricReader aggregatesMetricReader() {
|
||||
AggregateMetricReader repository = new AggregateMetricReader(
|
||||
globalMetricsForAggregation());
|
||||
return repository;
|
||||
}
|
||||
----
|
||||
|
|
@ -1105,6 +1119,10 @@ NOTE: the example above uses `MetricExportProperties` to inject and
|
|||
extract the key and prefix. This is provided to you as a convenience
|
||||
by Spring Boot, and the defaults for that will be sensible.
|
||||
|
||||
NOTE: the `MetricReaders` above are not `@Beans` and are not marked as
|
||||
`@ExportMetricReader` because they are just collecting and analysing
|
||||
data from other repositories, and don't want to export their values.
|
||||
|
||||
|
||||
[[production-ready-dropwizard-metrics]]
|
||||
=== Dropwizard Metrics
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package sample.metrics.redis;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
|
||||
import org.springframework.boot.actuate.metrics.export.MetricExportProperties;
|
||||
import org.springframework.boot.actuate.metrics.jmx.JmxMetricWriter;
|
||||
import org.springframework.boot.actuate.metrics.repository.redis.RedisMetricRepository;
|
||||
|
|
@ -38,6 +39,7 @@ public class SampleRedisExportApplication {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
public RedisMetricRepository redisMetricWriter(
|
||||
RedisConnectionFactory connectionFactory) {
|
||||
return new RedisMetricRepository(connectionFactory, this.export.getRedis().getPrefix(),
|
||||
|
|
@ -45,6 +47,7 @@ public class SampleRedisExportApplication {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
public JmxMetricWriter jmxMetricWriter(
|
||||
@Qualifier("mbeanExporter") MBeanExporter exporter) {
|
||||
return new JmxMetricWriter(exporter);
|
||||
|
|
|
|||
Loading…
Reference in New Issue