How to capture metrics for REST end points via micrometer libraray - spring

I am working on component that is based on spring framework. We have not yet moved to spring boot.
My requirement is to capture metrics(JVM/http/disk space) for my component which runs on an application server.
I came across micrometer library which can be utilized to capture such metrics and it can be integrated very well with Promotheus.
What I did was that I added the below dependency
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.7.5</version>
</dependency>
After adding the dependency I exposed a rest end point and added some simple logic to pull the metrics. Doing that I was able to fetch some basic JVM metrics. I referred the below link for this which explains how to capture metrics.
(https://micrometer.io/docs/ref/jvm)
However in addition to JVM metrics I also want to capture http request metrics(eg. the no of requests, time taken on the http calls to the rest services).
In my application there are quite many rest endpoints. Is there any way to do that. I was not able find any good documentation on that.
Any help would be highly appreciated.
Thanks
Sachin

As you said, Spring Boot does this out of the box so if you can move there, you don't need to do anything.
In order to instrument your web endpoints you can do a few things:
You can create a Filter and instrument all of your calls there.
This is what Spring Boot does, you can take a look/copy WebMvcMetricsFilter
You can add #Timer for your controllers and set-up TimedAspect
You can manually instrument your controllers see the docs

After following the above suggestions I was actually able to see my http metrics
I Simply created a configuration class annotated with #EnableAspectJAutoProxy and defined a bean inside the class as below
#Bean
public TimedAspect timedAspect() {
return new TimedAspect(registry);
}
And then added the #Timed annotation on my REST api POST methods and then I was able to see the statistics in Prometheus dashboard.
This really works!

Related

What is the correct way to add custom Prometheus metrics to a client library?

We have recently started monitoring our springboot apps with the micrometer prometheus integration. For the most part it works great out of the box; however, we have a client lib which wraps an http client for communicating with one of our apis that does NOT use Spring components, and is therefore excluded from the http_client_requests_* metric set.
The solution is obviously a #Timer annotation to manually add those custom metrics, and since our client api lib only exposes two methods, it would be ideal to just annotate these methods instead of having to add a timer anywhere I make a call with the lib in my app. The problem is, all of the setup instructions I find assume you're adding the integration to a server app instead of a lib, and I'm having trouble getting it to work.
I first tried adding the actuator and micrometer prometheus dependencies using compileOnly and runtimeOnly to hopefully not collide with the same dependencies being imported into my app, but even when that doesnt work and I change the imports to 'implementation' I get the 'No bean found with type of MeterRegistry' error other people have reported when I try to expose the TimedAspect bean like so:
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
Even if I got this to work, my thinking is I'd run into issues again with the
management.endpoints.web.exposure.include=health,info,prometheus
configuration the tutorials say is necessary to enable metrics collection, since my app already does this. So, before I get much deeper in attempting this approach I'd like to ask: Is there a better way to accomplish what I'm trying to do?

How to configure Micrometer's monitoring system at runtime with Spring Boot

I'm new to metrics in general and especially Micrometer, so this might be a dumb question:
Micrometer describes itself on the home page as a "facade" "without vendor lock-in", "think SLF4J, but for metrics". With "built-in support for [...] Netflix Atlas". The docs say it's included in Spring Boot 2.
So what I'd expect is the ability to configure the monitoring system on start-up - just as I would with SLF4J. So this doc describes a setting management.metrics.export.atlas.enabled (among others) for Spring Boot. But even with this setting auto-wiring a MeterRegistry registry fails as follows:
Parameter 4 of constructor in [snip] required a bean of type 'io.micrometer.core.instrument.MeterRegistry' that could not be found.
Action:
Consider defining a bean of type 'io.micrometer.core.instrument.MeterRegistry' in your configuration.
Google led me to Baeldung where I read about some micrometer-registry-atlas dependency plus providing a MeterRegistrybean of type AtlasMeterRegistry. This works, but it's not what I call a "facade without vendor lock-in", but I guess I'm just doing it wrong?
How can I provide the monitoring system during runtime, switching between Atlas and any other without re-compiling?
#crusy you are actually right, but the feature is part of the Actuator module. This is not well documented and I was lucky to find the answer in the Spring Boot Gitter channnel https://gitter.im/spring-projects/spring-boot/archives/2019/01/24?at=5c4980b00721b912a5cdc02f.
You will notice that the Metrics section in the Spring Boot documentation is under Actuator: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-metrics.
This means that in order for Micrometer to work out of the box, you need to include Actuator in your build. E.g for Gradle:
implementation ('org.springframework.boot:spring-boot-starter-actuator')
The MeterRegistry bean will be there now.
One of the definitions I found on Wikipedia says that vendor lock-in:
makes a customer dependent on a vendor for products and services,
unable to use another vendor without substantial switching costs.
Micrometer helps to unify interfaces to collect metrics (timers, gauges, counters, etc.), but there is no standard on how these metrics are shipped to backends (Atlas, Prometheus, etc.). That is the main reason why you need to define a specific library (micrometer-registry-atlas), properties, and sometimes also additional configuration.
Micrometer doesn't bring costs needed to switch to another backend to zero, but at least they are kept to minimum.

How do you find your way around a Spring codebase?

I'm started a position where the backend is in Spring and I'm having trouble. In Django, Flask, Rails, Express.js, etc, there are route files where you can find the declarations of the different URLs the server has responses configured for, and find your way around from there. Spring doesn't seem to have that....there's just files everywhere with annotations that transform the various classes into endpoints.
How do you find your way around or form some sort of mental conceptualization of the codebase's structure?
Here are some general-purpose tips:
Java IDEs are great, use them extensively. They can help in many cases.
All of them support spring boot applications. So you can open, say, pom.xml file and it will load the project.
All Rest Controllers are usually annotated with #RestController annotation
If you think the #RestController is too generic and you need something much more fine-grained in your project, consider using Spring Feature called "Stereo Type annotations". In short, you can define your own annotation (like #MyOwnVeryCustomProjectController) that will be itself marked as #RestController so that Spring boot will treat the classes annotated with that custom annotation just like Rest Controllers (you can also set up any parameter with reasonable defaults with this method).
If you use Java Configurations as opposed to a purely declarative approach with annotations and component scanning, then you might check whether there are #Configuration classes that aggregate bean definitions for all controllers.
Use Spring Actuator in Spring Boot services. In short, it exposes some HTTP endpoints, to any spring-boot process. Among other (fairly useful) endpoints, there is a mappings endpoint, it displays a list of all #RequestMapping paths in Runtime.
Try to find a class marked with the annotation #RestController. This class will serve as a controller to the path in #RequestMapping("/student") with multiple URL/ endpoints marked by any of the one annotations:
#RequestMapping("delete")
#PostMapping("/create")
#GetMapping("/list")
#DeleteMapping("{id}")
#PutMapping("{id}")
Likewise, there can be multiple controllers each, in turn, having multiple endpoints.
Hope this helps.

How to trace total in/out bandwidth used by users in spring boot application?

After some researching, I have discovered that there is a spring actuator project which is used to monitor and log information about the application. Here is the link that suggests how to put log in to my own custom repository for post processing. [http://www.sedooe.com/2017/08/tracing-requests-and-responses-with-spring-boot-actuator/ ]
However, the total in/out byte counts are not included. I know that I can try to wrap HttpServeletRequest and HttpServeletResponse (in the filter, pass them to the filter chain so that it can count in/out throughput whenever they are consumed or written out) which will return custom SerlvetInputStream and ServletOutputStream that can count the number of bytes.
This seems to be a common problem in business application and there should already be a solution so I wonder if there is any easier way to achieve this.
From my understanding the Spring-Boot 1.5 actuator implementation doesn't provide such a functionality. (Assuming you are talking about Spring-Boot 1.5.)
What you could do is having a look at the Micrometer project. It's the new actuator metrics "backend" for Spring-Boot 2.0. In case you are still using Spring-Boot 1.5 you can use the micrometer-spring-legacy library in your app.
Key thing to understand here is that for Spring-Boot 1.5 this is a metric backend which is living next to the "old" actuator.
What the project provides is instrumentation for embedded Jetty and Tomcat server. Allthough only the latter does provide in and out traffic metrics.
Assuming Tomcat, you'll get tomcat_global_received_bytes_total and tomcat_global_sent_bytes_total metrics over which you can reason about in your favorite monitoring system.

Programmatically configure Spring Boot app

what's the easiest way to get the spring boot goodness but not try to autoconfigure all the things? For instance, to only run flyway with our already configured properties (some loaded via Consul + Spring Cloud), I was hoping I could do something like:
#Configuration
#Import({DataSourceAutoConfiguration.class, FlywayAutoConfiguration.class})
public class FlywaySetup {}
and have the main method just call SpringApplication.run(FlywaySetup.class)
The problem with this is it picks up all the Component Scan / crazy long list of other dependencies. Any way to specifically configure the dependencies (but still get the nicities of the framework)
If you run this app, it shouldn't use component scan at all. There's nothing that triggers component scan in spring boot besides #ComponentScan (that's available on #SpringBootApplication).
It would help if you could provide more accurate details rather than "crazy long list of other dependencies.". Running that FlywaySetup should only load those two configuration classes (important: these are not handled as auto-configuration anymore). If you have component scan, there's something else you're not showing.
You can exclude auto-configurations you don't need.
You may want to take a look at this SO answer to explore mechanism how to do that.

Resources