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

Commit 671b2ad

Browse files
authored
Merge pull request #9 from microservices-demo/monitoring/prometheus
Added prometheus monitoring.
2 parents cf23f23 + 64e8e11 commit 671b2ad

File tree

5 files changed

+169
-0
lines changed

5 files changed

+169
-0
lines changed

pom.xml

+14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@
3131
<groupId>org.springframework.boot</groupId>
3232
<artifactId>spring-boot-starter-data-mongodb</artifactId>
3333
</dependency>
34+
<dependency>
35+
<groupId>org.springframework.boot</groupId>
36+
<artifactId>spring-boot-starter-actuator</artifactId>
37+
</dependency>
38+
<dependency>
39+
<groupId>io.prometheus</groupId>
40+
<artifactId>simpleclient</artifactId>
41+
<version>RELEASE</version>
42+
</dependency>
43+
<dependency>
44+
<groupId>io.prometheus</groupId>
45+
<artifactId>simpleclient_common</artifactId>
46+
<version>RELEASE</version>
47+
</dependency>
3448
<dependency>
3549
<groupId>org.springframework.data</groupId>
3650
<artifactId>spring-data-rest-hal-browser</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package works.weave.socks.shipping.configuration;
2+
3+
import io.prometheus.client.CollectorRegistry;
4+
import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter;
5+
import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration;
6+
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
7+
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
8+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
9+
import org.springframework.context.annotation.Bean;
10+
import works.weave.socks.shipping.controllers.PrometheusEndpoint;
11+
import works.weave.socks.shipping.controllers.PrometheusMvcEndpoint;
12+
import works.weave.socks.shipping.monitoring.PrometheusMetricWriter;
13+
14+
@ManagementContextConfiguration
15+
public class PrometheusEndpointContextConfiguration {
16+
17+
@Bean
18+
public PrometheusEndpoint prometheusEndpoint(CollectorRegistry registry) {
19+
return new PrometheusEndpoint(registry);
20+
}
21+
22+
@Bean
23+
@ConditionalOnBean(PrometheusEndpoint.class)
24+
@ConditionalOnEnabledEndpoint("prometheus")
25+
PrometheusMvcEndpoint prometheusMvcEndpoint(PrometheusEndpoint prometheusEndpoint) {
26+
return new PrometheusMvcEndpoint(prometheusEndpoint);
27+
}
28+
29+
@Bean
30+
CollectorRegistry collectorRegistry() {
31+
return new CollectorRegistry();
32+
}
33+
34+
@Bean
35+
@ExportMetricWriter
36+
MetricWriter prometheusMetricWriter(CollectorRegistry registry) {
37+
return new PrometheusMetricWriter(registry);
38+
}
39+
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package works.weave.socks.shipping.controllers;
2+
3+
import io.prometheus.client.CollectorRegistry;
4+
import io.prometheus.client.exporter.common.TextFormat;
5+
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
6+
7+
import java.io.IOException;
8+
import java.io.StringWriter;
9+
import java.io.Writer;
10+
11+
public class PrometheusEndpoint extends AbstractEndpoint<String> {
12+
13+
private CollectorRegistry registry;
14+
15+
public PrometheusEndpoint(CollectorRegistry registry) {
16+
super("prometheus", false, true);
17+
this.registry = registry;
18+
}
19+
20+
@Override
21+
public String invoke() {
22+
Writer writer = new StringWriter();
23+
try {
24+
TextFormat.write004(writer, registry.metricFamilySamples());
25+
} catch (IOException e) {
26+
e.printStackTrace();
27+
}
28+
return writer.toString();
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package works.weave.socks.shipping.controllers;
2+
3+
import io.prometheus.client.exporter.common.TextFormat;
4+
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointMvcAdapter;
5+
import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RequestMethod;
10+
import org.springframework.web.bind.annotation.ResponseBody;
11+
12+
import java.util.Collections;
13+
14+
public class PrometheusMvcEndpoint extends AbstractEndpointMvcAdapter<PrometheusEndpoint> {
15+
16+
public PrometheusMvcEndpoint(PrometheusEndpoint delegate) {
17+
super(delegate);
18+
}
19+
20+
@RequestMapping(method = RequestMethod.GET, produces = TextFormat.CONTENT_TYPE_004)
21+
@ResponseBody
22+
@HypermediaDisabled
23+
protected Object invoke() {
24+
if (!getDelegate().isEnabled()) {
25+
return new ResponseEntity<>(
26+
Collections.singletonMap("message", "This endpoint is disabled"),
27+
HttpStatus.NOT_FOUND);
28+
}
29+
return super.invoke();
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package works.weave.socks.shipping.monitoring;
2+
3+
import io.prometheus.client.CollectorRegistry;
4+
import io.prometheus.client.Counter;
5+
import io.prometheus.client.Gauge;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.boot.actuate.metrics.Metric;
8+
import org.springframework.boot.actuate.metrics.writer.Delta;
9+
import org.springframework.boot.actuate.metrics.writer.MetricWriter;
10+
11+
import java.util.concurrent.ConcurrentHashMap;
12+
import java.util.concurrent.ConcurrentMap;
13+
14+
public class PrometheusMetricWriter implements MetricWriter {
15+
16+
private final ConcurrentMap<String, Counter> counters = new ConcurrentHashMap<>();
17+
private final ConcurrentMap<String, Gauge> gauges = new ConcurrentHashMap<>();
18+
private CollectorRegistry registry;
19+
20+
@Autowired
21+
public PrometheusMetricWriter(CollectorRegistry registry) {
22+
this.registry = registry;
23+
}
24+
25+
@Override
26+
public void increment(Delta<?> delta) {
27+
counter(delta.getName()).inc(delta.getValue().doubleValue());
28+
}
29+
30+
@Override
31+
public void reset(String metricName) {
32+
counter(metricName).clear();
33+
}
34+
35+
@Override
36+
public void set(Metric<?> value) {
37+
gauge(value.getName()).set(value.getValue().doubleValue());
38+
}
39+
40+
private Counter counter(String name) {
41+
String key = sanitizeName(name);
42+
return counters.computeIfAbsent(key, k -> Counter.build().name(k).help(k).register(registry));
43+
}
44+
45+
private Gauge gauge(String name) {
46+
String key = sanitizeName(name);
47+
return gauges.computeIfAbsent(key, k -> Gauge.build().name(k).help(k).register(registry));
48+
}
49+
50+
private String sanitizeName(String name) {
51+
return name.replaceAll("[^a-zA-Z0-9_]", "_");
52+
}
53+
54+
}

0 commit comments

Comments
 (0)