diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsNodes.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsNodes.java index 7a512fd75ea8f..d19f341f8323a 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsNodes.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsNodes.java @@ -430,11 +430,11 @@ public void addNodeStats(NodeStats nodeStats) { return; } count++; - if (nodeStats.getProcess().cpu() != null) { + if (nodeStats.getProcess().getCpu() != null) { // with no sigar, this may not be available - cpuPercent += nodeStats.getProcess().cpu().getPercent(); + cpuPercent += nodeStats.getProcess().getCpu().getPercent(); } - long fd = nodeStats.getProcess().openFileDescriptors(); + long fd = nodeStats.getProcess().getOpenFileDescriptors(); if (fd > 0) { // fd can be -1 if not supported on platform totalOpenFileDescriptors += fd; diff --git a/core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java b/core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java index 006d55edaeeb0..d084e6315e8ae 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java @@ -40,7 +40,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.monitor.jvm.JvmInfo; -import org.elasticsearch.monitor.process.JmxProcessProbe; +import org.elasticsearch.monitor.process.ProcessProbe; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; import org.elasticsearch.node.internal.InternalSettingsPreparer; @@ -143,14 +143,22 @@ public boolean handle(int code) { StringHelper.randomId(); } + static void initializeProbes() { + // Force probes to be loaded + ProcessProbe.getInstance(); + } + public static boolean isMemoryLocked() { return Natives.isMemoryLocked(); } private void setup(boolean addShutdownHook, Settings settings, Environment environment) throws Exception { - initializeNatives(settings.getAsBoolean("bootstrap.mlockall", false), + initializeNatives(settings.getAsBoolean("bootstrap.mlockall", false), settings.getAsBoolean("bootstrap.ctrlhandler", true)); + // initialize probes before the security manager is installed + initializeProbes(); + if (addShutdownHook) { Runtime.getRuntime().addShutdownHook(new Thread() { @Override @@ -167,7 +175,7 @@ public void run() { // look for jar hell JarHell.checkJarHell(); - + // install SM after natives, shutdown hooks, etc. setupSecurity(settings, environment); @@ -262,7 +270,7 @@ public static void main(String[] args) { if (System.getProperty("es.max-open-files", "false").equals("true")) { ESLogger logger = Loggers.getLogger(Bootstrap.class); - logger.info("max_open_files [{}]", JmxProcessProbe.getMaxFileDescriptorCount()); + logger.info("max_open_files [{}]", ProcessProbe.getInstance().getMaxFileDescriptorCount()); } // warn if running using the client VM diff --git a/core/src/main/java/org/elasticsearch/monitor/MonitorModule.java b/core/src/main/java/org/elasticsearch/monitor/MonitorModule.java index db876d9189325..2b08460210fc7 100644 --- a/core/src/main/java/org/elasticsearch/monitor/MonitorModule.java +++ b/core/src/main/java/org/elasticsearch/monitor/MonitorModule.java @@ -28,7 +28,6 @@ import org.elasticsearch.monitor.os.JmxOsProbe; import org.elasticsearch.monitor.os.OsProbe; import org.elasticsearch.monitor.os.OsService; -import org.elasticsearch.monitor.process.JmxProcessProbe; import org.elasticsearch.monitor.process.ProcessProbe; import org.elasticsearch.monitor.process.ProcessService; @@ -50,7 +49,7 @@ public MonitorModule(Settings settings) { @Override protected void configure() { // bind default implementations - bind(ProcessProbe.class).to(JmxProcessProbe.class).asEagerSingleton(); + bind(ProcessProbe.class).toInstance(ProcessProbe.getInstance()); bind(OsProbe.class).to(JmxOsProbe.class).asEagerSingleton(); bind(FsProbe.class).asEagerSingleton(); diff --git a/core/src/main/java/org/elasticsearch/monitor/process/JmxProcessProbe.java b/core/src/main/java/org/elasticsearch/monitor/process/JmxProcessProbe.java deleted file mode 100644 index f91d7823938d5..0000000000000 --- a/core/src/main/java/org/elasticsearch/monitor/process/JmxProcessProbe.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.monitor.process; - -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; - -import java.lang.management.ManagementFactory; -import java.lang.management.OperatingSystemMXBean; -import java.lang.reflect.Method; - -import static org.elasticsearch.monitor.jvm.JvmInfo.jvmInfo; - -/** - * - */ -public class JmxProcessProbe extends AbstractComponent implements ProcessProbe { - - private static final OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); - - private static final Method getMaxFileDescriptorCountField; - private static final Method getOpenFileDescriptorCountField; - - static { - Method method = null; - try { - method = osMxBean.getClass().getDeclaredMethod("getMaxFileDescriptorCount"); - method.setAccessible(true); - } catch (Exception e) { - // not available - } - getMaxFileDescriptorCountField = method; - - method = null; - try { - method = osMxBean.getClass().getDeclaredMethod("getOpenFileDescriptorCount"); - method.setAccessible(true); - } catch (Exception e) { - // not available - } - getOpenFileDescriptorCountField = method; - } - - public static long getMaxFileDescriptorCount() { - if (getMaxFileDescriptorCountField == null) { - return -1; - } - try { - return (Long) getMaxFileDescriptorCountField.invoke(osMxBean); - } catch (Exception e) { - return -1; - } - } - - public static long getOpenFileDescriptorCount() { - if (getOpenFileDescriptorCountField == null) { - return -1; - } - try { - return (Long) getOpenFileDescriptorCountField.invoke(osMxBean); - } catch (Exception e) { - return -1; - } - } - - @Inject - public JmxProcessProbe(Settings settings) { - super(settings); - } - - @Override - public ProcessInfo processInfo() { - return new ProcessInfo(jvmInfo().pid(), getMaxFileDescriptorCount()); - } - - @Override - public ProcessStats processStats() { - ProcessStats stats = new ProcessStats(); - stats.timestamp = System.currentTimeMillis(); - stats.openFileDescriptors = getOpenFileDescriptorCount(); - return stats; - } -} diff --git a/core/src/main/java/org/elasticsearch/monitor/process/ProcessInfo.java b/core/src/main/java/org/elasticsearch/monitor/process/ProcessInfo.java index 8fd16d528fb13..7d1ea03b085fd 100644 --- a/core/src/main/java/org/elasticsearch/monitor/process/ProcessInfo.java +++ b/core/src/main/java/org/elasticsearch/monitor/process/ProcessInfo.java @@ -19,7 +19,6 @@ package org.elasticsearch.monitor.process; -import org.elasticsearch.bootstrap.Bootstrap; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Streamable; @@ -29,27 +28,20 @@ import java.io.IOException; -/** - * - */ public class ProcessInfo implements Streamable, ToXContent { long refreshInterval; private long id; - private long maxFileDescriptors = -1; - private boolean mlockall; ProcessInfo() { - } - public ProcessInfo(long id, long maxFileDescriptors) { + public ProcessInfo(long id, boolean mlockall) { this.id = id; - this.maxFileDescriptors = maxFileDescriptors; - this.mlockall = Bootstrap.isMemoryLocked(); + this.mlockall = mlockall; } public long refreshInterval() { @@ -60,30 +52,11 @@ public long getRefreshInterval() { return this.refreshInterval; } - /** - * The process id. - */ - public long id() { - return this.id; - } - /** * The process id. */ public long getId() { - return id(); - } - - public long maxFileDescriptors() { - return this.maxFileDescriptors; - } - - public long getMaxFileDescriptors() { - return maxFileDescriptors; - } - - public boolean mlockAll() { - return mlockall; + return id; } public boolean isMlockall() { @@ -95,7 +68,6 @@ static final class Fields { static final XContentBuilderString REFRESH_INTERVAL = new XContentBuilderString("refresh_interval"); static final XContentBuilderString REFRESH_INTERVAL_IN_MILLIS = new XContentBuilderString("refresh_interval_in_millis"); static final XContentBuilderString ID = new XContentBuilderString("id"); - static final XContentBuilderString MAX_FILE_DESCRIPTORS = new XContentBuilderString("max_file_descriptors"); static final XContentBuilderString MLOCKALL = new XContentBuilderString("mlockall"); } @@ -104,7 +76,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(Fields.PROCESS); builder.timeValueField(Fields.REFRESH_INTERVAL_IN_MILLIS, Fields.REFRESH_INTERVAL, refreshInterval); builder.field(Fields.ID, id); - builder.field(Fields.MAX_FILE_DESCRIPTORS, maxFileDescriptors); builder.field(Fields.MLOCKALL, mlockall); builder.endObject(); return builder; @@ -120,7 +91,6 @@ public static ProcessInfo readProcessInfo(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException { refreshInterval = in.readLong(); id = in.readLong(); - maxFileDescriptors = in.readLong(); mlockall = in.readBoolean(); } @@ -128,7 +98,6 @@ public void readFrom(StreamInput in) throws IOException { public void writeTo(StreamOutput out) throws IOException { out.writeLong(refreshInterval); out.writeLong(id); - out.writeLong(maxFileDescriptors); out.writeBoolean(mlockall); } } diff --git a/core/src/main/java/org/elasticsearch/monitor/process/ProcessProbe.java b/core/src/main/java/org/elasticsearch/monitor/process/ProcessProbe.java index 89d56ed8131fd..b1d1c7f67970c 100644 --- a/core/src/main/java/org/elasticsearch/monitor/process/ProcessProbe.java +++ b/core/src/main/java/org/elasticsearch/monitor/process/ProcessProbe.java @@ -19,12 +19,156 @@ package org.elasticsearch.monitor.process; -/** - * - */ -public interface ProcessProbe { +import org.elasticsearch.bootstrap.Bootstrap; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.lang.reflect.Method; + +import static org.elasticsearch.monitor.jvm.JvmInfo.jvmInfo; + +public class ProcessProbe { + + private static final OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); + + private static final Method getMaxFileDescriptorCountField; + private static final Method getOpenFileDescriptorCountField; + private static final Method getProcessCpuLoad; + private static final Method getProcessCpuTime; + private static final Method getCommittedVirtualMemorySize; + + static { + getMaxFileDescriptorCountField = getMethod("getMaxFileDescriptorCount"); + getOpenFileDescriptorCountField = getMethod("getOpenFileDescriptorCount"); + getProcessCpuLoad = getMethod("getProcessCpuLoad"); + getProcessCpuTime = getMethod("getProcessCpuTime"); + getCommittedVirtualMemorySize = getMethod("getCommittedVirtualMemorySize"); + } + + private static class ProcessProbeHolder { + private final static ProcessProbe INSTANCE = new ProcessProbe(); + } + + public static ProcessProbe getInstance() { + return ProcessProbeHolder.INSTANCE; + } + + private ProcessProbe() { + } + + /** + * Returns the maximum number of file descriptors allowed on the system, or -1 if not supported. + */ + public long getMaxFileDescriptorCount() { + if (getMaxFileDescriptorCountField == null) { + return -1; + } + try { + return (Long) getMaxFileDescriptorCountField.invoke(osMxBean); + } catch (Throwable t) { + return -1; + } + } + + /** + * Returns the number of opened file descriptors associated with the current process, or -1 if not supported. + */ + public long getOpenFileDescriptorCount() { + if (getOpenFileDescriptorCountField == null) { + return -1; + } + try { + return (Long) getOpenFileDescriptorCountField.invoke(osMxBean); + } catch (Throwable t) { + return -1; + } + } + + /** + * Returns the process CPU usage in percent + */ + public short getProcessCpuPercent() { + if (getProcessCpuLoad != null) { + try { + double load = (double) getProcessCpuLoad.invoke(osMxBean); + if (load >= 0) { + return (short) (load * 100); + } + } catch (Throwable t) { + return -1; + } + } + return -1; + } + + /** + * Returns the CPU time (in milliseconds) used by the process on which the Java virtual machine is running, or -1 if not supported. + */ + public long getProcessCpuTotalTime() { + if (getProcessCpuTime != null) { + try { + long time = (long) getProcessCpuTime.invoke(osMxBean); + if (time >= 0) { + return (time / 1_000_000L); + } + } catch (Throwable t) { + return -1; + } + } + return -1; + } + + /** + * Returns the size (in bytes) of virtual memory that is guaranteed to be available to the running process + */ + public long getTotalVirtualMemorySize() { + if (getCommittedVirtualMemorySize != null) { + try { + long virtual = (long) getCommittedVirtualMemorySize.invoke(osMxBean); + if (virtual >= 0) { + return virtual; + } + } catch (Throwable t) { + return -1; + } + } + return -1; + } + + public ProcessInfo processInfo() { + return new ProcessInfo(jvmInfo().pid(), Bootstrap.isMemoryLocked()); + } + + public ProcessStats processStats() { + ProcessStats stats = new ProcessStats(); + stats.timestamp = System.currentTimeMillis(); + stats.openFileDescriptors = getOpenFileDescriptorCount(); + stats.maxFileDescriptors = getMaxFileDescriptorCount(); + + ProcessStats.Cpu cpu = new ProcessStats.Cpu(); + cpu.percent = getProcessCpuPercent(); + cpu.total = getProcessCpuTotalTime(); + stats.cpu = cpu; + + ProcessStats.Mem mem = new ProcessStats.Mem(); + mem.totalVirtual = getTotalVirtualMemorySize(); + stats.mem = mem; - ProcessInfo processInfo(); + return stats; + } - ProcessStats processStats(); + /** + * Returns a given method of the OperatingSystemMXBean, + * or null if the method is not found or unavailable. + */ + private static Method getMethod(String methodName) { + try { + Method method = osMxBean.getClass().getDeclaredMethod(methodName); + method.setAccessible(true); + return method; + } catch (Throwable t) { + // not available + } + return null; + } } diff --git a/core/src/main/java/org/elasticsearch/monitor/process/ProcessStats.java b/core/src/main/java/org/elasticsearch/monitor/process/ProcessStats.java index 9777864a89ae2..44ef7c7a81602 100644 --- a/core/src/main/java/org/elasticsearch/monitor/process/ProcessStats.java +++ b/core/src/main/java/org/elasticsearch/monitor/process/ProcessStats.java @@ -30,14 +30,12 @@ import java.io.IOException; -/** - * - */ public class ProcessStats implements Streamable, ToXContent { long timestamp = -1; - long openFileDescriptors; + long openFileDescriptors = -1; + long maxFileDescriptors = -1; Cpu cpu = null; @@ -46,57 +44,38 @@ public class ProcessStats implements Streamable, ToXContent { ProcessStats() { } - public long timestamp() { - return this.timestamp; - } - public long getTimestamp() { - return timestamp(); - } - - public long openFileDescriptors() { - return this.openFileDescriptors; + return timestamp; } public long getOpenFileDescriptors() { return openFileDescriptors; } - public Cpu cpu() { - return cpu; + public long getMaxFileDescriptors() { + return maxFileDescriptors; } public Cpu getCpu() { - return cpu(); - } - - public Mem mem() { - return mem; + return cpu; } public Mem getMem() { - return mem(); + return mem; } static final class Fields { static final XContentBuilderString PROCESS = new XContentBuilderString("process"); static final XContentBuilderString TIMESTAMP = new XContentBuilderString("timestamp"); static final XContentBuilderString OPEN_FILE_DESCRIPTORS = new XContentBuilderString("open_file_descriptors"); + static final XContentBuilderString MAX_FILE_DESCRIPTORS = new XContentBuilderString("max_file_descriptors"); static final XContentBuilderString CPU = new XContentBuilderString("cpu"); static final XContentBuilderString PERCENT = new XContentBuilderString("percent"); - static final XContentBuilderString SYS = new XContentBuilderString("sys"); - static final XContentBuilderString SYS_IN_MILLIS = new XContentBuilderString("sys_in_millis"); - static final XContentBuilderString USER = new XContentBuilderString("user"); - static final XContentBuilderString USER_IN_MILLIS = new XContentBuilderString("user_in_millis"); static final XContentBuilderString TOTAL = new XContentBuilderString("total"); static final XContentBuilderString TOTAL_IN_MILLIS = new XContentBuilderString("total_in_millis"); static final XContentBuilderString MEM = new XContentBuilderString("mem"); - static final XContentBuilderString RESIDENT = new XContentBuilderString("resident"); - static final XContentBuilderString RESIDENT_IN_BYTES = new XContentBuilderString("resident_in_bytes"); - static final XContentBuilderString SHARE = new XContentBuilderString("share"); - static final XContentBuilderString SHARE_IN_BYTES = new XContentBuilderString("share_in_bytes"); static final XContentBuilderString TOTAL_VIRTUAL = new XContentBuilderString("total_virtual"); static final XContentBuilderString TOTAL_VIRTUAL_IN_BYTES = new XContentBuilderString("total_virtual_in_bytes"); } @@ -106,18 +85,15 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(Fields.PROCESS); builder.field(Fields.TIMESTAMP, timestamp); builder.field(Fields.OPEN_FILE_DESCRIPTORS, openFileDescriptors); + builder.field(Fields.MAX_FILE_DESCRIPTORS, maxFileDescriptors); if (cpu != null) { builder.startObject(Fields.CPU); - builder.field(Fields.PERCENT, cpu.percent()); - builder.timeValueField(Fields.SYS_IN_MILLIS, Fields.SYS, cpu.sys); - builder.timeValueField(Fields.USER_IN_MILLIS, Fields.USER, cpu.user); + builder.field(Fields.PERCENT, cpu.percent); builder.timeValueField(Fields.TOTAL_IN_MILLIS, Fields.TOTAL, cpu.total); builder.endObject(); } if (mem != null) { builder.startObject(Fields.MEM); - builder.byteSizeField(Fields.RESIDENT_IN_BYTES, Fields.RESIDENT, mem.resident); - builder.byteSizeField(Fields.SHARE_IN_BYTES, Fields.SHARE, mem.share); builder.byteSizeField(Fields.TOTAL_VIRTUAL_IN_BYTES, Fields.TOTAL_VIRTUAL, mem.totalVirtual); builder.endObject(); } @@ -135,6 +111,7 @@ public static ProcessStats readProcessStats(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException { timestamp = in.readVLong(); openFileDescriptors = in.readLong(); + maxFileDescriptors = in.readLong(); if (in.readBoolean()) { cpu = Cpu.readCpu(in); } @@ -147,6 +124,7 @@ public void readFrom(StreamInput in) throws IOException { public void writeTo(StreamOutput out) throws IOException { out.writeVLong(timestamp); out.writeLong(openFileDescriptors); + out.writeLong(maxFileDescriptors); if (cpu == null) { out.writeBoolean(false); } else { @@ -164,8 +142,6 @@ public void writeTo(StreamOutput out) throws IOException { public static class Mem implements Streamable { long totalVirtual = -1; - long resident = -1; - long share = -1; Mem() { } @@ -179,47 +155,21 @@ public static Mem readMem(StreamInput in) throws IOException { @Override public void readFrom(StreamInput in) throws IOException { totalVirtual = in.readLong(); - resident = in.readLong(); - share = in.readLong(); } @Override public void writeTo(StreamOutput out) throws IOException { out.writeLong(totalVirtual); - out.writeLong(resident); - out.writeLong(share); - } - - public ByteSizeValue totalVirtual() { - return new ByteSizeValue(totalVirtual); } public ByteSizeValue getTotalVirtual() { - return totalVirtual(); - } - - public ByteSizeValue resident() { - return new ByteSizeValue(resident); - } - - public ByteSizeValue getResident() { - return resident(); - } - - public ByteSizeValue share() { - return new ByteSizeValue(share); - } - - public ByteSizeValue getShare() { - return share(); + return new ByteSizeValue(totalVirtual); } } public static class Cpu implements Streamable { short percent = -1; - long sys = -1; - long user = -1; long total = -1; Cpu() { @@ -235,90 +185,31 @@ public static Cpu readCpu(StreamInput in) throws IOException { @Override public void readFrom(StreamInput in) throws IOException { percent = in.readShort(); - sys = in.readLong(); - user = in.readLong(); total = in.readLong(); } @Override public void writeTo(StreamOutput out) throws IOException { out.writeShort(percent); - out.writeLong(sys); - out.writeLong(user); out.writeLong(total); } /** * Get the Process cpu usage. - *
- *Supported Platforms: All. - */ - public short percent() { - return percent; - } - - /** - * Get the Process cpu usage. - *
+ **
Supported Platforms: All. */ public short getPercent() { - return percent(); - } - - /** - * Get the Process cpu kernel time. - *
- *Supported Platforms: All. - */ - public TimeValue sys() { - return new TimeValue(sys); - } - - /** - * Get the Process cpu kernel time. - *
- *Supported Platforms: All. - */ - public TimeValue getSys() { - return sys(); - } - - /** - * Get the Process cpu user time. - *
- *Supported Platforms: All. - */ - public TimeValue user() { - return new TimeValue(user); - } - - /** - * Get the Process cpu time (sum of User and Sys). - *
- * Supported Platforms: All. - */ - public TimeValue total() { - return new TimeValue(total); + return percent; } /** * Get the Process cpu time (sum of User and Sys). - * + ** Supported Platforms: All. */ public TimeValue getTotal() { - return total(); - } - - /** - * Get the Process cpu user time. - *
- *Supported Platforms: All.
- */
- public TimeValue getUser() {
- return user();
+ return new TimeValue(total);
}
-
}
}
diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java
index 87fc5378fd14c..2e2e09c8e30dc 100644
--- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java
+++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java
@@ -53,7 +53,6 @@
import org.elasticsearch.monitor.jvm.JvmStats;
import org.elasticsearch.monitor.os.OsInfo;
import org.elasticsearch.monitor.os.OsStats;
-import org.elasticsearch.monitor.process.ProcessInfo;
import org.elasticsearch.monitor.process.ProcessStats;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestActionListener;
@@ -221,7 +220,6 @@ private Table buildTable(RestRequest req, ClusterStateResponse state, NodesInfoR
JvmInfo jvmInfo = info == null ? null : info.getJvm();
OsInfo osInfo = info == null ? null : info.getOs();
- ProcessInfo processInfo = info == null ? null : info.getProcess();
JvmStats jvmStats = stats == null ? null : stats.getJvm();
FsInfo fsInfo = stats == null ? null : stats.getFs();
@@ -232,7 +230,7 @@ private Table buildTable(RestRequest req, ClusterStateResponse state, NodesInfoR
table.startRow();
table.addCell(fullId ? node.id() : Strings.substring(node.getId(), 0, 4));
- table.addCell(info == null ? null : info.getProcess().id());
+ table.addCell(info == null ? null : info.getProcess().getId());
table.addCell(node.getHostName());
table.addCell(node.getHostAddress());
if (node.address() instanceof InetSocketTransportAddress) {
@@ -252,9 +250,8 @@ private Table buildTable(RestRequest req, ClusterStateResponse state, NodesInfoR
table.addCell(osStats == null ? null : osStats.getMem() == null ? null : osStats.getMem().usedPercent());
table.addCell(osInfo == null ? null : osInfo.getMem() == null ? null : osInfo.getMem().total()); // sigar fails to load in IntelliJ
table.addCell(processStats == null ? null : processStats.getOpenFileDescriptors());
- table.addCell(processStats == null || processInfo == null ? null :
- calculatePercentage(processStats.getOpenFileDescriptors(), processInfo.getMaxFileDescriptors()));
- table.addCell(processInfo == null ? null : processInfo.getMaxFileDescriptors());
+ table.addCell(processStats == null ? null : calculatePercentage(processStats.getOpenFileDescriptors(), processStats.getMaxFileDescriptors()));
+ table.addCell(processStats == null ? null : processStats.getMaxFileDescriptors());
table.addCell(osStats == null ? null : osStats.getLoadAverage().length < 1 ? null : String.format(Locale.ROOT, "%.2f", osStats.getLoadAverage()[0]));
table.addCell(jvmStats == null ? null : jvmStats.getUptime());
diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java
index cdde7a109eb7f..b5848379a61dd 100644
--- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java
+++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java
@@ -229,7 +229,7 @@ private Table buildTable(RestRequest req, ClusterStateResponse state, NodesInfoR
table.startRow();
table.addCell(fullId ? node.id() : Strings.substring(node.getId(), 0, 4));
- table.addCell(info == null ? null : info.getProcess().id());
+ table.addCell(info == null ? null : info.getProcess().getId());
table.addCell(node.getHostName());
table.addCell(node.getHostAddress());
if (node.address() instanceof InetSocketTransportAddress) {
diff --git a/core/src/test/java/org/elasticsearch/benchmark/monitor/process/ProcessProbeBenchmark.java b/core/src/test/java/org/elasticsearch/benchmark/monitor/process/ProcessProbeBenchmark.java
new file mode 100644
index 0000000000000..43f495b6b2fd9
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/benchmark/monitor/process/ProcessProbeBenchmark.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.benchmark.monitor.process;
+
+import org.elasticsearch.common.logging.ESLogger;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.monitor.process.ProcessProbe;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+
+public class ProcessProbeBenchmark {
+
+ private static final int ITERATIONS = 100_000;
+
+ public static void main(String[] args) {
+ System.setProperty("es.logger.prefix", "");
+ final ESLogger logger = ESLoggerFactory.getLogger("benchmark");
+
+ logger.info("--> loading process probe");
+ ProcessProbe probe = ProcessProbe.getInstance();
+
+ logger.info("--> warming up...");
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getOpenFileDescriptorCount();
+ probe.getMaxFileDescriptorCount();
+ probe.getTotalVirtualMemorySize();
+ probe.getProcessCpuPercent();
+ probe.getProcessCpuTotalTime();
+ }
+ logger.info("--> warmed up");
+
+
+
+
+ logger.info("--> testing 'getOpenFileDescriptorCount' method...");
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getOpenFileDescriptorCount();
+ }
+ long elapsed = System.currentTimeMillis() - start;
+ logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
+
+ logger.info("--> testing 'getMaxFileDescriptorCount' method...");
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getMaxFileDescriptorCount();
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
+
+ logger.info("--> testing 'getTotalVirtualMemorySize' method...");
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getTotalVirtualMemorySize();
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
+
+ logger.info("--> testing 'getProcessCpuPercent' method...");
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getProcessCpuPercent();
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
+
+ logger.info("--> testing 'getProcessCpuTotalTime' method...");
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ probe.getProcessCpuTotalTime();
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> total [{}] ms, avg [{}] ms", elapsed, (elapsed / (double)ITERATIONS));
+
+
+
+
+ logger.info("--> calculating process CPU user time with 'getAllThreadIds + getThreadUserTime' methods...");
+ final ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
+ final long[] threadIds = threadMxBean.getAllThreadIds();
+ long sum = 0;
+
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ for (long threadId : threadIds) {
+ sum += threadMxBean.getThreadUserTime(threadId);
+ }
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> execution time [total: {} ms, avg: {} ms] for {} iterations with average result of {}",
+ elapsed, (elapsed / (double)ITERATIONS), ITERATIONS, (sum / (double)ITERATIONS));
+
+ /* Commented as com.sun.management is listed as forbidden usage
+ if (threadMxBean instanceof com.sun.management.ThreadMXBean) {
+ logger.info("--> calculating process CPU user time with 'getAllThreadIds + getThreadUserTime(long[])' methods...");
+ final com.sun.management.ThreadMXBean threadMxBean2 = (com.sun.management.ThreadMXBean)threadMxBean;
+ sum = 0;
+
+ start = System.currentTimeMillis();
+ for (int i = 0; i < ITERATIONS; i++) {
+ long[] user = threadMxBean2.getThreadUserTime(threadIds);
+ for (int n = 0 ; n != threadIds.length; ++n) {
+ sum += user[n];
+ }
+ }
+ elapsed = System.currentTimeMillis() - start;
+ logger.info("--> execution time [total: {} ms, avg: {} ms] for {} iterations with average result of {}",
+ elapsed, (elapsed / (double)ITERATIONS), ITERATIONS, (sum / (double)ITERATIONS));
+
+ }*/
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java
index 083affa50b1ec..1ed5df3b75105 100644
--- a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java
+++ b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java
@@ -51,6 +51,9 @@ public class BootstrapForTesting {
static {
// just like bootstrap, initialize natives, then SM
Bootstrap.initializeNatives(true, true);
+
+ // initialize probes
+ Bootstrap.initializeProbes();
// check for jar hell
try {
diff --git a/core/src/test/java/org/elasticsearch/monitor/process/ProcessProbeTests.java b/core/src/test/java/org/elasticsearch/monitor/process/ProcessProbeTests.java
new file mode 100644
index 0000000000000..4aa4e64dbd264
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/monitor/process/ProcessProbeTests.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.monitor.process;
+
+import org.elasticsearch.bootstrap.Bootstrap;
+import org.elasticsearch.test.ElasticsearchTestCase;
+import org.junit.Test;
+
+import static org.elasticsearch.monitor.jvm.JvmInfo.jvmInfo;
+import static org.hamcrest.Matchers.*;
+
+public class ProcessProbeTests extends ElasticsearchTestCase {
+
+ ProcessProbe probe = ProcessProbe.getInstance();
+
+ @Test
+ public void testProcessInfo() {
+ ProcessInfo info = probe.processInfo();
+ assertNotNull(info);
+ assertThat(info.getRefreshInterval(), greaterThanOrEqualTo(0L));
+ assertThat(info.getId(), equalTo(jvmInfo().pid()));
+ assertThat(info.isMlockall(), equalTo(Bootstrap.isMemoryLocked()));
+ }
+
+ @Test
+ public void testProcessStats() {
+ ProcessStats stats = probe.processStats();
+ assertNotNull(stats);
+
+ ProcessStats.Cpu cpu = stats.getCpu();
+ assertNotNull(cpu);
+ assertThat(cpu.getPercent(), greaterThanOrEqualTo((short) 0));
+ assertThat(cpu.total, anyOf(equalTo(-1L), greaterThan(0L)));
+
+ ProcessStats.Mem mem = stats.getMem();
+ assertNotNull(mem);
+ assertThat(mem.totalVirtual, anyOf(equalTo(-1L), greaterThan(0L)));
+ }
+}
diff --git a/docs/reference/cluster/nodes-info.asciidoc b/docs/reference/cluster/nodes-info.asciidoc
index 07a2360acbee2..73dbb488476cf 100644
--- a/docs/reference/cluster/nodes-info.asciidoc
+++ b/docs/reference/cluster/nodes-info.asciidoc
@@ -32,6 +32,28 @@ curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2/_all
The `_all` flag can be set to return all the information - or you can simply omit it.
+
+[float]
+[[process-info]]
+==== Process information
+
+The `process` flag can be set to retrieve information that concern
+the current running process:
+
+`process.refresh_interval_in_millis`::
+ Refresh interval for the process statistics.
+
+`process.id`::
+ Process identifier (PID)
+
+`process.mlockall`::
+ Indicates if the process address space has been successfully locked in memory
+
+
+[float]
+[[plugins-info]]
+==== Plugins information
+
`plugins` - if set, the result will contain details about the loaded
plugins per node:
diff --git a/docs/reference/cluster/nodes-stats.asciidoc b/docs/reference/cluster/nodes-stats.asciidoc
index ce65c15153e82..47ef6ae87aa34 100644
--- a/docs/reference/cluster/nodes-stats.asciidoc
+++ b/docs/reference/cluster/nodes-stats.asciidoc
@@ -23,33 +23,33 @@ of `indices`, `os`, `process`, `jvm`, `transport`, `http`,
`fs`, `breaker` and `thread_pool`. For example:
[horizontal]
-`indices`::
+`indices`::
Indices stats about size, document count, indexing and
deletion times, search times, field cache size, merges and flushes
-`fs`::
+`fs`::
File system information, data path, free disk space, read/write
stats (see <