CodeGym /Courses /Module 5. Spring /Lecture 114: Performance Metrics and Memory Monitoring

Lecture 114: Performance Metrics and Memory Monitoring

Module 5. Spring
Level 19 , Lesson 3
Available

Metrics are the indicators used to judge your application's state, performance, and health. To draw an analogy, metrics are like human health signs: temperature, blood pressure, pulse. For example, if your server suddenly starts "choking", Actuator can hint at what's wrong: too many requests, low memory, or maybe your server just decided to take a vacation.


Actuator Metrics

Spring Boot Actuator gives you a bunch of metrics out of the box. Here are some of the more interesting ones:

Metric Description
jvm.memory.used JVM memory usage
http.server.requests HTTP request metrics: request count, average response time, etc.
cpu.usage CPU usage
logback.events Number of logging events
jvm.threads.live Number of live JVM threads
jvm.gc.pause Garbage collector pause time

Not bad, right? And that's just the basic set. If you want more, like adding some extra spice to the soup, you can add your own custom metrics (we'll talk about custom metrics later in the course).

Metrics are available at the /actuator/metrics endpoint. To explore all metrics, just hit that endpoint in your browser or Postman and you'll get a full list of available measurements.

Example:

{
  "names": [
    "jvm.memory.used",
    "http.server.requests",
    "logback.events",
    "jvm.threads.live",
    "system.cpu.usage"
  ]
}

If you want to get specific data for a particular metric (for example, JVM memory usage), use the endpoint /actuator/metrics/{metric_name}.

Example:

curl http://localhost:8080/actuator/metrics/jvm.memory.used

The result might look like this:

{
  "name": "jvm.memory.used",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 12345678
    }
  ],
  "availableTags": [
    {
      "tag": "area",
      "values": ["heap", "nonheap"]
    }
  ]
}

Here value is the current amount of used memory, and tags like area indicate whether the memory belongs to heap or non-heap (don't try to memorize all the terms right now — we'll go through them later).


Performance monitoring: HTTP requests as a litmus test

One of the key metrics for performance monitoring is http.server.requests. It tracks all HTTP requests coming into your application. This data can be a gold mine for understanding user behavior and spotting issues.

What kind of information can you get from http.server.requests?

  • Request count. How many requests did your app handle in a given period?
  • Average response time. How quickly does your app respond to requests?
  • Errors. How many requests returned 4xx or 5xx statuses?

Use the same endpoint /actuator/metrics/http.server.requests for details. Here's an example response:

{
  "name": "http.server.requests",
  "measurements": [
    {
      "statistic": "COUNT",
      "value": 438
    },
    {
      "statistic": "TOTAL_TIME",
      "value": 125.8
    },
    {
      "statistic": "MAX",
      "value": 2.5
    }
  ],
  "availableTags": [
    {
      "tag": "status",
      "values": ["200", "404", "500"]
    },
    {
      "tag": "uri",
      "values": ["/api/users", "/api/orders"]
    }
  ]
}

How to read this response?

  • COUNT — total number of requests (in this case 438).
  • TOTAL_TIME — total time spent processing all requests (125.8 seconds).
  • MAX — maximum time spent processing a single request (2.5 seconds).

Tags let you filter requests, for example by response status (200, 404) or by URI (/api/users, /api/orders). Very handy for deep-dive analytics.

Practical scenario

If you see that the response time for a particular URI is too high, it could be caused by a slow DB query or CPU pressure. You can start digging deeper to fix the problem.


Memory: monitor the JVM so it doesn't boil over

The Java Virtual Machine (JVM) is like your app's engine. If something's off with it, everything breaks. Actuator provides useful metrics for monitoring memory:

  • jvm.memory.used — current memory usage.
  • jvm.memory.max — the maximum amount of available memory.
  • jvm.gc.pause — garbage collector pause time.

Understanding heap and non-heap

JVM memory is split into two main types:

  • Heap memory — used for storing objects created with new.
  • Non-heap memory — used for storing class metadata, static variables, and other things.

Example analysis of the jvm.memory.used metric:

{
  "name": "jvm.memory.used",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 98765432
    }
  ],
  "availableTags": [
    {
      "tag": "area",
      "values": ["heap", "nonheap"]
    }
  ]
}

If heap memory is filled to 90% (or more), that might be a sign of a memory leak or a reason to increase the JVM -Xmx setting.


Practical cases: when metrics save the day

Case 1: High CPU load

The system.cpu.usage metric shows overall CPU usage. If it's constantly above 80%, that's a clear sign the server is overloaded. The cause could be unoptimized code or simply too much load.

Case 2: Frequent garbage collections (GC)

The jvm.gc.pause metric tracks garbage collector pauses. If pauses happen too often or take a long time (tens of milliseconds), that can slow the whole system. Check whether you're allocating too many short-lived objects in a short period.


Hands-on exercise

  1. Integrate Actuator into your project. If you haven't done this yet, add the spring-boot-starter-actuator dependency to your pom.xml or build.gradle.
  2. Explore metrics. Check out the endpoints /actuator/metrics and /actuator/metrics/{metric_name}. Try to fetch data for http.server.requests and jvm.memory.used.
  3. Analyze the data. Based on the data you get, try to draw conclusions about your application's state. For example, how long does it take to handle HTTP requests? What's the current JVM memory usage?
// Checking current CPU usage via Actuator
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:8080/actuator/metrics/system.cpu.usage", Map.class);
System.out.println("CPU usage: " + response.getBody());

Analyze, draw conclusions, optimize — and your server will thank you!

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION