Polish updated metrics code
This commit is contained in:
parent
d2f11c465e
commit
31d6a0f17a
|
@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
* others that might be installed by the user for other purposes).
|
* others that might be installed by the user for other purposes).
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
|
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
* the {@link ExportMetricReader} readers.
|
* the {@link ExportMetricReader} readers.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
|
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.boot.actuate.metrics.export.MetricExporters;
|
||||||
import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader;
|
import org.springframework.boot.actuate.metrics.reader.CompositeMetricReader;
|
||||||
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
||||||
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
|
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
@ -37,9 +38,13 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link EnableAutoConfiguration Auto-configuration} for metrics export.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
|
@ -47,22 +52,39 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
@EnableConfigurationProperties
|
@EnableConfigurationProperties
|
||||||
public class MetricExportAutoConfiguration {
|
public class MetricExportAutoConfiguration {
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
@ExportMetricWriter
|
|
||||||
private Map<String, MetricWriter> writers = Collections.emptyMap();
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MetricExportProperties metrics;
|
private MetricExportProperties properties;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private MetricsEndpointMetricReader endpointReader;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
@ExportMetricReader
|
@ExportMetricReader
|
||||||
private List<MetricReader> readers;
|
private List<MetricReader> readers;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private MetricsEndpointMetricReader endpointReader;
|
@ExportMetricWriter
|
||||||
|
private Map<String, MetricWriter> writers = Collections.emptyMap();
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(name = "metricWritersMetricExporter")
|
||||||
|
public SchedulingConfigurer metricWritersMetricExporter() {
|
||||||
|
Map<String, MetricWriter> writers = new HashMap<String, MetricWriter>();
|
||||||
|
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) {
|
||||||
|
writers.putAll(this.writers);
|
||||||
|
return new MetricExporters(reader, writers, this.properties);
|
||||||
|
}
|
||||||
|
return new NoOpSchedulingConfigurer();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class MetricExportPropertiesConfiguration {
|
protected static class MetricExportPropertiesConfiguration {
|
||||||
|
|
||||||
@Value("spring.metrics.${random.value:0000}.${spring.application.name:application}")
|
@Value("spring.metrics.${random.value:0000}.${spring.application.name:application}")
|
||||||
private String prefix = "spring.metrics";
|
private String prefix = "spring.metrics";
|
||||||
|
|
||||||
|
@ -70,36 +92,18 @@ public class MetricExportAutoConfiguration {
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public MetricExportProperties metricExportProperties() {
|
public MetricExportProperties metricExportProperties() {
|
||||||
MetricExportProperties export = new MetricExportProperties();
|
MetricExportProperties export = new MetricExportProperties();
|
||||||
export.getRedis().setPrefix(prefix);
|
export.getRedis().setPrefix(this.prefix);
|
||||||
return export;
|
return export;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
private static class NoOpSchedulingConfigurer implements SchedulingConfigurer {
|
||||||
@ConditionalOnMissingBean(name = "metricWritersMetricExporter")
|
|
||||||
public SchedulingConfigurer metricWritersMetricExporter() {
|
|
||||||
|
|
||||||
Map<String, MetricWriter> writers = new HashMap<String, MetricWriter>();
|
@Override
|
||||||
|
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||||
MetricReader reader = this.endpointReader;
|
|
||||||
if (reader == null && this.readers != null && !this.readers.isEmpty()) {
|
|
||||||
reader = new CompositeMetricReader(
|
|
||||||
this.readers.toArray(new MetricReader[this.readers.size()]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader != null) {
|
|
||||||
writers.putAll(this.writers);
|
|
||||||
MetricExporters exporters = new MetricExporters(reader, writers, this.metrics);
|
|
||||||
return exporters;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SchedulingConfigurer() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.springframework.messaging.MessageChannel;
|
||||||
* {@link MessageChannel}.
|
* {@link MessageChannel}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(MessageChannel.class)
|
@ConditionalOnClass(MessageChannel.class)
|
||||||
|
@ -46,4 +47,4 @@ public class MetricsChannelAutoConfiguration {
|
||||||
return new MessageChannelMetricWriter(channel);
|
return new MessageChannelMetricWriter(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import com.codahale.metrics.MetricRegistry;
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for Dropwizard-based metrics.
|
* {@link EnableAutoConfiguration Auto-configuration} for Dropwizard-based metrics.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(MetricRegistry.class)
|
@ConditionalOnClass(MetricRegistry.class)
|
||||||
|
@ -60,4 +61,4 @@ public class MetricsDropwizardAutoConfiguration {
|
||||||
return new MetricReaderPublicMetrics(reader);
|
return new MetricReaderPublicMetrics(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,8 @@ public class PublicMetricsAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public MetricReaderPublicMetrics metricReaderPublicMetrics() {
|
public MetricReaderPublicMetrics metricReaderPublicMetrics() {
|
||||||
return new MetricReaderPublicMetrics(new CompositeMetricReader(this.metricReaders.toArray(new MetricReader[0])));
|
return new MetricReaderPublicMetrics(new CompositeMetricReader(
|
||||||
|
this.metricReaders.toArray(new MetricReader[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||||
result.put(metric.getName(), metric.getValue());
|
result.put(metric.getName(), metric.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
// Could not evaluate metrics
|
// Could not evaluate metrics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.endpoint;
|
package org.springframework.boot.actuate.endpoint;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -25,12 +26,12 @@ import org.springframework.boot.actuate.metrics.Metric;
|
||||||
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MetricReader} that pulls all current values out of the {@link MetricsEndpoint}
|
* {@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
|
* 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).
|
* recent, and they all come out with the default (current time).
|
||||||
*
|
|
||||||
* @author Dave Syer
|
|
||||||
*
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class MetricsEndpointMetricReader implements MetricReader {
|
public class MetricsEndpointMetricReader implements MetricReader {
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ public class MetricsEndpointMetricReader implements MetricReader {
|
||||||
@Override
|
@Override
|
||||||
public Metric<?> findOne(String metricName) {
|
public Metric<?> findOne(String metricName) {
|
||||||
Metric<Number> metric = null;
|
Metric<Number> metric = null;
|
||||||
Object value = endpoint.invoke().get(metricName);
|
Object value = this.endpoint.invoke().get(metricName);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
metric = new Metric<Number>(metricName, (Number) value);
|
metric = new Metric<Number>(metricName, (Number) value);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +54,7 @@ public class MetricsEndpointMetricReader implements MetricReader {
|
||||||
@Override
|
@Override
|
||||||
public Iterable<Metric<?>> findAll() {
|
public Iterable<Metric<?>> findAll() {
|
||||||
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
||||||
Map<String, Object> values = endpoint.invoke();
|
Map<String, Object> values = this.endpoint.invoke();
|
||||||
Date timestamp = new Date();
|
Date timestamp = new Date();
|
||||||
for (Entry<String, Object> entry : values.entrySet()) {
|
for (Entry<String, Object> entry : values.entrySet()) {
|
||||||
String name = entry.getKey();
|
String name = entry.getKey();
|
||||||
|
@ -65,7 +66,7 @@ public class MetricsEndpointMetricReader implements MetricReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long count() {
|
public long count() {
|
||||||
return endpoint.invoke().size();
|
return this.endpoint.invoke().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2014-2015 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.metrics.aggregate;
|
package org.springframework.boot.actuate.metrics.aggregate;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -35,7 +36,7 @@ import org.springframework.util.StringUtils;
|
||||||
* value.
|
* value.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class AggregateMetricReader implements MetricReader {
|
public class AggregateMetricReader implements MetricReader {
|
||||||
|
|
||||||
|
@ -52,7 +53,6 @@ public class AggregateMetricReader implements MetricReader {
|
||||||
/**
|
/**
|
||||||
* The number of period-separated keys to remove from the start of the input metric
|
* The number of period-separated keys to remove from the start of the input metric
|
||||||
* names before aggregating.
|
* names before aggregating.
|
||||||
*
|
|
||||||
* @param truncate length of source metric prefixes
|
* @param truncate length of source metric prefixes
|
||||||
*/
|
*/
|
||||||
public void setTruncateKeyLength(int truncate) {
|
public void setTruncateKeyLength(int truncate) {
|
||||||
|
@ -62,7 +62,6 @@ public class AggregateMetricReader implements MetricReader {
|
||||||
/**
|
/**
|
||||||
* Prefix to apply to all output metrics. A period will be appended if no present in
|
* Prefix to apply to all output metrics. A period will be appended if no present in
|
||||||
* the provided value.
|
* the provided value.
|
||||||
*
|
|
||||||
* @param prefix the prefix to use default "aggregator.")
|
* @param prefix the prefix to use default "aggregator.")
|
||||||
*/
|
*/
|
||||||
public void setPrefix(String prefix) {
|
public void setPrefix(String prefix) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* Fast implementation of {@link CounterService} using {@link CounterBuffers}.
|
* Fast implementation of {@link CounterService} using {@link CounterBuffers}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class BufferCounterService implements CounterService {
|
public class BufferCounterService implements CounterService {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* Fast implementation of {@link GaugeService} using {@link GaugeBuffers}.
|
* Fast implementation of {@link GaugeService} using {@link GaugeBuffers}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class BufferGaugeService implements GaugeService {
|
public class BufferGaugeService implements GaugeService {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* {@link GaugeBuffers}.
|
* {@link GaugeBuffers}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class BufferMetricReader implements MetricReader, PrefixMetricReader {
|
public class BufferMetricReader implements MetricReader, PrefixMetricReader {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* Fast writes to in-memory metrics store using {@link LongBuffer}.
|
* Fast writes to in-memory metrics store using {@link LongBuffer}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class CounterBuffers {
|
public class CounterBuffers {
|
||||||
|
@ -113,4 +114,5 @@ public class CounterBuffers {
|
||||||
}
|
}
|
||||||
consumer.accept(adder);
|
consumer.accept(adder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.springframework.boot.actuate.metrics.buffer;
|
||||||
* Mutable buffer containing a double value and a timestamp.
|
* Mutable buffer containing a double value and a timestamp.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class DoubleBuffer {
|
public class DoubleBuffer {
|
||||||
|
|
||||||
|
@ -47,4 +48,5 @@ public class DoubleBuffer {
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
return this.timestamp;
|
return this.timestamp;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* Fast writes to in-memory metrics store using {@link DoubleBuffer}.
|
* Fast writes to in-memory metrics store using {@link DoubleBuffer}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class GaugeBuffers {
|
public class GaugeBuffers {
|
||||||
|
@ -94,4 +95,5 @@ public class GaugeBuffers {
|
||||||
}
|
}
|
||||||
consumer.accept(value);
|
consumer.accept(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.lang.UsesJava8;
|
||||||
* Mutable buffer containing a long adder (Java 8) and a timestamp.
|
* Mutable buffer containing a long adder (Java 8) and a timestamp.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava8
|
@UsesJava8
|
||||||
public class LongBuffer {
|
public class LongBuffer {
|
||||||
|
@ -56,4 +57,5 @@ public class LongBuffer {
|
||||||
public void add(long delta) {
|
public void add(long delta) {
|
||||||
this.adder.add(delta);
|
this.adder.add(delta);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -33,26 +33,27 @@ import org.springframework.util.StringUtils;
|
||||||
* export).
|
* export).
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractMetricExporter implements Exporter {
|
public abstract class AbstractMetricExporter implements Exporter {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(AbstractMetricExporter.class);
|
private static final Log logger = LogFactory.getLog(AbstractMetricExporter.class);
|
||||||
|
|
||||||
private volatile AtomicBoolean processing = new AtomicBoolean(false);
|
private final String prefix;
|
||||||
|
|
||||||
private Date earliestTimestamp = new Date();
|
private Date earliestTimestamp = new Date();
|
||||||
|
|
||||||
private boolean ignoreTimestamps = false;
|
private boolean ignoreTimestamps = false;
|
||||||
|
|
||||||
private final String prefix;
|
private boolean sendLatest = true;
|
||||||
|
|
||||||
|
private volatile AtomicBoolean processing = new AtomicBoolean(false);
|
||||||
|
|
||||||
private Date latestTimestamp = new Date(0L);
|
private Date latestTimestamp = new Date(0L);
|
||||||
|
|
||||||
private boolean sendLatest = true;
|
|
||||||
|
|
||||||
public AbstractMetricExporter(String prefix) {
|
public AbstractMetricExporter(String prefix) {
|
||||||
this.prefix = !StringUtils.hasText(prefix) ? "" : (prefix.endsWith(".") ? prefix
|
this.prefix = (!StringUtils.hasText(prefix) ? "" : (prefix.endsWith(".") ? prefix
|
||||||
: prefix + ".");
|
: prefix + "."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +74,6 @@ public abstract class AbstractMetricExporter implements Exporter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send only the data that changed since the last export.
|
* Send only the data that changed since the last export.
|
||||||
*
|
|
||||||
* @param sendLatest the flag to set
|
* @param sendLatest the flag to set
|
||||||
*/
|
*/
|
||||||
public void setSendLatest(boolean sendLatest) {
|
public void setSendLatest(boolean sendLatest) {
|
||||||
|
@ -82,47 +82,63 @@ public abstract class AbstractMetricExporter implements Exporter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void export() {
|
public void export() {
|
||||||
if (!this.processing.compareAndSet(false, true)) {
|
if (this.processing.compareAndSet(false, true)) {
|
||||||
// skip a tick
|
long latestTimestamp = System.currentTimeMillis();
|
||||||
return;
|
|
||||||
}
|
|
||||||
long latestTimestamp = 0;
|
|
||||||
try {
|
|
||||||
latestTimestamp = System.currentTimeMillis();
|
|
||||||
for (String group : groups()) {
|
|
||||||
Collection<Metric<?>> values = new ArrayList<Metric<?>>();
|
|
||||||
for (Metric<?> metric : next(group)) {
|
|
||||||
Metric<?> value = new Metric<Number>(this.prefix + metric.getName(),
|
|
||||||
metric.getValue(), metric.getTimestamp());
|
|
||||||
Date timestamp = metric.getTimestamp();
|
|
||||||
if (!this.ignoreTimestamps && this.earliestTimestamp.after(timestamp)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!this.ignoreTimestamps && this.sendLatest
|
|
||||||
&& this.latestTimestamp.after(timestamp)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
values.add(value);
|
|
||||||
}
|
|
||||||
if (!values.isEmpty()) {
|
|
||||||
write(group, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
logger.warn("Could not write to MetricWriter: " + e.getClass() + ": "
|
|
||||||
+ e.getMessage());
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
try {
|
||||||
|
exportGroups();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
logger.warn("Could not write to MetricWriter: " + ex.getClass() + ": "
|
||||||
|
+ ex.getMessage());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
this.latestTimestamp = new Date(latestTimestamp);
|
this.latestTimestamp = new Date(latestTimestamp);
|
||||||
flush();
|
flushQuietly();
|
||||||
|
this.processing.set(false);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
}
|
||||||
logger.warn("Could not flush MetricWriter: " + e.getClass() + ": "
|
}
|
||||||
+ e.getMessage());
|
|
||||||
|
private void exportGroups() {
|
||||||
|
for (String group : groups()) {
|
||||||
|
Collection<Metric<?>> values = new ArrayList<Metric<?>>();
|
||||||
|
for (Metric<?> metric : next(group)) {
|
||||||
|
Date timestamp = metric.getTimestamp();
|
||||||
|
if (canExportTimestamp(timestamp)) {
|
||||||
|
values.add(getPrefixedMetric(metric));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.processing.set(false);
|
if (!values.isEmpty()) {
|
||||||
|
write(group, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Metric<?> getPrefixedMetric(Metric<?> metric) {
|
||||||
|
String name = this.prefix + metric.getName();
|
||||||
|
return new Metric<Number>(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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +25,7 @@ package org.springframework.boot.actuate.metrics.export;
|
||||||
* it using a {@code @Scheduled} annotation in a Spring ApplicationContext.
|
* it using a {@code @Scheduled} annotation in a Spring ApplicationContext.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public interface Exporter {
|
public interface Exporter {
|
||||||
|
|
||||||
|
|
|
@ -16,23 +16,33 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.metrics.export;
|
package org.springframework.boot.actuate.metrics.export;
|
||||||
|
|
||||||
|
import java.io.Flushable;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
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.Metric;
|
||||||
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
import org.springframework.boot.actuate.metrics.reader.MetricReader;
|
||||||
|
import org.springframework.boot.actuate.metrics.writer.CompositeMetricWriter;
|
||||||
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
|
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
|
||||||
import org.springframework.boot.actuate.metrics.writer.WriterUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.PatternMatchUtils;
|
import org.springframework.util.PatternMatchUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Exporter} that "exports" by copying metric data from a source
|
* {@link Exporter} that "exports" by copying metric data from a source
|
||||||
* {@link MetricReader} to a destination {@link MetricWriter}.
|
* {@link MetricReader} to a destination {@link MetricWriter}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class MetricCopyExporter extends AbstractMetricExporter {
|
public class MetricCopyExporter extends AbstractMetricExporter {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(MetricCopyExporter.class);
|
||||||
|
|
||||||
private final MetricReader reader;
|
private final MetricReader reader;
|
||||||
|
|
||||||
private final MetricWriter writer;
|
private final MetricWriter writer;
|
||||||
|
@ -41,41 +51,53 @@ public class MetricCopyExporter extends AbstractMetricExporter {
|
||||||
|
|
||||||
private String[] excludes = 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, MetricWriter writer) {
|
public MetricCopyExporter(MetricReader reader, MetricWriter writer) {
|
||||||
this(reader, writer, "");
|
this(reader, writer, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIncludes(String... includes) {
|
/**
|
||||||
if (includes != null) {
|
* Create a new {@link MetricCopyExporter} instance.
|
||||||
this.includes = includes;
|
* @param reader the metric reader
|
||||||
}
|
* @param writer the metric writer
|
||||||
}
|
* @param prefix the name prefix
|
||||||
|
*/
|
||||||
public void setExcludes(String... excludes) {
|
|
||||||
if (excludes != null) {
|
|
||||||
this.excludes = excludes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetricCopyExporter(MetricReader reader, MetricWriter writer, String prefix) {
|
public MetricCopyExporter(MetricReader reader, MetricWriter writer, String prefix) {
|
||||||
super(prefix);
|
super(prefix);
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
@Override
|
||||||
protected Iterable<Metric<?>> next(String group) {
|
protected Iterable<Metric<?>> next(String group) {
|
||||||
if ((this.includes == null || this.includes.length == 0)
|
if (ObjectUtils.isEmpty(this.includes) && ObjectUtils.isEmpty(this.excludes)) {
|
||||||
&& (this.excludes == null || this.excludes.length == 0)) {
|
|
||||||
return this.reader.findAll();
|
return this.reader.findAll();
|
||||||
}
|
}
|
||||||
return new Iterable<Metric<?>>() {
|
return new PatternMatchingIterable(MetricCopyExporter.this.reader);
|
||||||
@Override
|
|
||||||
public Iterator<Metric<?>> iterator() {
|
|
||||||
return new PatternMatchingIterator(MetricCopyExporter.this.reader
|
|
||||||
.findAll().iterator());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,12 +109,52 @@ public class MetricCopyExporter extends AbstractMetricExporter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
WriterUtils.flush(this.writer);
|
flush(this.writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flush(MetricWriter 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<Metric<?>> {
|
||||||
|
|
||||||
|
private final MetricReader reader;
|
||||||
|
|
||||||
|
public PatternMatchingIterable(MetricReader reader) {
|
||||||
|
this.reader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Metric<?>> iterator() {
|
||||||
|
return new PatternMatchingIterator(this.reader.findAll().iterator());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PatternMatchingIterator implements Iterator<Metric<?>> {
|
private class PatternMatchingIterator implements Iterator<Metric<?>> {
|
||||||
|
|
||||||
private Metric<?> buffer = null;
|
private Metric<?> buffer = null;
|
||||||
|
|
||||||
private Iterator<Metric<?>> iterator;
|
private Iterator<Metric<?>> iterator;
|
||||||
|
|
||||||
public PatternMatchingIterator(Iterator<Metric<?>> iterator) {
|
public PatternMatchingIterator(Iterator<Metric<?>> iterator) {
|
||||||
|
@ -109,33 +171,24 @@ public class MetricCopyExporter extends AbstractMetricExporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Metric<?> findNext() {
|
private Metric<?> findNext() {
|
||||||
Metric<?> metric = null;
|
while (this.iterator.hasNext()) {
|
||||||
boolean matched = false;
|
Metric<?> metric = this.iterator.next();
|
||||||
while (this.iterator.hasNext() && !matched) {
|
if (isMatch(metric)) {
|
||||||
metric = this.iterator.next();
|
return metric;
|
||||||
if (MetricCopyExporter.this.includes == null
|
|
||||||
|| MetricCopyExporter.this.includes.length == 0) {
|
|
||||||
matched = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (String pattern : MetricCopyExporter.this.includes) {
|
|
||||||
if (PatternMatchUtils.simpleMatch(pattern, metric.getName())) {
|
|
||||||
matched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (MetricCopyExporter.this.excludes != null) {
|
|
||||||
for (String pattern : MetricCopyExporter.this.excludes) {
|
|
||||||
if (PatternMatchUtils.simpleMatch(pattern, metric.getName())) {
|
|
||||||
matched = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matched ? metric : null;
|
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
|
@Override
|
||||||
|
@ -144,5 +197,6 @@ public class MetricCopyExporter extends AbstractMetricExporter {
|
||||||
this.buffer = null;
|
this.buffer = null;
|
||||||
return metric;
|
return metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,55 +27,29 @@ import org.springframework.util.PatternMatchUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Configuration properties for metrics export.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties("spring.metrics.export")
|
@ConfigurationProperties("spring.metrics.export")
|
||||||
public class MetricExportProperties extends Trigger {
|
public class MetricExportProperties extends TriggerProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to disable all metric exports (assuming any MetricWriters are available).
|
* Flag to disable all metric exports (assuming any MetricWriters are available).
|
||||||
*/
|
*/
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
|
|
||||||
private Map<String, SpecificTrigger> triggers = new LinkedHashMap<String, SpecificTrigger>();
|
private Map<String, SpecificTriggerProperties> triggers = new LinkedHashMap<String, SpecificTriggerProperties>();
|
||||||
|
|
||||||
private Redis redis = new Redis();
|
private Redis redis = new Redis();
|
||||||
|
|
||||||
/**
|
|
||||||
* Default values for trigger configuration for all writers. Can also be set by
|
|
||||||
* including a writer with <code>name="*"</code>.
|
|
||||||
*
|
|
||||||
* @return the default trigger configuration
|
|
||||||
*/
|
|
||||||
public Trigger getDefault() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<String, SpecificTrigger> getTriggers() {
|
|
||||||
return this.triggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Redis getRedis() {
|
|
||||||
return redis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedis(Redis redis) {
|
|
||||||
this.redis = redis;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void setUpDefaults() {
|
public void setUpDefaults() {
|
||||||
Trigger defaults = this;
|
TriggerProperties defaults = this;
|
||||||
for (Entry<String, SpecificTrigger> entry : this.triggers.entrySet()) {
|
for (Entry<String, SpecificTriggerProperties> entry : this.triggers.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
SpecificTrigger value = entry.getValue();
|
SpecificTriggerProperties value = entry.getValue();
|
||||||
if (value.getNames() == null || value.getNames().length == 0) {
|
if (value.getNames() == null || value.getNames().length == 0) {
|
||||||
value.setNames(new String[] { key });
|
value.setNames(new String[] { key });
|
||||||
}
|
}
|
||||||
|
@ -86,7 +60,7 @@ public class MetricExportProperties extends Trigger {
|
||||||
if (defaults.getDelayMillis() == null) {
|
if (defaults.getDelayMillis() == null) {
|
||||||
defaults.setDelayMillis(5000);
|
defaults.setDelayMillis(5000);
|
||||||
}
|
}
|
||||||
for (Trigger value : this.triggers.values()) {
|
for (TriggerProperties value : this.triggers.values()) {
|
||||||
if (value.isSendLatest() == null) {
|
if (value.isSendLatest() == null) {
|
||||||
value.setSendLatest(defaults.isSendLatest());
|
value.setSendLatest(defaults.isSendLatest());
|
||||||
}
|
}
|
||||||
|
@ -96,47 +70,56 @@ public class MetricExportProperties extends Trigger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return this.enabled;
|
return this.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String, SpecificTriggerProperties> getTriggers() {
|
||||||
|
return this.triggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Redis getRedis() {
|
||||||
|
return this.redis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedis(Redis redis) {
|
||||||
|
this.redis = redis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default values for trigger configuration for all writers. Can also be set by
|
||||||
|
* including a writer with {@code name="*"}.
|
||||||
|
* @return the default trigger configuration
|
||||||
|
*/
|
||||||
|
public TriggerProperties getDefault() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a matching trigger configuration.
|
* Find a matching trigger configuration.
|
||||||
* @param name the bean name to match
|
* @param name the bean name to match
|
||||||
* @return a matching configuration if there is one
|
* @return a matching configuration if there is one
|
||||||
*/
|
*/
|
||||||
public Trigger findTrigger(String name) {
|
public TriggerProperties findTrigger(String name) {
|
||||||
for (SpecificTrigger value : this.triggers.values()) {
|
for (SpecificTriggerProperties value : this.triggers.values()) {
|
||||||
if (PatternMatchUtils.simpleMatch(value.getNames(), name)) {
|
if (PatternMatchUtils.simpleMatch(value.getNames(), name)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger for specific bean names.
|
|
||||||
*/
|
|
||||||
public static class SpecificTrigger extends Trigger {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Redis {
|
public static class Redis {
|
||||||
|
|
||||||
|
@ -155,9 +138,9 @@ public class MetricExportProperties extends Trigger {
|
||||||
* system sharing a redis repository.
|
* system sharing a redis repository.
|
||||||
*/
|
*/
|
||||||
private String key = "keys.spring.metrics";
|
private String key = "keys.spring.metrics";
|
||||||
|
|
||||||
public String getPrefix() {
|
public String getPrefix() {
|
||||||
return prefix;
|
return this.prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrefix(String prefix) {
|
public void setPrefix(String prefix) {
|
||||||
|
@ -165,7 +148,7 @@ public class MetricExportProperties extends Trigger {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKey(String key) {
|
public void setKey(String key) {
|
||||||
|
@ -187,74 +170,3 @@ public class MetricExportProperties extends Trigger {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Trigger {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,58 +27,68 @@ import org.springframework.scheduling.config.IntervalTask;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link SchedulingConfigurer} to handle metrics {@link MetricCopyExporter export}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class MetricExporters implements SchedulingConfigurer {
|
public class MetricExporters implements SchedulingConfigurer {
|
||||||
|
|
||||||
private MetricExportProperties export;
|
private final MetricReader reader;
|
||||||
|
|
||||||
private Map<String, MetricWriter> writers;
|
private final Map<String, MetricWriter> writers;
|
||||||
|
|
||||||
private Map<String, Exporter> exporters = new HashMap<String, Exporter>();
|
private final MetricExportProperties properties;
|
||||||
|
|
||||||
private MetricReader reader;
|
private final Map<String, Exporter> exporters = new HashMap<String, Exporter>();
|
||||||
|
|
||||||
public MetricExporters(MetricReader reader, Map<String, MetricWriter> writers,
|
public MetricExporters(MetricReader reader, Map<String, MetricWriter> writers,
|
||||||
MetricExportProperties export) {
|
MetricExportProperties properties) {
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.export = export;
|
|
||||||
this.writers = writers;
|
this.writers = writers;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||||
|
for (Entry<String, MetricWriter> entry : this.writers.entrySet()) {
|
||||||
|
String name = entry.getKey();
|
||||||
|
MetricWriter writer = entry.getValue();
|
||||||
|
TriggerProperties trigger = this.properties.findTrigger(name);
|
||||||
|
if (trigger != null) {
|
||||||
|
MetricCopyExporter exporter = getExporter(writer, trigger);
|
||||||
|
this.exporters.put(name, exporter);
|
||||||
|
ExportRunner runner = new ExportRunner(exporter);
|
||||||
|
IntervalTask task = new IntervalTask(runner, trigger.getDelayMillis(),
|
||||||
|
trigger.getDelayMillis());
|
||||||
|
taskRegistrar.addFixedDelayTask(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetricCopyExporter getExporter(MetricWriter 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<String, Exporter> getExporters() {
|
public Map<String, Exporter> getExporters() {
|
||||||
return this.exporters;
|
return this.exporters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static class ExportRunner implements Runnable {
|
||||||
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
|
||||||
|
|
||||||
for (Entry<String, MetricWriter> entry : this.writers.entrySet()) {
|
private final MetricCopyExporter exporter;
|
||||||
String name = entry.getKey();
|
|
||||||
Trigger trigger = this.export.findTrigger(name);
|
|
||||||
|
|
||||||
if (trigger != null) {
|
public ExportRunner(MetricCopyExporter exporter) {
|
||||||
|
this.exporter = exporter;
|
||||||
MetricWriter writer = entry.getValue();
|
}
|
||||||
final MetricCopyExporter exporter = new MetricCopyExporter(this.reader,
|
|
||||||
writer);
|
|
||||||
if (trigger.getIncludes() != null || trigger.getExcludes() != null) {
|
|
||||||
exporter.setIncludes(trigger.getIncludes());
|
|
||||||
exporter.setExcludes(trigger.getExcludes());
|
|
||||||
}
|
|
||||||
exporter.setSendLatest(trigger.isSendLatest());
|
|
||||||
|
|
||||||
this.exporters.put(name, exporter);
|
|
||||||
|
|
||||||
taskRegistrar.addFixedDelayTask(new IntervalTask(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
exporter.export();
|
|
||||||
}
|
|
||||||
}, trigger.getDelayMillis(), trigger.getDelayMillis()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
this.exporter.export();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -30,6 +30,7 @@ import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter;
|
||||||
* all metrics whose name starts with a prefix (or all metrics if the prefix is empty).
|
* all metrics whose name starts with a prefix (or all metrics if the prefix is empty).
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class PrefixMetricGroupExporter extends AbstractMetricExporter {
|
public class PrefixMetricGroupExporter extends AbstractMetricExporter {
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ public class PrefixMetricGroupExporter extends AbstractMetricExporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The groups to export.
|
||||||
* @param groups the groups to set
|
* @param groups the groups to set
|
||||||
*/
|
*/
|
||||||
public void setGroups(Set<String> groups) {
|
public void setGroups(Set<String> groups) {
|
||||||
|
|
|
@ -30,14 +30,14 @@ import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter;
|
||||||
/**
|
/**
|
||||||
* Exporter or converter for {@link RichGauge} data to a metric-based back end. Each gauge
|
* 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
|
* 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
|
* gauge), and suffixes that describe the data. For example, a gauge called {@code foo} is
|
||||||
* <code>foo</code> is stored as
|
* stored as {@code[foo.min, foo.max. foo.val, foo.count, foo.avg, foo.alpha]}. If the
|
||||||
* <code>[foo.min, foo.max. foo.val, foo.count, foo.avg, foo.alpha]</code>. If the
|
|
||||||
* {@link MetricWriter} provided is a {@link MultiMetricRepository} then the values for a
|
* {@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
|
* gauge will be stored as a group, and hence will be retrievable from the repository in a
|
||||||
* single query (or optionally individually).
|
* single query (or optionally individually).
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class RichGaugeExporter extends AbstractMetricExporter {
|
public class RichGaugeExporter extends AbstractMetricExporter {
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ public class RichGaugeExporter extends AbstractMetricExporter {
|
||||||
private static final String ALPHA = ".alpha";
|
private static final String ALPHA = ".alpha";
|
||||||
|
|
||||||
private final RichGaugeReader reader;
|
private final RichGaugeReader reader;
|
||||||
|
|
||||||
private final PrefixMetricWriter writer;
|
private final PrefixMetricWriter writer;
|
||||||
|
|
||||||
public RichGaugeExporter(RichGaugeReader reader, PrefixMetricWriter writer) {
|
public RichGaugeExporter(RichGaugeReader reader, PrefixMetricWriter writer) {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2015 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.metrics.integration;
|
package org.springframework.boot.actuate.metrics.integration;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -26,14 +27,15 @@ import org.springframework.integration.support.management.Statistics;
|
||||||
import org.springframework.lang.UsesJava7;
|
import org.springframework.lang.UsesJava7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MetricReader} for Spring Integration metrics (as provided by spring-integration-jmx).
|
* A {@link MetricReader} for Spring Integration metrics (as provided by
|
||||||
*
|
* spring-integration-jmx).
|
||||||
* @author Dave Syer
|
|
||||||
*
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@UsesJava7
|
@UsesJava7
|
||||||
public class SpringIntegrationMetricReader implements MetricReader {
|
public class SpringIntegrationMetricReader implements MetricReader {
|
||||||
|
|
||||||
private final IntegrationMBeanExporter exporter;
|
private final IntegrationMBeanExporter exporter;
|
||||||
|
|
||||||
public SpringIntegrationMetricReader(IntegrationMBeanExporter exporter) {
|
public SpringIntegrationMetricReader(IntegrationMBeanExporter exporter) {
|
||||||
|
@ -47,23 +49,34 @@ public class SpringIntegrationMetricReader implements MetricReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<Metric<?>> findAll() {
|
public Iterable<Metric<?>> findAll() {
|
||||||
|
IntegrationMBeanExporter exporter = this.exporter;
|
||||||
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
||||||
for (String name : exporter.getChannelNames()) {
|
for (String name : exporter.getChannelNames()) {
|
||||||
metrics.addAll(getStatistics("integration.channel." + name + ".errorRate", exporter.getChannelErrorRate(name)));
|
String prefix = "integration.channel." + name;
|
||||||
metrics.addAll(getStatistics("integration.channel." + name + ".sendRate", exporter.getChannelSendRate(name)));
|
metrics.addAll(getStatistics(prefix + ".errorRate",
|
||||||
metrics.add(new Metric<Long>("integration.channel." + name + ".receiveCount", exporter.getChannelReceiveCountLong(name)));
|
exporter.getChannelErrorRate(name)));
|
||||||
|
metrics.addAll(getStatistics(prefix + ".sendRate",
|
||||||
|
exporter.getChannelSendRate(name)));
|
||||||
|
metrics.add(new Metric<Long>(prefix + ".receiveCount", exporter
|
||||||
|
.getChannelReceiveCountLong(name)));
|
||||||
}
|
}
|
||||||
for (String name : exporter.getHandlerNames()) {
|
for (String name : exporter.getHandlerNames()) {
|
||||||
metrics.addAll(getStatistics("integration.handler." + name + ".duration", exporter.getHandlerDuration(name)));
|
metrics.addAll(getStatistics("integration.handler." + name + ".duration",
|
||||||
|
exporter.getHandlerDuration(name)));
|
||||||
}
|
}
|
||||||
metrics.add(new Metric<Long>("integration.activeHandlerCount", exporter.getActiveHandlerCountLong()));
|
metrics.add(new Metric<Long>("integration.activeHandlerCount", exporter
|
||||||
metrics.add(new Metric<Integer>("integration.handlerCount", exporter.getHandlerCount()));
|
.getActiveHandlerCountLong()));
|
||||||
metrics.add(new Metric<Integer>("integration.channelCount", exporter.getChannelCount()));
|
metrics.add(new Metric<Integer>("integration.handlerCount", exporter
|
||||||
metrics.add(new Metric<Integer>("integration.queuedMessageCount", exporter.getQueuedMessageCount()));
|
.getHandlerCount()));
|
||||||
return metrics;
|
metrics.add(new Metric<Integer>("integration.channelCount", exporter
|
||||||
|
.getChannelCount()));
|
||||||
|
metrics.add(new Metric<Integer>("integration.queuedMessageCount", exporter
|
||||||
|
.getQueuedMessageCount()));
|
||||||
|
return metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<? extends Metric<?>> getStatistics(String name, Statistics statistic) {
|
private Collection<? extends Metric<?>> getStatistics(String name,
|
||||||
|
Statistics statistic) {
|
||||||
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
List<Metric<?>> metrics = new ArrayList<Metric<?>>();
|
||||||
metrics.add(new Metric<Double>(name + ".mean", statistic.getMean()));
|
metrics.add(new Metric<Double>(name + ".mean", statistic.getMean()));
|
||||||
metrics.add(new Metric<Double>(name + ".max", statistic.getMax()));
|
metrics.add(new Metric<Double>(name + ".max", statistic.getMax()));
|
||||||
|
@ -75,7 +88,9 @@ public class SpringIntegrationMetricReader implements MetricReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long count() {
|
public long count() {
|
||||||
return exporter.getChannelCount()*11 + exporter.getHandlerCount()*5 + 4;
|
int totalChannelCount = this.exporter.getChannelCount() * 11;
|
||||||
|
int totalHandlerCount = this.exporter.getHandlerCount() * 5;
|
||||||
|
return totalChannelCount + totalHandlerCount + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.springframework.util.StringUtils;
|
||||||
* domain is copied from the input key and the type in the input key is discarded.
|
* domain is copied from the input key and the type in the input key is discarded.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class DefaultMetricNamingStrategy implements ObjectNamingStrategy {
|
public class DefaultMetricNamingStrategy implements ObjectNamingStrategy {
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import javax.management.MalformedObjectNameException;
|
import javax.management.MalformedObjectNameException;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -41,6 +42,7 @@ import org.springframework.jmx.export.naming.ObjectNamingStrategy;
|
||||||
* and <code>value</code> keys by splitting up the metric name on periods.
|
* and <code>value</code> keys by splitting up the metric name on periods.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@ManagedResource(description = "MetricWriter for pushing metrics to JMX MBeans.")
|
@ManagedResource(description = "MetricWriter for pushing metrics to JMX MBeans.")
|
||||||
public class JmxMetricWriter implements MetricWriter {
|
public class JmxMetricWriter implements MetricWriter {
|
||||||
|
@ -97,10 +99,9 @@ public class JmxMetricWriter implements MetricWriter {
|
||||||
try {
|
try {
|
||||||
// We can unregister the MBean, but if this writer is on the end of an
|
// 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.
|
// Exporter the chances are it will be re-registered almost immediately.
|
||||||
this.exporter.unregisterManagedResource(this.namingStrategy
|
this.exporter.unregisterManagedResource(getName(name, value));
|
||||||
.getObjectName(value, getKey(name)));
|
|
||||||
}
|
}
|
||||||
catch (MalformedObjectNameException e) {
|
catch (MalformedObjectNameException ex) {
|
||||||
logger.warn("Could not unregister MBean for " + name);
|
logger.warn("Could not unregister MBean for " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,18 +112,19 @@ public class JmxMetricWriter implements MetricWriter {
|
||||||
this.values.putIfAbsent(name, new MetricValue());
|
this.values.putIfAbsent(name, new MetricValue());
|
||||||
MetricValue value = this.values.get(name);
|
MetricValue value = this.values.get(name);
|
||||||
try {
|
try {
|
||||||
this.exporter.registerManagedResource(value,
|
this.exporter.registerManagedResource(value, getName(name, value));
|
||||||
this.namingStrategy.getObjectName(value, getKey(name)));
|
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception ex) {
|
||||||
// Could not register mbean, maybe just a race condition
|
// Could not register mbean, maybe just a race condition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.values.get(name);
|
return this.values.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey(String name) {
|
private ObjectName getName(String name, MetricValue value)
|
||||||
return String.format(this.domain + ":type=MetricValue,name=%s", name);
|
throws MalformedObjectNameException {
|
||||||
|
String key = String.format(this.domain + ":type=MetricValue,name=%s", name);
|
||||||
|
return this.namingStrategy.getObjectName(value, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManagedResource
|
@ManagedResource
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils;
|
||||||
* (overwriting the default).
|
* (overwriting the default).
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class DefaultOpenTsdbNamingStrategy implements OpenTsdbNamingStrategy {
|
public class DefaultOpenTsdbNamingStrategy implements OpenTsdbNamingStrategy {
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@ package org.springframework.boot.actuate.metrics.opentsdb;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* OpenTSDB Data.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class OpenTsdbData {
|
public class OpenTsdbData {
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.springframework.web.client.RestTemplate;
|
||||||
* <code>@Scheduled</code>} task to flush periodically.
|
* <code>@Scheduled</code>} task to flush periodically.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class OpenTsdbMetricWriter implements MetricWriter {
|
public class OpenTsdbMetricWriter implements MetricWriter {
|
||||||
|
|
||||||
|
@ -141,4 +142,4 @@ public class OpenTsdbMetricWriter implements MetricWriter {
|
||||||
set(new Metric<Long>(metricName, 0L));
|
set(new Metric<Long>(metricName, 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,10 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* OpenTSDB Name.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class OpenTsdbName {
|
public class OpenTsdbName {
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,18 @@
|
||||||
package org.springframework.boot.actuate.metrics.opentsdb;
|
package org.springframework.boot.actuate.metrics.opentsdb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Strategy used to convert a metric name into an {@link OpenTsdbName}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public interface OpenTsdbNamingStrategy {
|
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);
|
OpenTsdbName getName(String metricName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,16 +37,16 @@ import com.timgroup.statsd.StatsDClientErrorHandler;
|
||||||
* a gauge.
|
* a gauge.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
public class StatsdMetricWriter implements MetricWriter, Closeable {
|
public class StatsdMetricWriter implements MetricWriter, Closeable {
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(StatsdMetricWriter.class);
|
private static final Log logger = LogFactory.getLog(StatsdMetricWriter.class);
|
||||||
|
|
||||||
private final NonBlockingStatsDClient client;
|
private final NonBlockingStatsDClient client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new writer with the given parameters.
|
* Create a new writer instance with the given parameters.
|
||||||
*
|
|
||||||
* @param host the hostname for the statsd server
|
* @param host the hostname for the statsd server
|
||||||
* @param port the port for the statsd server
|
* @param port the port for the statsd server
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,6 @@ public class StatsdMetricWriter implements MetricWriter, Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new writer with the given parameters.
|
* Create a new writer with the given parameters.
|
||||||
*
|
|
||||||
* @param prefix the prefix to apply to all metric names (can be null)
|
* @param prefix the prefix to apply to all metric names (can be null)
|
||||||
* @param host the hostname for the statsd server
|
* @param host the hostname for the statsd server
|
||||||
* @param port the port for the statsd server
|
* @param port the port for the statsd server
|
||||||
|
@ -101,11 +100,13 @@ public class StatsdMetricWriter implements MetricWriter, Closeable {
|
||||||
|
|
||||||
private static final class LoggingStatsdErrorHandler implements
|
private static final class LoggingStatsdErrorHandler implements
|
||||||
StatsDClientErrorHandler {
|
StatsDClientErrorHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(Exception e) {
|
public void handle(Exception e) {
|
||||||
logger.debug("Failed to write metric. Exception: " + e.getClass()
|
logger.debug("Failed to write metric. Exception: " + e.getClass()
|
||||||
+ ", message: " + e.getMessage());
|
+ ", message: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,5 @@ public class DefaultCounterService implements CounterService {
|
||||||
this.names.put(metricName, name);
|
this.names.put(metricName, name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,4 +57,5 @@ public class DefaultGaugeService implements GaugeService {
|
||||||
this.names.put(metricName, name);
|
this.names.put(metricName, name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +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.io.Flushable;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.boot.actuate.metrics.export.MetricCopyExporter;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
public class WriterUtils {
|
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(MetricCopyExporter.class);
|
|
||||||
|
|
||||||
public static void flush(MetricWriter writer) {
|
|
||||||
if (writer instanceof CompositeMetricWriter) {
|
|
||||||
for (MetricWriter element : (CompositeMetricWriter) writer) {
|
|
||||||
flush(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 e) {
|
|
||||||
logger.warn("Could not flush MetricWriter: " + e.getClass() + ": "
|
|
||||||
+ e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Matchers;
|
import org.mockito.Matchers;
|
||||||
|
@ -38,8 +36,10 @@ import org.springframework.messaging.MessageHandler;
|
||||||
import org.springframework.messaging.MessagingException;
|
import org.springframework.messaging.MessagingException;
|
||||||
import org.springframework.messaging.SubscribableChannel;
|
import org.springframework.messaging.SubscribableChannel;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link MetricRepositoryAutoConfiguration}.
|
* Tests for {@link MetricExportAutoConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
@ -88,15 +88,15 @@ public class MetricExportAutoConfigurationTests {
|
||||||
@Test
|
@Test
|
||||||
public void exportMetricsEndpoint() {
|
public void exportMetricsEndpoint() {
|
||||||
this.context = new AnnotationConfigApplicationContext(WriterConfig.class,
|
this.context = new AnnotationConfigApplicationContext(WriterConfig.class,
|
||||||
MetricEndpointConfiguration.class,
|
MetricEndpointConfiguration.class, MetricExportAutoConfiguration.class,
|
||||||
MetricExportAutoConfiguration.class,
|
|
||||||
PropertyPlaceholderAutoConfiguration.class);
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
MetricExporters exporters = this.context.getBean(MetricExporters.class);
|
MetricExporters exporters = this.context.getBean(MetricExporters.class);
|
||||||
MetricCopyExporter exporter = (MetricCopyExporter) exporters.getExporters().get(
|
MetricCopyExporter exporter = (MetricCopyExporter) exporters.getExporters().get(
|
||||||
"writer");
|
"writer");
|
||||||
exporter.setIgnoreTimestamps(true);
|
exporter.setIgnoreTimestamps(true);
|
||||||
exporter.export();
|
exporter.export();
|
||||||
MetricsEndpointMetricReader reader = this.context.getBean("endpointReader", MetricsEndpointMetricReader.class);
|
MetricsEndpointMetricReader reader = this.context.getBean("endpointReader",
|
||||||
|
MetricsEndpointMetricReader.class);
|
||||||
Mockito.verify(reader, Mockito.atLeastOnce()).findAll();
|
Mockito.verify(reader, Mockito.atLeastOnce()).findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.actuate.metrics.CounterService;
|
import org.springframework.boot.actuate.metrics.CounterService;
|
||||||
|
@ -39,6 +33,12 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link MetricRepositoryAutoConfiguration}.
|
* Tests for {@link MetricRepositoryAutoConfiguration}.
|
||||||
*
|
*
|
||||||
|
|
|
@ -27,6 +27,8 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link AggregateMetricReader}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class AggregateMetricReaderTests {
|
public class AggregateMetricReaderTests {
|
||||||
|
|
|
@ -164,4 +164,5 @@ public class BufferGaugeServiceSpeedTests {
|
||||||
}
|
}
|
||||||
watch.stop();
|
watch.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,4 +61,5 @@ public class CounterBuffersTests {
|
||||||
public void findNonExistent() {
|
public void findNonExistent() {
|
||||||
assertNull(this.buffers.find("foo"));
|
assertNull(this.buffers.find("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speed tests for {@link CounterService}.
|
* Speed tests for {@link CounterService}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
@RunWith(Theories.class)
|
@RunWith(Theories.class)
|
||||||
|
@ -162,4 +163,5 @@ public class CounterServiceSpeedTests {
|
||||||
}
|
}
|
||||||
watch.stop();
|
watch.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,4 +126,5 @@ public class DefaultGaugeServiceSpeedTests {
|
||||||
System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms");
|
System.err.println("Read(" + count + ")=" + watch.getLastTaskTimeMillis() + "ms");
|
||||||
assertTrue(0 < total.longValue());
|
assertTrue(0 < total.longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices;
|
|
||||||
|
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
@ -114,13 +113,15 @@ public class DropwizardMetricServicesTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WriterThread extends Thread {
|
public static class WriterThread extends Thread {
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private boolean failed;
|
private boolean failed;
|
||||||
|
|
||||||
private DropwizardMetricServices writer;
|
private DropwizardMetricServices writer;
|
||||||
|
|
||||||
public WriterThread(ThreadGroup group, int index, DropwizardMetricServices writer) {
|
public WriterThread(ThreadGroup group, int index, DropwizardMetricServices writer) {
|
||||||
super(group, "Writer-" + index);
|
super(group, "Writer-" + index);
|
||||||
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
}
|
}
|
||||||
|
@ -143,5 +144,7 @@ public class DropwizardMetricServicesTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,16 @@ import org.springframework.boot.actuate.metrics.repository.InMemoryMetricReposit
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link MetricCopyExporter}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class MetricCopyExporterTests {
|
public class MetricCopyExporterTests {
|
||||||
|
|
||||||
private final InMemoryMetricRepository writer = new InMemoryMetricRepository();
|
private final InMemoryMetricRepository writer = new InMemoryMetricRepository();
|
||||||
|
|
||||||
private final InMemoryMetricRepository reader = new InMemoryMetricRepository();
|
private final InMemoryMetricRepository reader = new InMemoryMetricRepository();
|
||||||
|
|
||||||
private final MetricCopyExporter exporter = new MetricCopyExporter(this.reader,
|
private final MetricCopyExporter exporter = new MetricCopyExporter(this.reader,
|
||||||
this.writer);
|
this.writer);
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,20 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link MetricExporters}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class MetricExportersTests {
|
public class MetricExportersTests {
|
||||||
|
|
||||||
private MetricExporters exporters;
|
private MetricExporters exporters;
|
||||||
|
|
||||||
private MetricExportProperties export = new MetricExportProperties();
|
private MetricExportProperties export = new MetricExportProperties();
|
||||||
|
|
||||||
private Map<String, MetricWriter> writers = new LinkedHashMap<String, MetricWriter>();
|
private Map<String, MetricWriter> writers = new LinkedHashMap<String, MetricWriter>();
|
||||||
|
|
||||||
private MetricReader reader = Mockito.mock(MetricReader.class);
|
private MetricReader reader = Mockito.mock(MetricReader.class);
|
||||||
|
|
||||||
private MetricWriter writer = Mockito.mock(MetricWriter.class);
|
private MetricWriter writer = Mockito.mock(MetricWriter.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,12 +25,16 @@ import org.springframework.boot.actuate.metrics.rich.InMemoryRichGaugeRepository
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link RichGaugeExporter}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class RichGaugeExporterTests {
|
public class RichGaugeExporterTests {
|
||||||
|
|
||||||
private final InMemoryRichGaugeRepository reader = new InMemoryRichGaugeRepository();
|
private final InMemoryRichGaugeRepository reader = new InMemoryRichGaugeRepository();
|
||||||
|
|
||||||
private final InMemoryMetricRepository writer = new InMemoryMetricRepository();
|
private final InMemoryMetricRepository writer = new InMemoryMetricRepository();
|
||||||
|
|
||||||
private final RichGaugeExporter exporter = new RichGaugeExporter(this.reader,
|
private final RichGaugeExporter exporter = new RichGaugeExporter(this.reader,
|
||||||
this.writer);
|
this.writer);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
package org.springframework.boot.actuate.metrics.integration;
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
package org.springframework.boot.actuate.metrics.integration;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -17,22 +31,29 @@ import org.springframework.integration.monitor.IntegrationMBeanExporter;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link SpringIntegrationMetricReader}.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@SpringApplicationConfiguration(classes=TestConfiguration.class)
|
@SpringApplicationConfiguration(classes = TestConfiguration.class)
|
||||||
@IntegrationTest("spring.jmx.enabled=true")
|
@IntegrationTest("spring.jmx.enabled=true")
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
public class SpringIntegrationMetricReaderTests {
|
public class SpringIntegrationMetricReaderTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SpringIntegrationMetricReader reader;
|
private SpringIntegrationMetricReader reader;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
assertTrue(reader.count()>0);
|
assertTrue(this.reader.count() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import({JmxAutoConfiguration.class, IntegrationAutoConfiguration.class})
|
@Import({ JmxAutoConfiguration.class, IntegrationAutoConfiguration.class })
|
||||||
protected static class TestConfiguration {
|
protected static class TestConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public SpringIntegrationMetricReader reader(IntegrationMBeanExporter exporter) {
|
public SpringIntegrationMetricReader reader(IntegrationMBeanExporter exporter) {
|
||||||
|
|
|
@ -23,6 +23,8 @@ import org.junit.Test;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link DefaultMetricNamingStrategy}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class DefaultMetricNamingStrategyTests {
|
public class DefaultMetricNamingStrategyTests {
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Matchers;
|
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.springframework.boot.actuate.metrics.Metric;
|
import org.springframework.boot.actuate.metrics.Metric;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -29,9 +28,13 @@ import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.client.RestOperations;
|
import org.springframework.web.client.RestOperations;
|
||||||
|
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tests for {@link OpenTsdbMetricWriter}.
|
||||||
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
public class OpenTsdbMetricWriterTests {
|
public class OpenTsdbMetricWriterTests {
|
||||||
|
@ -48,25 +51,19 @@ public class OpenTsdbMetricWriterTests {
|
||||||
@Test
|
@Test
|
||||||
public void postSuccessfullyOnFlush() {
|
public void postSuccessfullyOnFlush() {
|
||||||
this.writer.set(new Metric<Double>("foo", 2.4));
|
this.writer.set(new Metric<Double>("foo", 2.4));
|
||||||
given(
|
given(this.restTemplate.postForEntity(anyString(), any(Object.class), anyMap()))
|
||||||
this.restTemplate.postForEntity(Matchers.anyString(),
|
|
||||||
Matchers.any(Object.class), anyMap()))
|
|
||||||
.willReturn(emptyResponse());
|
.willReturn(emptyResponse());
|
||||||
this.writer.flush();
|
this.writer.flush();
|
||||||
verify(this.restTemplate).postForEntity(Matchers.anyString(),
|
verify(this.restTemplate).postForEntity(anyString(), any(Object.class), anyMap());
|
||||||
Matchers.any(Object.class), anyMap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flushAutomaticlly() {
|
public void flushAutomaticlly() {
|
||||||
given(
|
given(this.restTemplate.postForEntity(anyString(), any(Object.class), anyMap()))
|
||||||
this.restTemplate.postForEntity(Matchers.anyString(),
|
|
||||||
Matchers.any(Object.class), anyMap()))
|
|
||||||
.willReturn(emptyResponse());
|
.willReturn(emptyResponse());
|
||||||
this.writer.setBufferSize(0);
|
this.writer.setBufferSize(0);
|
||||||
this.writer.set(new Metric<Double>("foo", 2.4));
|
this.writer.set(new Metric<Double>("foo", 2.4));
|
||||||
verify(this.restTemplate).postForEntity(Matchers.anyString(),
|
verify(this.restTemplate).postForEntity(anyString(), any(Object.class), anyMap());
|
||||||
Matchers.any(Object.class), anyMap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -76,7 +73,7 @@ public class OpenTsdbMetricWriterTests {
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private Class<Map> anyMap() {
|
private Class<Map> anyMap() {
|
||||||
return Matchers.any(Class.class);
|
return any(Class.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ public class StatsdMetricWriterTests {
|
||||||
private static final class DummyStatsDServer {
|
private static final class DummyStatsDServer {
|
||||||
|
|
||||||
private final List<String> messagesReceived = new ArrayList<String>();
|
private final List<String> messagesReceived = new ArrayList<String>();
|
||||||
|
|
||||||
private final DatagramSocket server;
|
private final DatagramSocket server;
|
||||||
|
|
||||||
public DummyStatsDServer(int port) {
|
public DummyStatsDServer(int port) {
|
||||||
|
@ -141,5 +142,7 @@ public class StatsdMetricWriterTests {
|
||||||
public List<String> messagesReceived() {
|
public List<String> messagesReceived() {
|
||||||
return new ArrayList<String>(this.messagesReceived);
|
return new ArrayList<String>(this.messagesReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2013 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Spring Boot sample with Redis export for metrics.
|
= Spring Boot sample with Redis export for metrics.
|
||||||
|
|
||||||
Start redis, e.g. with [Docker Compose]()
|
Start redis, e.g. with [Docker Compose]()
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,6 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Dave Syer
|
|
||||||
*/
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AggregateMetricsConfiguration {
|
public class AggregateMetricsConfiguration {
|
||||||
|
|
||||||
|
@ -45,8 +42,8 @@ public class AggregateMetricsConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
private MetricReader globalMetricsForAggregation() {
|
private MetricReader globalMetricsForAggregation() {
|
||||||
return new RedisMetricRepository(this.connectionFactory,
|
return new RedisMetricRepository(this.connectionFactory, this.export.getRedis()
|
||||||
this.export.getRedis().getAggregatePrefix(), this.export.getRedis().getKey());
|
.getAggregatePrefix(), this.export.getRedis().getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MetricReader aggregatesMetricReader() {
|
private MetricReader aggregatesMetricReader() {
|
||||||
|
|
|
@ -42,8 +42,8 @@ public class SampleRedisExportApplication {
|
||||||
@ExportMetricWriter
|
@ExportMetricWriter
|
||||||
public RedisMetricRepository redisMetricWriter(
|
public RedisMetricRepository redisMetricWriter(
|
||||||
RedisConnectionFactory connectionFactory) {
|
RedisConnectionFactory connectionFactory) {
|
||||||
return new RedisMetricRepository(connectionFactory, this.export.getRedis().getPrefix(),
|
return new RedisMetricRepository(connectionFactory, this.export.getRedis()
|
||||||
this.export.getRedis().getKey());
|
.getPrefix(), this.export.getRedis().getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
Loading…
Reference in New Issue