9

I would like to know is there a way to get the CPU Usage metrics with Spring Boot Actuator? Im able to see other metrics with /metrics and /health endpoints but not getting the CPU Usage. I want to avoid writing an extra class just to see the CPU Usage. Any idea? Thanks

1
  • The /metrics endpoint shows a load average of the machine. Is this what you are looking for ? A idle computer has a load average of 0. Each running process using or waiting for CPU resources adds 1 to the load average. Commented Dec 20, 2016 at 6:39

3 Answers 3

11

Just checked and I found this actuator... /actuator/metrics/process.cpu.usage

It outputs the following:

{
    name: "process.cpu.usage",
    description: "The "recent cpu usage" for the Java Virtual Machine process",
    baseUnit: null,
    measurements: [
        {
            statistic: "VALUE",
            value: 0.0001742149747252696
        }
    ],
    availableTags: [ ]
}

Currently using Spring Boot version 2.2.2.RELEASE.

Sign up to request clarification or add additional context in comments.

Comments

5

Spring Boot 2 actuator solution (building on @diginoise's code to measure CPU load), registering a Gauge with a function to measure the value when requested (no need to start Threads or schedule timers):

@Component
public class CpuMetrics {

    private final static String METRICS_NAME = "process.cpu.load";

    @Autowired
    private MeterRegistry meterRegistry;

    @PostConstruct
    public void init() {
        Gauge.builder(METRICS_NAME, this, CpuMetrics::getProcessCpuLoad)
            .baseUnit("%")
            .description("CPU Load")
            .register(meterRegistry);
    }

    public Double getProcessCpuLoad() {
        try {
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
            AttributeList list = mbs.getAttributes(name, new String[]{"ProcessCpuLoad"});

            return Optional.ofNullable(list)
                    .map(l -> l.isEmpty() ? null : l)
                    .map(List::iterator)
                    .map(Iterator::next)
                    .map(Attribute.class::cast)
                    .map(Attribute::getValue)
                    .map(Double.class::cast)
                    .orElse(null);

        } catch (Exception ex) {
            return null;
        }
    }
}

The CPU metrics will then be available at /actuator/metrics/process.cpu.load:

{
  "name": "process.cpu.load",
  "description": "CPU Load",
  "baseUnit": "%",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 0.09767676212004521
    }
  ],
  "availableTags": []
}

3 Comments

Could you please inform what this number "value": 0.09767676212004521 represents?
@Manu 1 would be 100%, so the value means 9.76..%
can we get "jvm.memory.used" in similar way ?
1

Unfortunately there isn't a CPU metric available via Spring Boot Actuator.
Fortunately you could write your own.

Just create a measuring bean which fulfills the following:

  1. It has access to GaugeService as it will be tracking one value.

    @Autowired
    private GaugeService gaugeService;
    
  2. Creates a thread which calls routine to measure process' CPU load:

    @PostConstruct
    public void startMeasuring() {
        new Thread() {
            @Override
            public void run() {
                gaugeService.submit("process.cpu.load", getProcessCpuLoad());
                Thread.sleep(2000);   //measure every 2sec.
            }
        }.start();
    }
    
  3. Has a routine which gets CPU load for your process using MxBeans:

    public static double getProcessCpuLoad() throws Exception {
        MBeanServer mbs    = ManagementFactory.getPlatformMBeanServer();
        ObjectName name    = ObjectName.getInstance("java.lang:type=OperatingSystem");
        AttributeList list = mbs.getAttributes(name, new String[]{ "ProcessCpuLoad" });
    
        if (list.isEmpty())     return Double.NaN;
    
        Attribute att = (Attribute)list.get(0);
        Double value  = (Double)att.getValue();
    
        // usually takes a couple of seconds before we get real values
        if (value == -1.0)      return Double.NaN;
        // returns a percentage value with 1 decimal point precision
        return ((int)(value * 1000) / 10.0);
    }
    

You could also extract the system wide CPU load using this method.

Hope this helps.

2 Comments

how do we get "jvm.memory.used" in similar way ? I used : AttributeList list = mbs.getAttributes(name, new String[]{ "JvmMemoryUsed" }); but it's not working
@pujankc There are many answers here how to check memory used via JMX: stackoverflow.com/questions/1759831/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.