Skip to content

Instantly share code, notes, and snippets.

@fastnsilver
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fastnsilver/bf3bd2dd3d7b00662c7e to your computer and use it in GitHub Desktop.
Save fastnsilver/bf3bd2dd3d7b00662c7e to your computer and use it in GitHub Desktop.
Another way to export metrics via statsd, graphite, and/or cloudwatch
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Collection;
import java.util.LinkedHashSet;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.core.Ordered;
import com.sun.management.OperatingSystemMXBean;
public class AdditionalSystemPublicMetrics implements PublicMetrics, Ordered {
private final RuntimeMXBean runtimeMXBean;
private final OperatingSystemMXBean operatingSystemMXBean;
private long processCpuUsageTime;
private long runtimeUpTime;
public AdditionalSystemPublicMetrics() {
runtimeMXBean = ManagementFactory.getRuntimeMXBean();
operatingSystemMXBean = (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 20;
}
@Override
public Collection<Metric<?>> metrics() {
Collection<Metric<?>> result = new LinkedHashSet<Metric<?>>();
addManagementMetrics(result);
return result;
}
private void addManagementMetrics(Collection<Metric<?>> result) {
result.add(new Metric<Double>("process.cpu.load", operatingSystemMXBean.getProcessCpuLoad()));
result.add(new Metric<Float>("process.cpu.usageTime", getProcessCpuUsage()));
}
private float getProcessCpuUsage() {
float cpuUsage = 0.0f;
// Save what we collected last time
final long lastProcessCpuUsageTime = processCpuUsageTime;
final long lastRuntimeUpTime = runtimeUpTime;
// Get new cpu related perf counters
processCpuUsageTime = operatingSystemMXBean.getProcessCpuTime();
runtimeUpTime = runtimeMXBean.getUptime();
final int nCPUs = operatingSystemMXBean.getAvailableProcessors();
if(lastRuntimeUpTime != 0 && lastRuntimeUpTime < runtimeUpTime) {
// elapsedCpu is in ns and elapsedTime is in ms.
final long elapsedCpu = processCpuUsageTime - lastProcessCpuUsageTime;
final long elapsedTime = runtimeUpTime - lastRuntimeUpTime;
// cpuUsage could go higher than 100% because elapsedTime
// and elapsedCpu are not fetched simultaneously. Limit to
// 99% to avoid Plotter showing a scale from 0% to 200%.
cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * nCPUs));
}
return cpuUsage;
}
}
@Configuration
@ConditionalOnAwsCloudEnvironment
@EnableContextCredentials
@EnableConfigurationProperties(MonitoringAgentSettings.class)
public class CloudWatchConfig {
@Autowired
private AWSCredentials awsCredentials;
@Autowired
private MonitoringAgentSettings agentSettings;
@Autowired
private MetricRegistry metricRegistry;
// @see https://github.com/blacklocus/metrics-cloudwatch
@Bean
@ConditionalOnProperty(name="monitoringAgent.cloudwatch.reporting.enabled", havingValue="true")
CloudWatchReportingBean cloudWatchReportingBean() {
return new CloudWatchReportingBean();
}
private final class CloudWatchReportingBean {
private final CloudWatchReporter reporter;
public CloudWatchReportingBean() {
reporter = new CloudWatchReporter(metricRegistry, agentSettings.getApplicationHostname(), MetricFilter.ALL, new AmazonCloudWatchAsyncClient(awsCredentials));
}
@PostConstruct
public void init() {
reporter.start(agentSettings.getRateMillis(), TimeUnit.MILLISECONDS);
}
@PreDestroy
public void destroy() {
reporter.stop();
}
}
}
@Component
public class MonitoringAgentSettings {
@Value("${spring.application.name}")
private String applicationName;
@Value("${monitoringAgent.graphite.hostname:}")
private String graphiteServerHostname;
@Value("${monitoringAgent.graphite.port:2003}")
private Integer graphiteServerPort;
@Value("${monitoringAgent.graphite.reporting.enabled:false}")
private boolean graphiteReportingEnabled;
@Value("${monitoringAgent.statsd.hostname:}")
private String statsdServerHostname;
@Value("${monitoringAgent.statsd.port:8125}")
private Integer statsdServerPort;
@Value("${monitoringAgent.statsd.reporting.enabled:false}")
private boolean statsdReportingEnabled;
@Value("${monitoringAgent.jmx.reporting.enabled:false}")
private boolean jmxReportingEnabled;
@Value("${monitoringAgent.cloudwatch.reporting.enabled:false}")
private boolean cloudwatchReportingEnabled;
@Value("${monitoringAgent.rateMillis:30000}")
private int rateMillis;
public String getApplicationName() {
return applicationName;
}
public String getApplicationHostname() {
String hostname = "localhost";
try {
hostname = InetAddress.getLocalHost().getHostName().replace('.', '_');
} catch (UnknownHostException uhe) {
// do nothing
}
final String shortName = applicationName.length() > 6 ? applicationName.substring(0, 6) : applicationName;
return shortName + "-" + hostname;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getGraphiteServerHostname() {
return graphiteServerHostname;
}
public void setGraphiteServerHostname(String graphiteServerHostname) {
this.graphiteServerHostname = graphiteServerHostname;
}
public Integer getGraphiteServerPort() {
return graphiteServerPort;
}
public void setGraphiteServerPort(Integer graphiteServerPort) {
this.graphiteServerPort = graphiteServerPort;
}
public String getStatsdServerHostname() {
return statsdServerHostname;
}
public void setStatsdServerHostname(String statsdServerHostname) {
this.statsdServerHostname = statsdServerHostname;
}
public Integer getStatsdServerPort() {
return statsdServerPort;
}
public void setStatsdServerPort(Integer statsdServerPort) {
this.statsdServerPort = statsdServerPort;
}
public int getRateMillis() {
return rateMillis;
}
public void setRateMillis(int rateMillis) {
this.rateMillis = rateMillis;
}
public boolean isGraphiteReportingEnabled() {
return graphiteReportingEnabled;
}
public void setGraphiteReportingEnabled(boolean graphiteReportingEnabled) {
this.graphiteReportingEnabled = graphiteReportingEnabled;
}
public boolean isStatsdReportingEnabled() {
return statsdReportingEnabled;
}
public void setStatsdReportingEnabled(boolean statsdReportingEnabled) {
this.statsdReportingEnabled = statsdReportingEnabled;
}
public boolean isJmxReportingEnabled() {
return jmxReportingEnabled;
}
public void setJmxReportingEnabled(boolean jmxReportingEnabled) {
this.jmxReportingEnabled = jmxReportingEnabled;
}
public boolean isCloudwatchReportingEnabled() {
return cloudwatchReportingEnabled;
}
public void setCloudwatchReportingEnabled(boolean cloudwatchReportingEnabled) {
this.cloudwatchReportingEnabled = cloudwatchReportingEnabled;
}
}
@Configuration
@EnableScheduling
@EnableConfigurationProperties(MonitoringAgentSettings.class)
@AutoConfigureAfter(MetricRepositoryAutoConfiguration.class)
public class MonitoringAgentSupport {
@Autowired
private MonitoringAgentSettings agentSettings;
// @see http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html#production-ready-code-hale-metrics
@Autowired
private MetricRegistry metricRegistry;
@Bean
public AdditionalSystemPublicMetrics additionalSystemPublicMetrics() {
return new AdditionalSystemPublicMetrics();
}
// @see https://github.com/jjagged/metrics-statsd
@Bean
@ConditionalOnClass(value={StatsD.class, StatsDReporter.class})
@ConditionalOnProperty(name="monitoringAgent.statsd.reporting.enabled", havingValue="true")
public StatsDReportingBean statsDReportingBean() {
return new StatsDReportingBean();
}
// @see https://dropwizard.github.io/metrics/3.1.0/manual/graphite/
@Bean
@ConditionalOnClass(value={PickledGraphite.class, GraphiteReporter.class})
@ConditionalOnProperty(name="monitoringAgent.jmx.graphite.enabled", havingValue="true")
public GraphiteReportingBean graphiteReportingBean() {
return new GraphiteReportingBean();
}
// @see https://dropwizard.github.io/metrics/3.1.0/manual/core/#man-core-reporters-jmx
// not recommended for production use!
@Bean
@ConditionalOnProperty(name="monitoringAgent.jmx.reporting.enabled", havingValue="true")
public JmxReportingBean jmxReportingBean() {
return new JmxReportingBean();
}
// @see https://dropwizard.github.io/metrics/3.1.0/manual/servlet/
@Bean
public FilterRegistrationBean filterRegistrationBean() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new InstrumentedFilter());
return registrationBean;
}
private final class GraphiteReportingBean {
private final GraphiteReporter reporter;
public GraphiteReportingBean() {
final PickledGraphite pickledGraphite = new PickledGraphite(new InetSocketAddress(agentSettings.getGraphiteServerHostname(), agentSettings.getGraphiteServerPort()));
reporter = GraphiteReporter.forRegistry(metricRegistry)
.prefixedWith(agentSettings.getApplicationHostname())
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL)
.build(pickledGraphite);
}
@PostConstruct
public void init() {
reporter.start(agentSettings.getRateMillis(), TimeUnit.MILLISECONDS);
}
@PreDestroy
public void destroy() {
reporter.stop();
}
}
private final class StatsDReportingBean {
private final StatsDReporter reporter;
public StatsDReportingBean() {
final StatsD statsD = new StatsD(agentSettings.getStatsdServerHostname(), agentSettings.getStatsdServerPort());
reporter = StatsDReporter.forRegistry(metricRegistry)
.prefixedWith(agentSettings.getApplicationHostname())
.convertDurationsTo(TimeUnit.MILLISECONDS)
.convertRatesTo(TimeUnit.SECONDS)
.filter(MetricFilter.ALL)
.build(statsD);
}
@PostConstruct
public void init() {
reporter.start(agentSettings.getRateMillis(), TimeUnit.MILLISECONDS);
}
@PreDestroy
public void destroy() {
reporter.stop();
}
}
private final class JmxReportingBean {
private final JmxReporter reporter;
public JmxReportingBean() {
reporter = JmxReporter.forRegistry(metricRegistry).build();
}
@PostConstruct
public void init() {
reporter.start();
}
@PreDestroy
public void destroy() {
reporter.stop();
}
}
}
<!-- @see http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html#production-ready-code-hale-metrics -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-servlet</artifactId>
<version>${dropwizard-metrics.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-graphite</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-jvm</artifactId>
<version>${dropwizard-metrics.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-jetty9</artifactId>
<version>${dropwizard-metrics.version}</version>
<scope>provided</scope>
</dependency>
<!-- @see https://github.com/jjagged/metrics-statsd -->
<dependency>
<groupId>com.github.jjagged</groupId>
<artifactId>metrics-statsd</artifactId>
<version>1.0.0</version>
</dependency>
<!-- @see https://github.com/blacklocus/metrics-cloudwatch -->
<dependency>
<groupId>com.blacklocus</groupId>
<artifactId>metrics-cloudwatch</artifactId>
<version>0.3.4</version>
</dependency>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment