preface
Two weeks before the Spring Festival, I wrote two articles on the Spring Boot application integration with Prometheus + Grafana for monitoring alarms.
- Spring Boot Actuator Module Description: Health check, measurement, indicator collection and monitoring
- The SpringBoot microservice application integrates Prometheus + Grafana to monitor alarms
With the Spring Boot Actuator module + Micrometer-Registrie-Prometheus module, Spring Boot application and Prometheus integration become very simple.
But some of the older projects may be Spring MVC projects that are not Spring Boot. This time I’ll look at how traditional Spring MVC integrates with Prometheus. To sort of complete the series.
The relevant theoretical part, in fact, has been explained in the previous two articles, so I will not repeat it here and go straight into the practical part.
In field
1. Introduce dependencies
This is where Prometheus’s most basic Java client dependencies are introduced.
<properties> ... The < IO. Prometheus. Version > 0.8.0 < / IO. Prometheus. Version > < / properties > <! -- The client --> <dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient</artifactId> <version>${io.prometheus.version}</version> </dependency> <! -- Hotspot JVM metrics--> <dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_hotspot</artifactId> <version>${io.prometheus.version}</version> </dependency> <! -- https://mvnrepository.com/artifact/io.prometheus/simpleclient_servlet --> <dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_servlet</artifactId> <version>${io.prometheus.version}</version> </dependency>Copy the code
Simpleclient_hotspot helps to collect Hotspot JVM metrics, and there are other dependencies that can be found in the official Github research option
2. Configure a new endpoint
<servlet>
<servlet-name>metrics</servlet-name>
<servlet-class>io.prometheus.client.exporter.MetricsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>metrics</servlet-name>
<url-pattern>/metrics</url-pattern>
</servlet-mapping>
Copy the code
If you integrate Shiro and Spring Security, remember to configure the corresponding path
3. Enable JVM monitoring parameters
Add the following code to the startup class,
@PostConstruct
public void init(a) {
// Outputs JVM information
DefaultExports.initialize();
}
Copy the code
test
Now to start the project, visit http://ip:port/metrics and see the relevant metrics data:
# HELP jvm_buffer_pool_used_bytes Used bytes of a given JVM buffer pool. # TYPE jvm_buffer_pool_used_bytes gauge Jvm_buffer_pool_used_bytes {pool="direct",} 1791403.0 jVM_buffer_pool_used_bytes {pool="mapped",} 0.0 # HELP jvm_buffer_pool_capacity_bytes Bytes capacity of a given JVM buffer pool. # TYPE jvm_buffer_pool_capacity_bytes gauge Jvm_buffer_pool_capacity_bytes {pool="direct",} 1791403.0 jVM_BUFFer_pool_CAPACity_bytes {pool="mapped",} 0.0 # HELP jvm_buffer_pool_used_buffers Used buffers of a given JVM buffer pool. # TYPE jvm_buffer_pool_used_buffers gauge Jvm_buffer_pool_used_buffers {pool="direct",} 44.0 jvm_buffer_pool_used_buffers{pool="mapped",} 0.0 # HELP jvm_memory_pool_allocated_bytes_total Total bytes allocated in a given JVM memory pool. Only updated after GC, not continuously. # TYPE jvm_memory_pool_allocated_bytes_total counter jvm_memory_pool_allocated_bytes_total{pool="Code Cache",} 2.4131136E7 jVM_memorY_pool_allocated_bytes_total {pool="PS Eden Space",} 1.157973728E9 Jvm_memory_pool_allocated_bytes_total {pool="PS Old Gen",} 4.2983992E7 jVM_memory_pool_allocated_bytes_total {pool="PS Survivor Space",} 2.3271936E7 jVM_memorY_pool_allocated_bytes_total {pool="Compressed Class Space",} 6964912.0 Jvm_memory_pool_allocated_bytes_total {pool="Metaspace",} 5.9245208E7 # HELP jVM_classes_loaded The number of classes that are currently loaded in the JVM # TYPE jvm_classes_loaded gauge ......Copy the code
After data is available, the following steps (Prometheus acquisition metrics, visualization) are described in detail in the SpringBoot microservice application integration Prometheus + Grafana implementation for monitoring alarms.
4. Data burying point (custom Metrics)
Prometheus provides four different Metrics types :Counter, Gauge, Histogram, and Summary.
- Counter – A Counter that only increases and does not decrease
- Gauge – Gauges that can be added or subtracted
- Histogram – the corresponding buckets interval is used for statistical distribution
- Summary – Statistics of data distribution defined by the client
As for how to use it, the official doc provides detailed instructions. Here are two simple examples:
You can declare a special interceptor to handle the operation of statistical Metrics:
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex); }}Copy the code
Counter
Counters can be used to record types of metrics that only increase but do not decrease, such as the total number of application requests (http_requests_total).
For counters of type Counter, there is only one inc() method for Counter +1
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
// Use the request path and HTTP method as tags
private Counter requestCounter = Counter.build()
.name("io_namespace_http_requests_total")
.labelNames("path"."method")
.help("Total requests.")
.register();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Call the inc() technology +1
requestCounter.labels(request.getRequestURI(), request.getMethod()).inc();
super.afterCompletion(request, response, handler, ex); }}Copy the code
Some corresponding PromQL for common aggregation operations:
Commonly used # PromQL
## Query the total number of application requests
sum(io_namespace_http_requests_total)
Http requests per second
sum(rate(io_wise2c_gateway_requests_total[5m]))
## Query the URIs of Top N application requests
topk(10, sum(io_namespace_http_requests_total) by (path))
Copy the code
Histogram
The Buckets record the size (such as HTTP request bytes) and the number of events in the specified distribution range.
Take requests_latency_seconds as an example. Suppose we need to record the number of times the HTTP request response time fits within the distribution range {.005,.01,.025,.05,.075,.1,.25,.5,.75, 1, 2.5, 5, 7.5, 10}.
public class PrometheusMetricsInterceptor extends HandlerInterceptorAdapter {
private Histogram requestLatencyHistogram = Histogram.build()
.labelNames("path"."method"."code")
.name("io_namespace_http_requests_latency_seconds_histogram")
.help("Request latency in seconds.")
.register();
// The spring interceptor singleton is not thread-safe, so use threadLocal
private ThreadLocal<Histogram.Timer> timerThreadLocal = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Histogram.Timer histogramRequestTimer = requestLatencyHistogram.labels(request.getRequestURI(), request.getMethod()).startTimer();
timerThreadLocal.set(histogramRequestTimer);
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
Histogram.Timer histogramRequestTimer = timerThreadLocal.get();
histogramRequestTimer.observeDuration();
timerThreadLocal.remove();
super.afterCompletion(request, response, handler, ex); }}Copy the code
Finally, access the previously configured /metrics endpoint to see the corresponding buried point data.
conclusion
This completes the story of how traditional Spring MVC integrates with Prometheus and can be used in conjunction with the previous two articles.
I hope I can bring you some harvest.
If this article is helpful to you, please give me a thumbs up. This is my biggest motivation 🤝🤝🤗🤗.
reference
- The official doc
- Prometheus Book