Merge pull request #14741 from jasontedor/return-of-the-cpu-percent
Add system CPU percent to OS stats
This commit is contained in:
commit
450aa7b3ce
|
@ -0,0 +1,20 @@
|
||||||
|
package org.elasticsearch.monitor;
|
||||||
|
|
||||||
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class Probes {
|
||||||
|
public static short getLoadAndScaleToPercent(Method method, OperatingSystemMXBean osMxBean) {
|
||||||
|
if (method != null) {
|
||||||
|
try {
|
||||||
|
double load = (double) method.invoke(osMxBean);
|
||||||
|
if (load >= 0) {
|
||||||
|
return (short) (load * 100);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.monitor.os;
|
package org.elasticsearch.monitor.os;
|
||||||
|
|
||||||
import org.apache.lucene.util.Constants;
|
import org.apache.lucene.util.Constants;
|
||||||
|
import org.elasticsearch.monitor.Probes;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
|
@ -34,6 +35,7 @@ public class OsProbe {
|
||||||
private static final Method getFreeSwapSpaceSize;
|
private static final Method getFreeSwapSpaceSize;
|
||||||
private static final Method getTotalSwapSpaceSize;
|
private static final Method getTotalSwapSpaceSize;
|
||||||
private static final Method getSystemLoadAverage;
|
private static final Method getSystemLoadAverage;
|
||||||
|
private static final Method getSystemCpuLoad;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
getFreePhysicalMemorySize = getMethod("getFreePhysicalMemorySize");
|
getFreePhysicalMemorySize = getMethod("getFreePhysicalMemorySize");
|
||||||
|
@ -41,6 +43,7 @@ public class OsProbe {
|
||||||
getFreeSwapSpaceSize = getMethod("getFreeSwapSpaceSize");
|
getFreeSwapSpaceSize = getMethod("getFreeSwapSpaceSize");
|
||||||
getTotalSwapSpaceSize = getMethod("getTotalSwapSpaceSize");
|
getTotalSwapSpaceSize = getMethod("getTotalSwapSpaceSize");
|
||||||
getSystemLoadAverage = getMethod("getSystemLoadAverage");
|
getSystemLoadAverage = getMethod("getSystemLoadAverage");
|
||||||
|
getSystemCpuLoad = getMethod("getSystemCpuLoad");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,6 +116,10 @@ public class OsProbe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public short getSystemCpuPercent() {
|
||||||
|
return Probes.getLoadAndScaleToPercent(getSystemCpuLoad, osMxBean);
|
||||||
|
}
|
||||||
|
|
||||||
private static class OsProbeHolder {
|
private static class OsProbeHolder {
|
||||||
private final static OsProbe INSTANCE = new OsProbe();
|
private final static OsProbe INSTANCE = new OsProbe();
|
||||||
}
|
}
|
||||||
|
@ -136,7 +143,9 @@ public class OsProbe {
|
||||||
public OsStats osStats() {
|
public OsStats osStats() {
|
||||||
OsStats stats = new OsStats();
|
OsStats stats = new OsStats();
|
||||||
stats.timestamp = System.currentTimeMillis();
|
stats.timestamp = System.currentTimeMillis();
|
||||||
stats.loadAverage = getSystemLoadAverage();
|
stats.cpu = new OsStats.Cpu();
|
||||||
|
stats.cpu.percent = getSystemCpuPercent();
|
||||||
|
stats.cpu.loadAverage = getSystemLoadAverage();
|
||||||
|
|
||||||
OsStats.Mem mem = new OsStats.Mem();
|
OsStats.Mem mem = new OsStats.Mem();
|
||||||
mem.total = getTotalPhysicalMemorySize();
|
mem.total = getTotalPhysicalMemorySize();
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
|
|
||||||
long timestamp;
|
long timestamp;
|
||||||
|
|
||||||
double loadAverage = -1;
|
Cpu cpu = null;
|
||||||
|
|
||||||
Mem mem = null;
|
Mem mem = null;
|
||||||
|
|
||||||
|
@ -49,10 +49,7 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getLoadAverage() {
|
public Cpu getCpu() { return cpu; }
|
||||||
return loadAverage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Mem getMem() {
|
public Mem getMem() {
|
||||||
return mem;
|
return mem;
|
||||||
|
@ -65,6 +62,8 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
static final class Fields {
|
static final class Fields {
|
||||||
static final XContentBuilderString OS = new XContentBuilderString("os");
|
static final XContentBuilderString OS = new XContentBuilderString("os");
|
||||||
static final XContentBuilderString TIMESTAMP = new XContentBuilderString("timestamp");
|
static final XContentBuilderString TIMESTAMP = new XContentBuilderString("timestamp");
|
||||||
|
static final XContentBuilderString CPU = new XContentBuilderString("cpu");
|
||||||
|
static final XContentBuilderString PERCENT = new XContentBuilderString("percent");
|
||||||
static final XContentBuilderString LOAD_AVERAGE = new XContentBuilderString("load_average");
|
static final XContentBuilderString LOAD_AVERAGE = new XContentBuilderString("load_average");
|
||||||
|
|
||||||
static final XContentBuilderString MEM = new XContentBuilderString("mem");
|
static final XContentBuilderString MEM = new XContentBuilderString("mem");
|
||||||
|
@ -85,7 +84,12 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
builder.startObject(Fields.OS);
|
builder.startObject(Fields.OS);
|
||||||
builder.field(Fields.TIMESTAMP, getTimestamp());
|
builder.field(Fields.TIMESTAMP, getTimestamp());
|
||||||
builder.field(Fields.LOAD_AVERAGE, getLoadAverage());
|
if (cpu != null) {
|
||||||
|
builder.startObject(Fields.CPU);
|
||||||
|
builder.field(Fields.PERCENT, cpu.getPercent());
|
||||||
|
builder.field(Fields.LOAD_AVERAGE, cpu.getLoadAverage());
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
if (mem != null) {
|
if (mem != null) {
|
||||||
builder.startObject(Fields.MEM);
|
builder.startObject(Fields.MEM);
|
||||||
|
@ -120,7 +124,7 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
@Override
|
@Override
|
||||||
public void readFrom(StreamInput in) throws IOException {
|
public void readFrom(StreamInput in) throws IOException {
|
||||||
timestamp = in.readVLong();
|
timestamp = in.readVLong();
|
||||||
loadAverage = in.readDouble();
|
cpu = in.readOptionalStreamable(Cpu::new);
|
||||||
if (in.readBoolean()) {
|
if (in.readBoolean()) {
|
||||||
mem = Mem.readMem(in);
|
mem = Mem.readMem(in);
|
||||||
}
|
}
|
||||||
|
@ -132,7 +136,7 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
out.writeVLong(timestamp);
|
out.writeVLong(timestamp);
|
||||||
out.writeDouble(loadAverage);
|
out.writeOptionalStreamable(cpu);
|
||||||
if (mem == null) {
|
if (mem == null) {
|
||||||
out.writeBoolean(false);
|
out.writeBoolean(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -147,6 +151,39 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Cpu implements Streamable {
|
||||||
|
short percent = -1;
|
||||||
|
double loadAverage = -1;
|
||||||
|
|
||||||
|
Cpu() {}
|
||||||
|
|
||||||
|
public static Cpu readCpu(StreamInput in) throws IOException {
|
||||||
|
Cpu cpu = new Cpu();
|
||||||
|
cpu.readFrom(in);
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFrom(StreamInput in) throws IOException {
|
||||||
|
percent = in.readShort();
|
||||||
|
loadAverage = in.readDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeShort(percent);
|
||||||
|
out.writeDouble(loadAverage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getPercent() {
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLoadAverage() {
|
||||||
|
return loadAverage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Swap implements Streamable {
|
public static class Swap implements Streamable {
|
||||||
|
|
||||||
long total = -1;
|
long total = -1;
|
||||||
|
@ -230,5 +267,4 @@ public class OsStats implements Streamable, ToXContent {
|
||||||
private static short calculatePercentage(long used, long max) {
|
private static short calculatePercentage(long used, long max) {
|
||||||
return max <= 0 ? 0 : (short) (Math.round((100d * used) / max));
|
return max <= 0 ? 0 : (short) (Math.round((100d * used) / max));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.monitor.process;
|
package org.elasticsearch.monitor.process;
|
||||||
|
|
||||||
import org.elasticsearch.bootstrap.BootstrapInfo;
|
import org.elasticsearch.bootstrap.BootstrapInfo;
|
||||||
|
import org.elasticsearch.monitor.Probes;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
|
@ -88,17 +89,7 @@ public class ProcessProbe {
|
||||||
* Returns the process CPU usage in percent
|
* Returns the process CPU usage in percent
|
||||||
*/
|
*/
|
||||||
public short getProcessCpuPercent() {
|
public short getProcessCpuPercent() {
|
||||||
if (getProcessCpuLoad != null) {
|
return Probes.getLoadAndScaleToPercent(getProcessCpuLoad, osMxBean);
|
||||||
try {
|
|
||||||
double load = (double) getProcessCpuLoad.invoke(osMxBean);
|
|
||||||
if (load >= 0) {
|
|
||||||
return (short) (load * 100);
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -130,6 +130,7 @@ public class RestNodesAction extends AbstractCatAction {
|
||||||
table.addCell("file_desc.percent", "default:false;alias:fdp,fileDescriptorPercent;text-align:right;desc:used file descriptor ratio");
|
table.addCell("file_desc.percent", "default:false;alias:fdp,fileDescriptorPercent;text-align:right;desc:used file descriptor ratio");
|
||||||
table.addCell("file_desc.max", "default:false;alias:fdm,fileDescriptorMax;text-align:right;desc:max file descriptors");
|
table.addCell("file_desc.max", "default:false;alias:fdm,fileDescriptorMax;text-align:right;desc:max file descriptors");
|
||||||
|
|
||||||
|
table.addCell("cpu", "alias:cpu;text-align:right;desc:recent cpu usage");
|
||||||
table.addCell("load", "alias:l;text-align:right;desc:most recent load avg");
|
table.addCell("load", "alias:l;text-align:right;desc:most recent load avg");
|
||||||
table.addCell("uptime", "default:false;alias:u;text-align:right;desc:node uptime");
|
table.addCell("uptime", "default:false;alias:u;text-align:right;desc:node uptime");
|
||||||
table.addCell("node.role", "alias:r,role,dc,nodeRole;desc:d:data node, c:client node");
|
table.addCell("node.role", "alias:r,role,dc,nodeRole;desc:d:data node, c:client node");
|
||||||
|
@ -258,7 +259,8 @@ public class RestNodesAction extends AbstractCatAction {
|
||||||
table.addCell(processStats == null ? null : calculatePercentage(processStats.getOpenFileDescriptors(), processStats.getMaxFileDescriptors()));
|
table.addCell(processStats == null ? null : calculatePercentage(processStats.getOpenFileDescriptors(), processStats.getMaxFileDescriptors()));
|
||||||
table.addCell(processStats == null ? null : processStats.getMaxFileDescriptors());
|
table.addCell(processStats == null ? null : processStats.getMaxFileDescriptors());
|
||||||
|
|
||||||
table.addCell(osStats == null ? null : String.format(Locale.ROOT, "%.2f", osStats.getLoadAverage()));
|
table.addCell(osStats == null ? null : Short.toString(osStats.getCpu().getPercent()));
|
||||||
|
table.addCell(osStats == null ? null : String.format(Locale.ROOT, "%.2f", osStats.getCpu().getLoadAverage()));
|
||||||
table.addCell(jvmStats == null ? null : jvmStats.getUptime());
|
table.addCell(jvmStats == null ? null : jvmStats.getUptime());
|
||||||
table.addCell(node.clientNode() ? "c" : node.dataNode() ? "d" : "-");
|
table.addCell(node.clientNode() ? "c" : node.dataNode() ? "d" : "-");
|
||||||
table.addCell(masterId == null ? "x" : masterId.equals(node.id()) ? "*" : node.masterNode() ? "m" : "-");
|
table.addCell(masterId == null ? "x" : masterId.equals(node.id()) ? "*" : node.masterNode() ? "m" : "-");
|
||||||
|
|
|
@ -41,12 +41,10 @@ public class OsProbeBenchmark {
|
||||||
probe.getTotalSwapSpaceSize();
|
probe.getTotalSwapSpaceSize();
|
||||||
probe.getFreeSwapSpaceSize();
|
probe.getFreeSwapSpaceSize();
|
||||||
probe.getSystemLoadAverage();
|
probe.getSystemLoadAverage();
|
||||||
|
probe.getSystemCpuPercent();
|
||||||
}
|
}
|
||||||
logger.info("--> warmed up");
|
logger.info("--> warmed up");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger.info("--> testing 'getTotalPhysicalMemorySize' method...");
|
logger.info("--> testing 'getTotalPhysicalMemorySize' method...");
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
for (int i = 0; i < ITERATIONS; i++) {
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
@ -86,5 +84,13 @@ public class OsProbeBenchmark {
|
||||||
}
|
}
|
||||||
elapsed = System.currentTimeMillis() - start;
|
elapsed = System.currentTimeMillis() - start;
|
||||||
logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
|
logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
|
||||||
|
|
||||||
|
logger.info("--> testing 'getSystemCpuPercent' method...");
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
probe.getSystemCpuPercent();
|
||||||
|
}
|
||||||
|
elapsed = System.currentTimeMillis() - start;
|
||||||
|
logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,7 @@ package org.elasticsearch.monitor.os;
|
||||||
import org.apache.lucene.util.Constants;
|
import org.apache.lucene.util.Constants;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.allOf;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.anyOf;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
|
||||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
|
||||||
import static org.hamcrest.Matchers.lessThan;
|
|
||||||
import static org.hamcrest.Matchers.lessThanOrEqualTo;
|
|
||||||
|
|
||||||
public class OsProbeTests extends ESTestCase {
|
public class OsProbeTests extends ESTestCase {
|
||||||
OsProbe probe = OsProbe.getInstance();
|
OsProbe probe = OsProbe.getInstance();
|
||||||
|
@ -47,12 +41,13 @@ public class OsProbeTests extends ESTestCase {
|
||||||
OsStats stats = probe.osStats();
|
OsStats stats = probe.osStats();
|
||||||
assertNotNull(stats);
|
assertNotNull(stats);
|
||||||
assertThat(stats.getTimestamp(), greaterThan(0L));
|
assertThat(stats.getTimestamp(), greaterThan(0L));
|
||||||
|
assertThat(stats.getCpu().getPercent(), anyOf(equalTo((short) -1), is(both(greaterThanOrEqualTo((short) 0)).and(lessThanOrEqualTo((short) 100)))));
|
||||||
if (Constants.WINDOWS) {
|
if (Constants.WINDOWS) {
|
||||||
// Load average is always -1 on Windows platforms
|
// Load average is always -1 on Windows platforms
|
||||||
assertThat(stats.getLoadAverage(), equalTo((double) -1));
|
assertThat(stats.getCpu().getLoadAverage(), equalTo((double) -1));
|
||||||
} else {
|
} else {
|
||||||
// Load average can be negative if not available or not computed yet, otherwise it should be >= 0
|
// Load average can be negative if not available or not computed yet, otherwise it should be >= 0
|
||||||
assertThat(stats.getLoadAverage(), anyOf(lessThan((double) 0), greaterThanOrEqualTo((double) 0)));
|
assertThat(stats.getCpu().getLoadAverage(), anyOf(lessThan((double) 0), greaterThanOrEqualTo((double) 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(stats.getMem());
|
assertNotNull(stats.getMem());
|
||||||
|
|
|
@ -128,7 +128,10 @@ the operating system:
|
||||||
`os.timestamp`::
|
`os.timestamp`::
|
||||||
Last time the operating system statistics have been refreshed
|
Last time the operating system statistics have been refreshed
|
||||||
|
|
||||||
`os.load_average`::
|
`os.cpu.percent`::
|
||||||
|
Recent CPU usage for the whole system, or -1 if not supported
|
||||||
|
|
||||||
|
`os.cpu.load_average`::
|
||||||
System load average for the last minute, or -1 if not supported
|
System load average for the last minute, or -1 if not supported
|
||||||
|
|
||||||
`os.mem.total_in_bytes`::
|
`os.mem.total_in_bytes`::
|
||||||
|
|
|
@ -428,3 +428,15 @@ controls the backing queue for the thread pool and modifying this is an expert s
|
||||||
and high risk of being misused. The ability to change the thread pool type for any thread pool has been removed; do note
|
and high risk of being misused. The ability to change the thread pool type for any thread pool has been removed; do note
|
||||||
that it is still possible to adjust relevant thread pool parameters for each of the thread pools (e.g., depending on
|
that it is still possible to adjust relevant thread pool parameters for each of the thread pools (e.g., depending on
|
||||||
the thread pool type, `keep_alive`, `queue_size`, etc.).
|
the thread pool type, `keep_alive`, `queue_size`, etc.).
|
||||||
|
|
||||||
|
=== Adding system CPU percent to OS stats
|
||||||
|
|
||||||
|
The recent CPU usage (as a percent) has been added to the OS stats reported under the node stats API and the cat nodes
|
||||||
|
API. The breaking change here is that there is a new object in the "os" object in the node stats response. This object
|
||||||
|
is called "cpu" and includes "percent" and "load_average" as fields. This moves the "load_average" field that was
|
||||||
|
previously a top-level field in the "os" object to the "cpu" object. Additionally, the "cpu" field in the cat nodes API
|
||||||
|
response is output by default.
|
||||||
|
|
||||||
|
Finally, the API for org.elasticsearch.monitor.os.OsStats has changed. The `getLoadAverage` method has been removed. The
|
||||||
|
value for this can now be obtained from `OsStats.Cpu#getLoadAverage`. Additionally, the recent CPU usage can be obtained
|
||||||
|
from `OsStats.Cpu#getPercent`.
|
||||||
|
|
Loading…
Reference in New Issue