0

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上


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...


引用和评论

0 条评论
评论支持部分 Markdown 语法:**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用 @ 来通知其他用户。

AltStyle によって変換されたページ (->オリジナル) /