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