可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to export all of the metrics which are visible at the endpoint /metrics
to a StatsdMetricWriter
.
I've got the following configuration class so far:
package com.tonyghita.metricsdriven.service.config; import com.codahale.metrics.MetricRegistry; import com.ryantenney.metrics.spring.config.annotation.EnableMetrics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.autoconfigure.ExportMetricReader; import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter; import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.boot.actuate.metrics.reader.MetricRegistryMetricReader; import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter; import org.springframework.boot.actuate.metrics.writer.MetricWriter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableMetrics(proxyTargetClass = true) public class MetricsConfig { private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfig.class); @Value("${statsd.host:localhost}") private String host = "localhost"; @Value("${statsd.port:8125}") private int port; @Autowired private MetricRegistry metricRegistry; @Bean @ExportMetricReader public MetricReader metricReader() { return new MetricRegistryMetricReader(metricRegistry); } @Bean @ExportMetricWriter public MetricWriter metricWriter() { LOGGER.info("Configuring StatsdMetricWriter to export to {}:{}", host, port); return new StatsdMetricWriter(host, port); } }
Which writes all of the metrics which I've added to Statsd, but I'd like to also send the system/JVM metrics that are visible on the /metrics
endpoint.
What am I missing?
回答1:
I had the same problem and found a solution here: https://github.com/tzolov/export-metrics-example
Just add a MetricsEndpointMetricReader
to your config and everything available at th e/metrics endpoint will be published to the StatsdMetricWriter
.
Here is a complete example config for spring boot 1.3.x and dropwizard metrics-jvm 3.1.x:
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.jvm.GarbageCollectorMetricSet; import com.codahale.metrics.jvm.MemoryUsageGaugeSet; import com.codahale.metrics.jvm.ThreadStatesGaugeSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter; import org.springframework.boot.actuate.endpoint.MetricsEndpoint; import org.springframework.boot.actuate.endpoint.MetricsEndpointMetricReader; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.statsd.StatsdMetricWriter; import org.springframework.boot.actuate.metrics.writer.Delta; import org.springframework.boot.actuate.metrics.writer.MetricWriter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MetricsConfiguration { @Bean public MetricRegistry metricRegistry() { final MetricRegistry metricRegistry = new MetricRegistry(); metricRegistry.register("jvm.memory",new MemoryUsageGaugeSet()); metricRegistry.register("jvm.thread-states",new ThreadStatesGaugeSet()); metricRegistry.register("jvm.garbage-collector",new GarbageCollectorMetricSet()); return metricRegistry; } /* * Reading all metrics that appear on the /metrics endpoint to expose them to metrics writer beans. */ @Bean public MetricsEndpointMetricReader metricsEndpointMetricReader(final MetricsEndpoint metricsEndpoint) { return new MetricsEndpointMetricReader(metricsEndpoint); } @Bean @ConditionalOnProperty(prefix = "statsd", name = {"prefix", "host", "port"}) @ExportMetricWriter public MetricWriter statsdMetricWriter(@Value("${statsd.prefix}") String statsdPrefix, @Value("${statsd.host}") String statsdHost, @Value("${statsd.port}") int statsdPort) { return new StatsdMetricWriter(statsdPrefix, statsdHost, statsdPort); } }
回答2:
From what I've seen in spring-boot code, only calls to CounterService
and GaugeService
implementations are forwarded to dropwizard's MetricRegistry
.
Therefore, as you already observed, only counter.*
and gauge.*
metrics from the /metrics
endpoint will end up in Statsd
.
System and JVM metrics are exposed through custom SystemPublicMetrics
class, which doesn't use counter or gauge service.
I'm not sure if there is a simpler solution (maybe someone from Spring team will comment), but one way to do it (not spring-boot specific) would be to use a scheduled task that periodically writes system stats to the MetricRegistry
.
回答3:
To register JVM metrics you can use the JVM related MetricSets supplied by codehale.metrics.jvm library. You can just add the whole set without supplying whether they are gauges or counters.
Here is my example code where I am registering jvm related metrics:
@Configuration @EnableMetrics(proxyTargetClass = true) public class MetricsConfig { @Autowired private StatsdProperties statsdProperties; @Autowired private MetricsEndpoint metricsEndpoint; @Autowired private DataSourcePublicMetrics dataSourcePublicMetrics; @Bean @ExportMetricReader public MetricReader metricReader() { return new MetricRegistryMetricReader(metricRegistry()); } public MetricRegistry metricRegistry() { final MetricRegistry metricRegistry = new MetricRegistry(); //jvm metrics metricRegistry.register("jvm.gc",new GarbageCollectorMetricSet()); metricRegistry.register("jvm.mem",new MemoryUsageGaugeSet()); metricRegistry.register("jvm.thread-states",new ThreadStatesGaugeSet()); return metricRegistry; } @Bean @ConditionalOnProperty(prefix = "metrics.writer.statsd", name = {"host", "port"}) @ExportMetricWriter public MetricWriter statsdMetricWriter() { return new StatsdMetricWriter( statsdProperties.getPrefix(), statsdProperties.getHost(), statsdProperties.getPort() ); }
}
Note: I am using spring boot version 1.3.0.M4
回答4:
Enjoy! (see the public metrics logged in console as dropwizard metrics)
@Configuration @EnableMetrics @EnableScheduling public class MetricsReporter extends MetricsConfigurerAdapter { @Autowired private SystemPublicMetrics systemPublicMetrics; private MetricRegistry metricRegistry; @Scheduled(fixedDelay = 5000) void exportPublicMetrics() { for (Metric> metric : systemPublicMetrics.metrics()) { Counter counter = metricRegistry.counter(metric.getName()); counter.dec(counter.getCount()); counter.inc(Double.valueOf(metric.getValue().toString()).longValue()); } } @Override public void configureReporters(MetricRegistry metricRegistry) { this.metricRegistry = metricRegistry; ConsoleReporter.forRegistry(metricRegistry).build().start(10, TimeUnit.SECONDS); } }