Skip to content
Snippets Groups Projects
Commit 14599cdd authored by Phil Winder's avatar Phil Winder Committed by GitHub
Browse files

Merge pull request #10 from microservices-demo/monitoring/prometheus

Added prometheus monitoring, available on /prometheus.
parents ed37296c 3bc5c992
No related branches found
No related tags found
No related merge requests found
......@@ -31,6 +31,20 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_common</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
......
package works.weave.socks.cart.configuration;
import io.prometheus.client.CollectorRegistry;
import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration;
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import works.weave.socks.cart.controllers.PrometheusEndpoint;
import works.weave.socks.cart.controllers.PrometheusMvcEndpoint;
import works.weave.socks.cart.monitoring.PrometheusMetricWriter;
@ManagementContextConfiguration
public class PrometheusEndpointContextConfiguration {
@Bean
public works.weave.socks.cart.controllers.PrometheusEndpoint prometheusEndpoint(CollectorRegistry registry) {
return new PrometheusEndpoint(registry);
}
@Bean
@ConditionalOnBean(PrometheusEndpoint.class)
@ConditionalOnEnabledEndpoint("prometheus")
PrometheusMvcEndpoint prometheusMvcEndpoint(PrometheusEndpoint prometheusEndpoint) {
return new PrometheusMvcEndpoint(prometheusEndpoint);
}
@Bean
CollectorRegistry collectorRegistry() {
return new CollectorRegistry();
}
@Bean
@ExportMetricWriter
MetricWriter prometheusMetricWriter(CollectorRegistry registry) {
return new PrometheusMetricWriter(registry);
}
}
package works.weave.socks.cart.controllers;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.common.TextFormat;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
public class PrometheusEndpoint extends AbstractEndpoint<String> {
private CollectorRegistry registry;
public PrometheusEndpoint(CollectorRegistry registry) {
super("prometheus", false, true);
this.registry = registry;
}
@Override
public String invoke() {
Writer writer = new StringWriter();
try {
TextFormat.write004(writer, registry.metricFamilySamples());
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
}
package works.weave.socks.cart.controllers;
import io.prometheus.client.exporter.common.TextFormat;
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointMvcAdapter;
import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Collections;
public class PrometheusMvcEndpoint extends AbstractEndpointMvcAdapter<PrometheusEndpoint> {
public PrometheusMvcEndpoint(PrometheusEndpoint delegate) {
super(delegate);
}
@RequestMapping(method = RequestMethod.GET, produces = TextFormat.CONTENT_TYPE_004)
@ResponseBody
@HypermediaDisabled
protected Object invoke() {
if (!getDelegate().isEnabled()) {
return new ResponseEntity<>(
Collections.singletonMap("message", "This endpoint is disabled"),
HttpStatus.NOT_FOUND);
}
return super.invoke();
}
}
package works.weave.socks.cart.monitoring;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Counter;
import io.prometheus.client.Gauge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.writer.Delta;
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class PrometheusMetricWriter implements MetricWriter {
private final ConcurrentMap<String, Counter> counters = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Gauge> gauges = new ConcurrentHashMap<>();
private CollectorRegistry registry;
@Autowired
public PrometheusMetricWriter(CollectorRegistry registry) {
this.registry = registry;
}
@Override
public void increment(Delta<?> delta) {
counter(delta.getName()).inc(delta.getValue().doubleValue());
}
@Override
public void reset(String metricName) {
counter(metricName).clear();
}
@Override
public void set(Metric<?> value) {
gauge(value.getName()).set(value.getValue().doubleValue());
}
private Counter counter(String name) {
String key = sanitizeName(name);
return counters.computeIfAbsent(key, k -> Counter.build().name(k).help(k).register(registry));
}
private Gauge gauge(String name) {
String key = sanitizeName(name);
return gauges.computeIfAbsent(key, k -> Gauge.build().name(k).help(k).register(registry));
}
private String sanitizeName(String name) {
return name.replaceAll("[^a-zA-Z0-9_]", "_");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment