Skip to content
This repository has been archived by the owner on Dec 5, 2023. It is now read-only.

Commit

Permalink
Merge pull request #10 from microservices-demo/monitoring/prometheus
Browse files Browse the repository at this point in the history
Added prometheus monitoring.
  • Loading branch information
pidster authored Sep 23, 2016
2 parents 90b03d2 + f4d9447 commit 34a5fe5
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
14 changes: 14 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package works.weave.socks.orders.config;

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.orders.controllers.PrometheusEndpoint;
import works.weave.socks.orders.controllers.PrometheusMvcEndpoint;
import works.weave.socks.orders.monitoring.PrometheusMetricWriter;

@ManagementContextConfiguration
public class PrometheusEndpointContextConfiguration {

@Bean
public 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);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package works.weave.socks.orders.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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package works.weave.socks.orders.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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package works.weave.socks.orders.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 comments on commit 34a5fe5

Please sign in to comment.