autoconfig
~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/MetricsDropwizardAutoConfiguration.java
@Configuration
@ConditionalOnClass(MetricRegistry.class)
@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class)
public class MetricsDropwizardAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MetricRegistry metricRegistry() {
return new MetricRegistry();
}
@Bean
@ConditionalOnMissingBean({ DropwizardMetricServices.class, CounterService.class,
GaugeService.class })
public DropwizardMetricServices dropwizardMetricServices(
MetricRegistry metricRegistry) {
return new DropwizardMetricServices(metricRegistry);
}
@Bean
public MetricReaderPublicMetrics dropwizardPublicMetrics(
MetricRegistry metricRegistry) {
MetricRegistryMetricReader reader = new MetricRegistryMetricReader(
metricRegistry);
return new MetricReaderPublicMetrics(reader);
}
}
这里将dropwizard的metrics包装为MetricReaderPublicMetrics
MetricRegistryMetricReader
~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java
public class MetricRegistryMetricReader implements MetricReader, MetricRegistryListener {
private static final Log logger = LogFactory.getLog(MetricRegistryMetricReader.class);
private static final Map<Class<?>, Set<String>> numberKeys = new ConcurrentHashMap<Class<?>, Set<String>>();
private final Object monitor = new Object();
private final Map<String, String> names = new ConcurrentHashMap<String, String>();
private final MultiValueMap<String, String> reverse = new LinkedMultiValueMap<String, String>();
private final MetricRegistry registry;
public MetricRegistryMetricReader(MetricRegistry registry) {
this.registry = registry;
registry.addListener(this);
}
@Override
public Metric<?> findOne(String metricName) {
String name = this.names.get(metricName);
if (name == null) {
return null;
}
com.codahale.metrics.Metric metric = this.registry.getMetrics().get(name);
if (metric == null) {
return null;
}
if (metric instanceof Counter) {
Counter counter = (Counter) metric;
return new Metric<Number>(metricName, counter.getCount());
}
if (metric instanceof Gauge) {
Object value = ((Gauge<?>) metric).getValue();
if (value instanceof Number) {
return new Metric<Number>(metricName, (Number) value);
}
if (logger.isDebugEnabled()) {
logger.debug("Ignoring gauge '" + name + "' (" + metric
+ ") as its value is not a Number");
}
return null;
}
if (metric instanceof Sampling) {
if (metricName.contains(".snapshot.")) {
Number value = getMetric(((Sampling) metric).getSnapshot(), metricName);
if (metric instanceof Timer) {
// convert back to MILLISEC
value = TimeUnit.MILLISECONDS.convert(value.longValue(),
TimeUnit.NANOSECONDS);
}
return new Metric<Number>(metricName, value);
}
}
return new Metric<Number>(metricName, getMetric(metric, metricName));
}
@Override
public Iterable<Metric<?>> findAll() {
return new Iterable<Metric<?>>() {
@Override
public Iterator<Metric<?>> iterator() {
Set<Metric<?>> metrics = new HashSet<Metric<?>>();
for (String name : MetricRegistryMetricReader.this.names.keySet()) {
Metric<?> metric = findOne(name);
if (metric != null) {
metrics.add(metric);
}
}
return metrics.iterator();
}
};
}
@Override
public long count() {
return this.names.size();
}
@Override
public void onGaugeAdded(String name, Gauge<?> gauge) {
this.names.put(name, name);
synchronized (this.monitor) {
this.reverse.add(name, name);
}
}
@Override
public void onGaugeRemoved(String name) {
remove(name);
}
@Override
public void onCounterAdded(String name, Counter counter) {
this.names.put(name, name);
synchronized (this.monitor) {
this.reverse.add(name, name);
}
}
@Override
public void onCounterRemoved(String name) {
remove(name);
}
@Override
public void onHistogramAdded(String name, Histogram histogram) {
for (String key : getNumberKeys(histogram)) {
String metricName = name + "." + key;
this.names.put(metricName, name);
synchronized (this.monitor) {
this.reverse.add(name, metricName);
}
}
for (String key : getNumberKeys(histogram.getSnapshot())) {
String metricName = name + ".snapshot." + key;
this.names.put(metricName, name);
synchronized (this.monitor) {
this.reverse.add(name, metricName);
}
}
}
@Override
public void onHistogramRemoved(String name) {
remove(name);
}
@Override
public void onMeterAdded(String name, Meter meter) {
for (String key : getNumberKeys(meter)) {
String metricName = name + "." + key;
this.names.put(metricName, name);
synchronized (this.monitor) {
this.reverse.add(name, metricName);
}
}
}
@Override
public void onMeterRemoved(String name) {
remove(name);
}
@Override
public void onTimerAdded(String name, Timer timer) {
for (String key : getNumberKeys(timer)) {
String metricName = name + "." + key;
this.names.put(metricName, name);
synchronized (this.monitor) {
this.reverse.add(name, metricName);
}
}
for (String key : getNumberKeys(timer.getSnapshot())) {
String metricName = name + ".snapshot." + key;
this.names.put(metricName, name);
synchronized (this.monitor) {
this.reverse.add(name, metricName);
}
}
}
@Override
public void onTimerRemoved(String name) {
remove(name);
}
private void remove(String name) {
List<String> keys;
synchronized (this.monitor) {
keys = this.reverse.remove(name);
}
if (keys != null) {
for (String key : keys) {
this.names.remove(name + "." + key);
}
}
}
private static Set<String> getNumberKeys(Object metric) {
Set<String> result = numberKeys.get(metric.getClass());
if (result == null) {
result = new HashSet<String>();
}
if (result.isEmpty()) {
for (PropertyDescriptor descriptor : BeanUtils
.getPropertyDescriptors(metric.getClass())) {
if (ClassUtils.isAssignable(Number.class, descriptor.getPropertyType())) {
result.add(descriptor.getName());
}
}
numberKeys.put(metric.getClass(), result);
}
return result;
}
private static Number getMetric(Object metric, String metricName) {
String key = StringUtils.getFilenameExtension(metricName);
return (Number) new BeanWrapperImpl(metric).getPropertyValue(key);
}
}
PublicMetricsAutoConfiguration
~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java
@Configuration
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, CacheAutoConfiguration.class,
MetricRepositoryAutoConfiguration.class, CacheStatisticsAutoConfiguration.class,
IntegrationAutoConfiguration.class })
public class PublicMetricsAutoConfiguration {
private final List<MetricReader> metricReaders;
public PublicMetricsAutoConfiguration(
@ExportMetricReader ObjectProvider<List<MetricReader>> metricReadersProvider) {
this.metricReaders = metricReadersProvider.getIfAvailable();
}
@Bean
public SystemPublicMetrics systemPublicMetrics() {
return new SystemPublicMetrics();
}
@Bean
public MetricReaderPublicMetrics metricReaderPublicMetrics() {
return new MetricReaderPublicMetrics(
new CompositeMetricReader(this.metricReaders == null ? new MetricReader[0]
: this.metricReaders
.toArray(new MetricReader[this.metricReaders.size()])));
}
@Bean
@ConditionalOnBean(RichGaugeReader.class)
public RichGaugeReaderPublicMetrics richGaugePublicMetrics(
RichGaugeReader richGaugeReader) {
return new RichGaugeReaderPublicMetrics(richGaugeReader);
}
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnBean(DataSource.class)
static class DataSourceMetricsConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(DataSourcePoolMetadataProvider.class)
public DataSourcePublicMetrics dataSourcePublicMetrics() {
return new DataSourcePublicMetrics();
}
}
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnWebApplication
static class TomcatMetricsConfiguration {
@Bean
@ConditionalOnMissingBean
public TomcatPublicMetrics tomcatPublicMetrics() {
return new TomcatPublicMetrics();
}
}
@Configuration
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheManager.class)
static class CacheStatisticsConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(CacheStatisticsProvider.class)
public CachePublicMetrics cachePublicMetrics() {
return new CachePublicMetrics();
}
}
@Configuration
@ConditionalOnClass(IntegrationMBeanExporter.class)
@ConditionalOnBean(IntegrationMBeanExporter.class)
@ConditionalOnJava(JavaVersion.SEVEN)
@UsesJava7
static class IntegrationMetricsConfiguration {
@Bean
@ConditionalOnMissingBean(name = "springIntegrationPublicMetrics")
public MetricReaderPublicMetrics springIntegrationPublicMetrics(
IntegrationMBeanExporter exporter) {
return new MetricReaderPublicMetrics(
new SpringIntegrationMetricReader(exporter));
}
}
}
这里既有SystemPublicMetrics,也有MetricReaderPublicMetrics,使用了CompositeMetricReader
MetricsEndpoint
~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java
@ConfigurationProperties(prefix = "endpoints.metrics")
public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
private final List<PublicMetrics> publicMetrics;
/**
* Create a new {@link MetricsEndpoint} instance.
* @param publicMetrics the metrics to expose
*/
public MetricsEndpoint(PublicMetrics publicMetrics) {
this(Collections.singleton(publicMetrics));
}
/**
* Create a new {@link MetricsEndpoint} instance.
* @param publicMetrics the metrics to expose. The collection will be sorted using the
* {@link AnnotationAwareOrderComparator}.
*/
public MetricsEndpoint(Collection<PublicMetrics> publicMetrics) {
super("metrics");
Assert.notNull(publicMetrics, "PublicMetrics must not be null");
this.publicMetrics = new ArrayList<PublicMetrics>(publicMetrics);
AnnotationAwareOrderComparator.sort(this.publicMetrics);
}
public void registerPublicMetrics(PublicMetrics metrics) {
this.publicMetrics.add(metrics);
AnnotationAwareOrderComparator.sort(this.publicMetrics);
}
public void unregisterPublicMetrics(PublicMetrics metrics) {
this.publicMetrics.remove(metrics);
}
@Override
public Map<String, Object> invoke() {
Map<String, Object> result = new LinkedHashMap<String, Object>();
List<PublicMetrics> metrics = new ArrayList<PublicMetrics>(this.publicMetrics);
for (PublicMetrics publicMetric : metrics) {
try {
for (Metric<?> metric : publicMetric.metrics()) {
result.put(metric.getName(), metric.getValue());
}
}
catch (Exception ex) {
// Could not evaluate metrics
}
}
return result;
}
}
这里将public metric暴露在/metrics的endpoint上
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。