Last active
August 29, 2015 14:18
-
-
Save fastnsilver/bf3bd2dd3d7b00662c7e to your computer and use it in GitHub Desktop.
Another way to export metrics via statsd, graphite, and/or cloudwatch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- @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