diff --git a/pom.xml b/pom.xml
index 3da5a30..e9acffa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,7 @@
UTF-8
1.8
+ 0.0.21
@@ -38,13 +39,18 @@
io.prometheus
- simpleclient
- RELEASE
+ simpleclient_spring_boot
+ ${prometheus.version}
io.prometheus
- simpleclient_common
- RELEASE
+ simpleclient_hotspot
+ ${prometheus.version}
+
+
+ io.prometheus
+ simpleclient_servlet
+ ${prometheus.version}
org.springframework.data
diff --git a/src/main/java/works/weave/socks/shipping/configuration/PrometheusAutoConfiguration.java b/src/main/java/works/weave/socks/shipping/configuration/PrometheusAutoConfiguration.java
new file mode 100644
index 0000000..a601eae
--- /dev/null
+++ b/src/main/java/works/weave/socks/shipping/configuration/PrometheusAutoConfiguration.java
@@ -0,0 +1,35 @@
+package works.weave.socks.shipping.configuration;
+
+import io.prometheus.client.exporter.MetricsServlet;
+import io.prometheus.client.hotspot.DefaultExports;
+import io.prometheus.client.spring.boot.SpringBootMetricsCollector;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.actuate.endpoint.PublicMetrics;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Collection;
+
+@Configuration
+@ConditionalOnClass(SpringBootMetricsCollector.class)
+class PrometheusAutoConfiguration {
+ @Bean
+ @ConditionalOnMissingBean(SpringBootMetricsCollector.class)
+ SpringBootMetricsCollector springBootMetricsCollector(Collection publicMetrics) {
+ SpringBootMetricsCollector springBootMetricsCollector = new SpringBootMetricsCollector
+ (publicMetrics);
+ springBootMetricsCollector.register();
+ return springBootMetricsCollector;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(name = "prometheusMetricsServletRegistrationBean")
+ ServletRegistrationBean prometheusMetricsServletRegistrationBean(@Value("${prometheus.metrics" +
+ ".path:/metrics}") String metricsPath) {
+ DefaultExports.initialize();
+ return new ServletRegistrationBean(new MetricsServlet(), metricsPath);
+ }
+}
diff --git a/src/main/java/works/weave/socks/shipping/configuration/PrometheusEndpointContextConfiguration.java b/src/main/java/works/weave/socks/shipping/configuration/PrometheusEndpointContextConfiguration.java
deleted file mode 100644
index 109d191..0000000
--- a/src/main/java/works/weave/socks/shipping/configuration/PrometheusEndpointContextConfiguration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package works.weave.socks.shipping.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.shipping.controllers.PrometheusEndpoint;
-import works.weave.socks.shipping.controllers.PrometheusMvcEndpoint;
-import works.weave.socks.shipping.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);
- }
-
-}
diff --git a/src/main/java/works/weave/socks/shipping/configuration/WebMvcConfig.java b/src/main/java/works/weave/socks/shipping/configuration/WebMvcConfig.java
new file mode 100644
index 0000000..5e19be2
--- /dev/null
+++ b/src/main/java/works/weave/socks/shipping/configuration/WebMvcConfig.java
@@ -0,0 +1,25 @@
+package works.weave.socks.shipping.configuration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import works.weave.socks.shipping.middleware.HTTPMonitoringInterceptor;
+
+@Configuration
+public class WebMvcConfig extends WebMvcConfigurerAdapter {
+ @Autowired
+ private HTTPMonitoringInterceptor httpMonitoringInterceptor;
+
+ @Bean
+ HTTPMonitoringInterceptor httpMonitoringInterceptor() {
+ return new HTTPMonitoringInterceptor();
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(httpMonitoringInterceptor)
+ .addPathPatterns("/**");
+ }
+}
diff --git a/src/main/java/works/weave/socks/shipping/controllers/PrometheusEndpoint.java b/src/main/java/works/weave/socks/shipping/controllers/PrometheusEndpoint.java
deleted file mode 100644
index a297934..0000000
--- a/src/main/java/works/weave/socks/shipping/controllers/PrometheusEndpoint.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package works.weave.socks.shipping.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 {
-
- 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();
- }
-}
diff --git a/src/main/java/works/weave/socks/shipping/controllers/PrometheusMvcEndpoint.java b/src/main/java/works/weave/socks/shipping/controllers/PrometheusMvcEndpoint.java
deleted file mode 100644
index 9d527a1..0000000
--- a/src/main/java/works/weave/socks/shipping/controllers/PrometheusMvcEndpoint.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package works.weave.socks.shipping.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 {
-
- 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();
- }
-}
diff --git a/src/main/java/works/weave/socks/shipping/middleware/HTTPMonitoringInterceptor.java b/src/main/java/works/weave/socks/shipping/middleware/HTTPMonitoringInterceptor.java
new file mode 100644
index 0000000..2daad53
--- /dev/null
+++ b/src/main/java/works/weave/socks/shipping/middleware/HTTPMonitoringInterceptor.java
@@ -0,0 +1,48 @@
+package works.weave.socks.shipping.middleware;
+
+import io.prometheus.client.Histogram;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class HTTPMonitoringInterceptor implements HandlerInterceptor {
+ static final Histogram requestLatency = Histogram.build()
+ .name("request_duration_seconds")
+ .help("Request duration in seconds.")
+ .labelNames("service", "method", "route", "status_code")
+ .register();
+
+ private static final String startTimeKey = "startTime";
+
+ @Value("${spring.application.name:orders}")
+ private String serviceName;
+
+ @Override
+ public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse
+ httpServletResponse, Object o) throws Exception {
+ httpServletRequest.setAttribute(startTimeKey, System.nanoTime());
+ return true;
+ }
+
+ @Override
+ public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse
+ httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
+ long start = (long) httpServletRequest.getAttribute(startTimeKey);
+ long elapsed = System.nanoTime() - start;
+ double seconds = (double) elapsed / 1000000000.0;
+ requestLatency.labels(
+ serviceName,
+ httpServletRequest.getMethod(),
+ httpServletRequest.getServletPath(),
+ Integer.toString(httpServletResponse.getStatus())
+ ).observe(seconds);
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse
+ httpServletResponse, Object o, Exception e) throws Exception {
+ }
+}
diff --git a/src/main/java/works/weave/socks/shipping/monitoring/PrometheusMetricWriter.java b/src/main/java/works/weave/socks/shipping/monitoring/PrometheusMetricWriter.java
deleted file mode 100644
index 138472e..0000000
--- a/src/main/java/works/weave/socks/shipping/monitoring/PrometheusMetricWriter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package works.weave.socks.shipping.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 counters = new ConcurrentHashMap<>();
- private final ConcurrentMap 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_]", "_");
- }
-
-}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index fc33208..6c6418d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -4,3 +4,5 @@ endpoints.health.enabled=false
spring.zipkin.baseUrl=http://${zipkin:zipkin}:9411/
spring.sleuth.sampler.percentage=1.0
spring.application.name=shipping
+# Disable actuator metrics endpoints
+endpoints.metrics.enabled=false