Metrics Collection for Spring Boot REST APIs
Asked Answered
E

3

9

I am trying to collect metrics for my Spring Boot(2.1.0.RELEASE) Application. Specifically, I want to know

  1. No of times individual REST endpoints were called.
  2. Time taken by each of those endpoints to process the request.
  3. Average rate at which my requests are being processed/errored.

The actuator /actuator/metrics endpoint gives lot of info but I am not sure if any of those are useful for my case. Also, can someone tell if @Timed(or any other out-of-the-box annotation) can be used for achieving those stats or I have to use something like below in every controller method:

  Timer timer = new SimpleMeterRegistry().timer("timer.name");
timer.record(() -> {
    // all logic here
});

I tried using @Timed on my controller method but it doesn't adds any new response to the /actuator/metrics endpoint.

Escobar answered 11/7, 2019 at 10:50 Comment(0)
B
17

You can use Spring Boot /actuator/metrics/http.server.requests to get all endPoints which are executed with their count, exception, outcome, status, total time, etc as follow.

If you want to see details for particular endPoint then you can do it by calling request as follow

localhost:8889/actuator/metrics/http.server.requests?tag=uri:<endPoint>
localhost:8889/actuator/metrics/http.server.requests?tag=uri:/user/asset/getAllAssets
localhost:8889/actuator/metrics/http.server.requests?tag=uri:/user/asset/getAllAssets&tag=status:200
  • You will get COUNT as how many times particular endPoint has been called
  • You will get COUNT as how many times particular endPoint has been
    called with a particular Status
  • To get the average time to execute endPoint you can do TOTAL_TIME/COUNT for particular endPoint as well as for whole application

localhost:8889/actuator/metrics/http.server.requests

{
    "name": "http.server.requests",
    "description": null,
    "baseUnit": "seconds",
    "measurements": [
        {
            "statistic": "COUNT",
            "value": 3
        },
        {
            "statistic": "TOTAL_TIME",
            "value": 0.21817219999999998
        },
        {
            "statistic": "MAX",
            "value": 0.1379249
        }
    ],
    "availableTags": [
        {
            "tag": "exception",
            "values": [
                "MethodArgumentTypeMismatchException",
                "None"
            ]
        },
        {
            "tag": "method",
            "values": [
                "GET"
            ]
        },
        {
            "tag": "uri",
            "values": [
                "/{id}.*",
                "/user/asset/getAsset/{assetId}",
                "/user/asset/getAllAssets"
            ]
        },
        {
            "tag": "outcome",
            "values": [
                "CLIENT_ERROR",
                "SUCCESS"
            ]
        },
        {
            "tag": "status",
            "values": [
                "400",
                "404",
                "200"
            ]
        }
    ]
}

localhost:8889/actuator/metrics/http.server.requests?tag=uri:/user/asset/getAllAssets

{
    "name": "http.server.requests",
    "description": null,
    "baseUnit": "seconds",
    "measurements": [
        {
            "statistic": "COUNT",
            "value": 1
        },
        {
            "statistic": "TOTAL_TIME",
            "value": 0.1379249
        },
        {
            "statistic": "MAX",
            "value": 0
        }
    ],
    "availableTags": [
        {
            "tag": "exception",
            "values": [
                "None"
            ]
        },
        {
            "tag": "method",
            "values": [
                "GET"
            ]
        },
        {
            "tag": "outcome",
            "values": [
                "SUCCESS"
            ]
        },
        {
            "tag": "status",
            "values": [
                "200"
            ]
        }
    ]
}
Bellinger answered 11/7, 2019 at 11:5 Comment(2)
But if we restart the application we will loose the existing data, is there a way to prevent this? also in case I want to add similar metrics to a class that communicates with an external server is this feasible on actuator level? for example I want to monitor how much time it is taking to send external requests to another application.Adonis
And you will not see the endpoint straight away, if you are running from local, hit the api once and then it will show up under http.server.requestsObnubilate
B
2

Another way is to use Spring Boot Admin. For that, we have to configure client-server. To avoid the error make sure the version for client-server dependency is the same. We can add the required metric from the dropdown as shown in images.

Client-Side:

pom.xml

<dependency>
     <groupId>de.codecentric</groupId>
     <artifactId>spring-boot-admin-starter-client</artifactId>
     <version>2.1.4</version>
</dependency>

application.properties

spring.boot.admin.api-path=/instances
spring.boot.admin.client.url=http://localhost:6699
management.endpoints.web.exposure.include=*

Server Side:

application.properties

server.port = 6699
spring.boot.admin.server.url=http://localhost:8889

pom.xml

 <dependency>
         <groupId>de.codecentric</groupId>
         <artifactId>spring-boot-admin-starter-server</artifactId>
         <version>2.1.4</version>
    </dependency>

Add @EnableAdminServer

import de.codecentric.boot.admin.server.config.EnableAdminServer;

@SpringBootApplication
@EnableAdminServer
public class AdminApplication {

    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }

}

GUI http://localhost:6699/#/applications

Homepage Homepage

Metrics Metric Colletion

Health enter image description here

Graphs enter image description here

Bellinger answered 8/10, 2019 at 6:57 Comment(0)
W
0

Use Actuator: To add the actuator to a Maven-based project, add the following ‘Starter’ dependency:

    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

For Gradle, use the following declaration:

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
    }

Actuator endpoints let you monitor and interact with your application. Spring Boot includes a number of built-in endpoints and lets you add your own. For example, the health endpoint provides basic application health information. By default, the health endpoint is mapped to /actuator/health.

By default, all endpoints except for shutdown are enabled.

Since Endpoints may contain sensitive information, you should carefully consider when to expose them. Add the below in the application.properties file to enable health and info

management.endpoints.jmx.exposure.include=health,info

or to enable everything except env and bean, do the below

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,bean
Wirer answered 27/12, 2021 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.