Merge remote-tracking branch 'upstream/master' into feature/ingest

This commit is contained in:
Tal Levy 2015-11-17 12:08:26 -08:00
commit d0b5fc8bb4
33 changed files with 343 additions and 99 deletions

View File

@ -171,5 +171,9 @@ task clean(type: GradleBuild) {
tasks = ['clean'] tasks = ['clean']
} }
task run(dependsOn: ':distribution:run') task run() {
dependsOn ':distribution:run'
description = 'Runs elasticsearch in the foreground'
group = 'Verification'
}

View File

@ -23,45 +23,163 @@ import com.carrotsearch.ant.tasks.junit4.JUnit4
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.eventbus.Subscribe import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.eventbus.Subscribe
import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent
import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteResultEvent import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteResultEvent
import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedTestResultEvent
import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener
import org.gradle.logging.ProgressLogger import org.gradle.logging.ProgressLogger
import org.gradle.logging.ProgressLoggerFactory import org.gradle.logging.ProgressLoggerFactory
import org.junit.runner.Description import org.junit.runner.Description
import java.util.concurrent.atomic.AtomicInteger import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.*
import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatDurationInSeconds import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatDurationInSeconds
import static java.lang.Math.max
/**
* Adapts junit4's event listeners into gradle's ProgressLogger. Note that
* junit4 guarantees (via guava) that methods on this class won't be called by
* multiple threads simultaneously which is helpful in making it simpler.
*
* Every time a test finishes this class will update the logger. It will log
* the last finished test method on the logger line until the first suite
* finishes. Once the first suite finishes it always logs the last finished
* suite. This means that in test runs with a single suite the logger will be
* updated with the test name the whole time which is useful because these runs
* usually have longer individual tests. For test runs with lots of suites the
* majority of the time is spent showing the last suite that finished which is
* more useful for those test runs because test methods there tend to be very
* quick.
*/
class TestProgressLogger implements AggregatedEventListener { class TestProgressLogger implements AggregatedEventListener {
/** Factory to build a progress logger when testing starts */ /** Factory to build a progress logger when testing starts */
ProgressLoggerFactory factory ProgressLoggerFactory factory
ProgressLogger progressLogger ProgressLogger progressLogger
int totalSuites; int totalSuites
AtomicInteger suitesCompleted = new AtomicInteger() int totalSlaves
AtomicInteger testsCompleted = new AtomicInteger()
AtomicInteger testsFailed = new AtomicInteger() // sprintf formats used to align the integers we print
AtomicInteger testsIgnored = new AtomicInteger() String suitesFormat
String slavesFormat
String testsFormat
// Counters incremented test completion.
volatile int suitesCompleted = 0
volatile int testsCompleted = 0
volatile int testsFailed = 0
volatile int testsIgnored = 0
// Information about the last, most interesting event.
volatile String eventDescription
volatile int eventSlave
volatile long eventExecutionTime
/** Have we finished a whole suite yet? */
volatile boolean suiteFinished = false
/* Note that we probably overuse volatile here but it isn't hurting us and
lets us move things around without worying about breaking things. */
@Subscribe @Subscribe
void onStart(AggregatedStartEvent e) throws IOException { void onStart(AggregatedStartEvent e) throws IOException {
totalSuites = e.getSuiteCount(); totalSuites = e.suiteCount
totalSlaves = e.slaveCount
progressLogger = factory.newOperation(TestProgressLogger) progressLogger = factory.newOperation(TestProgressLogger)
progressLogger.setDescription('Randomized test runner') progressLogger.setDescription('Randomized test runner')
progressLogger.started() progressLogger.started()
progressLogger.progress('Starting JUnit4 with ' + e.getSlaveCount() + ' jvms') progressLogger.progress(
"Starting JUnit4 for ${totalSuites} suites on ${totalSlaves} jvms")
suitesFormat = "%0${widthForTotal(totalSuites)}d"
slavesFormat = "%-${widthForTotal(totalSlaves)}s"
/* Just guess the number of tests because we can't figure it out from
here and it isn't worth doing anything fancy to prevent the console
from jumping around a little. 200 is a pretty wild guess for the
minimum but it makes REST tests output sanely. */
int totalNumberOfTestsGuess = max(200, totalSuites * 10)
testsFormat = "%0${widthForTotal(totalNumberOfTestsGuess)}d"
}
@Subscribe
void onTestResult(AggregatedTestResultEvent e) throws IOException {
testsCompleted++
switch (e.status) {
case ERROR:
case FAILURE:
testsFailed++
break
case IGNORED:
case IGNORED_ASSUMPTION:
testsIgnored++
break
case OK:
break
default:
throw new IllegalArgumentException(
"Unknown test status: [${e.status}]")
}
if (!suiteFinished) {
updateEventInfo(e)
}
log()
} }
@Subscribe @Subscribe
void onSuiteResult(AggregatedSuiteResultEvent e) throws IOException { void onSuiteResult(AggregatedSuiteResultEvent e) throws IOException {
final int suitesCompleted = suitesCompleted.incrementAndGet(); suitesCompleted++
final int testsCompleted = testsCompleted.addAndGet(e.getDescription().testCount()) suiteFinished = true
final int testsFailed = testsFailed.addAndGet(e.getErrorCount() + e.getFailureCount()) updateEventInfo(e)
final int testsIgnored = testsIgnored.addAndGet(e.getIgnoredCount()) log()
Description description = e.getDescription() }
String suiteName = description.getDisplayName();
suiteName = suiteName.substring(suiteName.lastIndexOf('.') + 1); /**
progressLogger.progress('Suites [' + suitesCompleted + '/' + totalSuites + '], Tests [' + testsCompleted + '|' + testsFailed + '|' + testsIgnored + '], ' + suiteName + ' on J' + e.getSlave().id + ' in ' + formatDurationInSeconds(e.getExecutionTime())) * Update the suite information with a junit4 event.
*/
private void updateEventInfo(Object e) {
eventDescription = simpleName(e.description.className)
if (e.description.methodName != null) {
eventDescription += "#${e.description.methodName}"
}
eventSlave = e.slave.id
eventExecutionTime = e.executionTime
}
/**
* Extract a Class#getSimpleName style name from Class#getName style
* string. We can't just use Class#getSimpleName because junit descriptions
* don't alway s set the class field but they always set the className
* field.
*/
private static String simpleName(String className) {
return className.substring(className.lastIndexOf('.') + 1)
}
private void log() {
/* Remember that instances of this class are only ever active on one
thread at a time so there really aren't race conditions here. It'd be
OK if there were because they'd only display an overcount
temporarily. */
String log = ''
if (totalSuites > 1) {
/* Skip printing the suites to save space when there is only a
single suite. This is nice because when there is only a single
suite we log the method name and those can be long. */
log += sprintf("Suites [${suitesFormat}/${suitesFormat}], ",
[suitesCompleted, totalSuites])
}
log += sprintf("Tests [${testsFormat}|%d|%d], ",
[testsCompleted, testsFailed, testsIgnored])
log += "in ${formatDurationInSeconds(eventExecutionTime)} "
if (totalSlaves > 1) {
/* Skip printing the slaves if there is only one of them. This is
nice because when there is only a single slave there is often
only a single suite and we could use the extra space to log the
test method names. */
log += "J${sprintf(slavesFormat, eventSlave)} "
}
log += "completed ${eventDescription}"
progressLogger.progress(log)
}
private static int widthForTotal(int total) {
return ((total - 1) as String).length()
} }
@Override @Override

View File

@ -240,6 +240,10 @@ class BuildPlugin implements Plugin<Project> {
'X-Compile-Elasticsearch-Version': VersionProperties.elasticsearch, 'X-Compile-Elasticsearch-Version': VersionProperties.elasticsearch,
'X-Compile-Lucene-Version': VersionProperties.lucene, 'X-Compile-Lucene-Version': VersionProperties.lucene,
'Build-Date': ZonedDateTime.now(ZoneOffset.UTC)) 'Build-Date': ZonedDateTime.now(ZoneOffset.UTC))
if (jarTask.manifest.attributes.containsKey('Change') == false) {
logger.warn('Building without git revision id.')
jarTask.manifest.attributes('Change': 'N/A')
}
} }
} }
} }

View File

@ -18,9 +18,9 @@
*/ */
package org.elasticsearch.gradle.plugin package org.elasticsearch.gradle.plugin
import nebula.plugin.extraconfigurations.ProvidedBasePlugin
import org.elasticsearch.gradle.BuildPlugin import org.elasticsearch.gradle.BuildPlugin
import org.elasticsearch.gradle.test.RestIntegTestTask import org.elasticsearch.gradle.test.RestIntegTestTask
import org.elasticsearch.gradle.test.RunTask
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.tasks.bundling.Zip import org.gradle.api.tasks.bundling.Zip
@ -33,26 +33,21 @@ class PluginBuildPlugin extends BuildPlugin {
@Override @Override
void apply(Project project) { void apply(Project project) {
super.apply(project) super.apply(project)
// TODO: add target compatibility (java version) to elasticsearch properties and set for the project
configureDependencies(project) configureDependencies(project)
// this afterEvaluate must happen before the afterEvaluate added by integTest configure, // this afterEvaluate must happen before the afterEvaluate added by integTest configure,
// so that the file name resolution for installing the plugin will be setup // so that the file name resolution for installing the plugin will be setup
project.afterEvaluate { project.afterEvaluate {
project.jar.configure { String name = project.pluginProperties.extension.name
baseName project.pluginProperties.extension.name project.jar.baseName = name
} project.bundlePlugin.baseName = name
project.bundlePlugin.configure { project.integTest.dependsOn(project.bundlePlugin)
baseName project.pluginProperties.extension.name project.integTest.clusterConfig.plugin(name, project.bundlePlugin.outputs.files)
} project.tasks.run.dependsOn(project.bundlePlugin)
project.integTest.configure { project.tasks.run.clusterConfig.plugin(name, project.bundlePlugin.outputs.files)
dependsOn project.bundlePlugin
cluster {
plugin project.pluginProperties.extension.name, project.bundlePlugin.outputs.files
}
}
} }
Task bundle = configureBundleTask(project)
RestIntegTestTask.configure(project) RestIntegTestTask.configure(project)
RunTask.configure(project)
Task bundle = configureBundleTask(project)
project.configurations.archives.artifacts.removeAll { it.archiveTask.is project.jar } project.configurations.archives.artifacts.removeAll { it.archiveTask.is project.jar }
project.configurations.getByName('default').extendsFrom = [] project.configurations.getByName('default').extendsFrom = []
project.artifacts { project.artifacts {

View File

@ -102,7 +102,7 @@ class ClusterFormationTasks {
String camelName = plugin.getKey().replaceAll(/-(\w)/) { _, c -> c.toUpperCase(Locale.ROOT) } String camelName = plugin.getKey().replaceAll(/-(\w)/) { _, c -> c.toUpperCase(Locale.ROOT) }
String taskName = "${task.name}#install${camelName[0].toUpperCase(Locale.ROOT) + camelName.substring(1)}Plugin" String taskName = "${task.name}#install${camelName[0].toUpperCase(Locale.ROOT) + camelName.substring(1)}Plugin"
// delay reading the file location until execution time by wrapping in a closure within a GString // delay reading the file location until execution time by wrapping in a closure within a GString
String file = "${ -> new File(pluginsTmpDir, plugin.getValue().singleFile.getName()).toURI().toURL().toString() }" String file = "${-> new File(pluginsTmpDir, plugin.getValue().singleFile.getName()).toURI().toURL().toString()}"
Object[] args = [new File(home, 'bin/plugin'), 'install', file] Object[] args = [new File(home, 'bin/plugin'), 'install', file]
setup = configureExecTask(taskName, project, setup, cwd, args) setup = configureExecTask(taskName, project, setup, cwd, args)
} }
@ -115,8 +115,11 @@ class ClusterFormationTasks {
Task start = configureStartTask("${task.name}#start", project, setup, cwd, config, clusterName, pidFile, home) Task start = configureStartTask("${task.name}#start", project, setup, cwd, config, clusterName, pidFile, home)
task.dependsOn(start) task.dependsOn(start)
Task stop = configureStopTask("${task.name}#stop", project, [], pidFile) if (config.daemonize) {
task.finalizedBy(stop) // if we are running in the background, make sure to stop the server when the task completes
Task stop = configureStopTask("${task.name}#stop", project, [], pidFile)
task.finalizedBy(stop)
}
} }
/** Adds a task to extract the elasticsearch distribution */ /** Adds a task to extract the elasticsearch distribution */

View File

@ -1,12 +1,23 @@
package org.elasticsearch.gradle.test package org.elasticsearch.gradle.test
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction import org.gradle.api.Project
class RunTask extends DefaultTask { class RunTask extends DefaultTask {
ClusterConfiguration clusterConfig = new ClusterConfiguration(httpPort: 9200, transportPort: 9300, daemonize: false) ClusterConfiguration clusterConfig = new ClusterConfiguration(httpPort: 9200, transportPort: 9300, daemonize: false)
RunTask() { RunTask() {
ClusterFormationTasks.setup(project, this, clusterConfig) project.afterEvaluate {
ClusterFormationTasks.setup(project, this, clusterConfig)
}
}
static void configure(Project project) {
RunTask task = project.tasks.create(
name: 'run',
type: RunTask,
description: "Runs elasticsearch with '${project.path}'",
group: 'Verification')
} }
} }

View File

@ -33,9 +33,13 @@ import java.util.jar.JarInputStream;
import java.util.jar.Manifest; import java.util.jar.Manifest;
/** /**
* Information about a build of Elasticsearch.
*/ */
public class Build { public class Build {
/**
* The current build of Elasticsearch. Filled with information scanned at
* startup from the jar.
*/
public static final Build CURRENT; public static final Build CURRENT;
static { static {
@ -56,6 +60,14 @@ public class Build {
shortHash = "Unknown"; shortHash = "Unknown";
date = "Unknown"; date = "Unknown";
} }
if (shortHash == null) {
throw new IllegalStateException("Error finding the build shortHash. " +
"Stopping Elasticsearch now so it doesn't run in subtly broken ways. This is likely a build bug.");
}
if (date == null) {
throw new IllegalStateException("Error finding the build date. " +
"Stopping Elasticsearch now so it doesn't run in subtly broken ways. This is likely a build bug.");
}
CURRENT = new Build(shortHash, date); CURRENT = new Build(shortHash, date);
} }

View File

@ -223,8 +223,8 @@ public class NodeStats extends BaseNodeResponse implements ToXContent {
http = HttpStats.readHttpStats(in); http = HttpStats.readHttpStats(in);
} }
breaker = AllCircuitBreakerStats.readOptionalAllCircuitBreakerStats(in); breaker = AllCircuitBreakerStats.readOptionalAllCircuitBreakerStats(in);
scriptStats = in.readOptionalStreamable(new ScriptStats()); scriptStats = in.readOptionalStreamable(ScriptStats::new);
discoveryStats = in.readOptionalStreamable(new DiscoveryStats(null)); discoveryStats = in.readOptionalStreamable(() -> new DiscoveryStats(null));
} }

View File

@ -553,10 +553,10 @@ public class CommonStats implements Streamable, ToXContent {
if (in.readBoolean()) { if (in.readBoolean()) {
segments = SegmentsStats.readSegmentsStats(in); segments = SegmentsStats.readSegmentsStats(in);
} }
translog = in.readOptionalStreamable(new TranslogStats()); translog = in.readOptionalStreamable(TranslogStats::new);
suggest = in.readOptionalStreamable(new SuggestStats()); suggest = in.readOptionalStreamable(SuggestStats::new);
requestCache = in.readOptionalStreamable(new RequestCacheStats()); requestCache = in.readOptionalStreamable(RequestCacheStats::new);
recoveryStats = in.readOptionalStreamable(new RecoveryStats()); recoveryStats = in.readOptionalStreamable(RecoveryStats::new);
} }
@Override @Override

View File

@ -346,7 +346,7 @@ public class SearchRequest extends ActionRequest<SearchRequest> implements Indic
indicesOptions = IndicesOptions.readIndicesOptions(in); indicesOptions = IndicesOptions.readIndicesOptions(in);
requestCache = in.readOptionalBoolean(); requestCache = in.readOptionalBoolean();
template = in.readOptionalStreamable(new Template()); template = in.readOptionalStreamable(Template::new);
} }
@Override @Override

View File

@ -68,7 +68,7 @@ public class RestoreSource implements Streamable, ToXContent {
} }
public static RestoreSource readOptionalRestoreSource(StreamInput in) throws IOException { public static RestoreSource readOptionalRestoreSource(StreamInput in) throws IOException {
return in.readOptionalStreamable(new RestoreSource()); return in.readOptionalStreamable(RestoreSource::new);
} }
@Override @Override

View File

@ -39,7 +39,7 @@ public class RoutingValidationException extends RoutingException {
public RoutingValidationException(StreamInput in) throws IOException { public RoutingValidationException(StreamInput in) throws IOException {
super(in); super(in);
validation = in.readOptionalStreamable(new RoutingTableValidation()); validation = in.readOptionalStreamable(RoutingTableValidation::new);
} }
@Override @Override

View File

@ -53,6 +53,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import static org.elasticsearch.ElasticsearchException.readException; import static org.elasticsearch.ElasticsearchException.readException;
import static org.elasticsearch.ElasticsearchException.readStackTrace; import static org.elasticsearch.ElasticsearchException.readStackTrace;
@ -532,8 +533,9 @@ public abstract class StreamInput extends InputStream {
/** /**
* Serializes a potential null value. * Serializes a potential null value.
*/ */
public <T extends Streamable> T readOptionalStreamable(T streamable) throws IOException { public <T extends Streamable> T readOptionalStreamable(Supplier<T> supplier) throws IOException {
if (readBoolean()) { if (readBoolean()) {
T streamable = supplier.get();
streamable.readFrom(this); streamable.readFrom(this);
return streamable; return streamable;
} else { } else {

View File

@ -62,7 +62,7 @@ public final class CommitStats implements Streamable, ToXContent {
} }
public static CommitStats readOptionalCommitStatsFrom(StreamInput in) throws IOException { public static CommitStats readOptionalCommitStatsFrom(StreamInput in) throws IOException {
return in.readOptionalStreamable(new CommitStats()); return in.readOptionalStreamable(CommitStats::new);
} }

View File

@ -57,7 +57,7 @@ public class AllCircuitBreakerStats implements Streamable, ToXContent {
} }
public static AllCircuitBreakerStats readOptionalAllCircuitBreakerStats(StreamInput in) throws IOException { public static AllCircuitBreakerStats readOptionalAllCircuitBreakerStats(StreamInput in) throws IOException {
AllCircuitBreakerStats stats = in.readOptionalStreamable(new AllCircuitBreakerStats()); AllCircuitBreakerStats stats = in.readOptionalStreamable(AllCircuitBreakerStats::new);
return stats; return stats;
} }

View File

@ -74,7 +74,7 @@ public class CircuitBreakerStats implements Streamable, ToXContent {
} }
public static CircuitBreakerStats readOptionalCircuitBreakerStats(StreamInput in) throws IOException { public static CircuitBreakerStats readOptionalCircuitBreakerStats(StreamInput in) throws IOException {
CircuitBreakerStats stats = in.readOptionalStreamable(new CircuitBreakerStats()); CircuitBreakerStats stats = in.readOptionalStreamable(CircuitBreakerStats::new);
return stats; return stats;
} }

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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));
} }
} }

View File

@ -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;
} }
/** /**

View File

@ -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" : "-");

View File

@ -194,7 +194,7 @@ public class InternalAggregations implements Aggregations, ToXContent, Streamabl
} }
public static InternalAggregations readOptionalAggregations(StreamInput in) throws IOException { public static InternalAggregations readOptionalAggregations(StreamInput in) throws IOException {
return in.readOptionalStreamable(new InternalAggregations()); return in.readOptionalStreamable(InternalAggregations::new);
} }
@Override @Override

View File

@ -559,7 +559,7 @@ public class InternalSearchHit implements SearchHit {
score = in.readFloat(); score = in.readFloat();
id = in.readText(); id = in.readText();
type = in.readText(); type = in.readText();
nestedIdentity = in.readOptionalStreamable(new InternalNestedIdentity()); nestedIdentity = in.readOptionalStreamable(InternalNestedIdentity::new);
version = in.readLong(); version = in.readLong();
source = in.readBytesReference(); source = in.readBytesReference();
if (source.length() == 0) { if (source.length() == 0) {
@ -810,7 +810,7 @@ public class InternalSearchHit implements SearchHit {
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
field = in.readOptionalText(); field = in.readOptionalText();
offset = in.readInt(); offset = in.readInt();
child = in.readOptionalStreamable(new InternalNestedIdentity()); child = in.readOptionalStreamable(InternalNestedIdentity::new);
} }
@Override @Override

View File

@ -180,7 +180,7 @@ public class ShardSearchLocalRequest extends ContextAndHeaderHolder implements S
types = in.readStringArray(); types = in.readStringArray();
filteringAliases = in.readStringArray(); filteringAliases = in.readStringArray();
nowInMillis = in.readVLong(); nowInMillis = in.readVLong();
template = in.readOptionalStreamable(new Template()); template = in.readOptionalStreamable(Template::new);
requestCache = in.readOptionalBoolean(); requestCache = in.readOptionalBoolean();
} }

View File

@ -190,7 +190,7 @@ public class RestoreInfo implements ToXContent, Streamable {
* @return restore info * @return restore info
*/ */
public static RestoreInfo readOptionalRestoreInfo(StreamInput in) throws IOException { public static RestoreInfo readOptionalRestoreInfo(StreamInput in) throws IOException {
return in.readOptionalStreamable(new RestoreInfo()); return in.readOptionalStreamable(RestoreInfo::new);
} }
} }

View File

@ -324,7 +324,7 @@ public class SnapshotInfo implements ToXContent, Streamable {
* @return deserialized snapshot info or null * @return deserialized snapshot info or null
*/ */
public static SnapshotInfo readOptionalSnapshotInfo(StreamInput in) throws IOException { public static SnapshotInfo readOptionalSnapshotInfo(StreamInput in) throws IOException {
return in.readOptionalStreamable(new SnapshotInfo()); return in.readOptionalStreamable(SnapshotInfo::new);
} }
} }

View File

@ -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));
} }
} }

View File

@ -1,3 +1,22 @@
/*
* 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.common.io.stream; package org.elasticsearch.common.io.stream;
import org.elasticsearch.common.bytes.ByteBufferBytesReference; import org.elasticsearch.common.bytes.ByteBufferBytesReference;

View File

@ -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());

View File

@ -19,6 +19,7 @@
import org.apache.tools.ant.filters.FixCrLfFilter import org.apache.tools.ant.filters.FixCrLfFilter
import org.elasticsearch.gradle.precommit.DependencyLicensesTask import org.elasticsearch.gradle.precommit.DependencyLicensesTask
import org.elasticsearch.gradle.test.RunTask
import org.elasticsearch.gradle.MavenFilteringHack import org.elasticsearch.gradle.MavenFilteringHack
// for deb/rpm // for deb/rpm
@ -196,4 +197,5 @@ DependencyLicensesTask.configure(project) {
mapping from: /jackson-.*/, to: 'jackson' mapping from: /jackson-.*/, to: 'jackson'
} }
task run(type:org.elasticsearch.gradle.test.RunTask){} RunTask.configure(project)

View File

@ -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`::

View File

@ -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`.

View File

@ -6,8 +6,8 @@
- match: - match:
$body: | $body: |
/ #host ip heap.percent ram.percent load node.role master name / #host ip heap.percent ram.percent cpu load node.role master name
^ (\S+ \s+ (\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d*(\.\d+)? \s+ [-dc] \s+ [-*mx] \s+ (\S+\s?)+ \s+ \n)+ $/ ^ (\S+ \s+ (\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ \d* \s+ (-)?\d*(\.\d+)? \s+ [-dc] \s+ [-*mx] \s+ (\S+\s?)+ \s+ \n)+ $/
- do: - do:
cat.nodes: cat.nodes:
@ -15,8 +15,8 @@
- match: - match:
$body: | $body: |
/^ host \s+ ip \s+ heap\.percent \s+ ram\.percent \s+ load \s+ node\.role \s+ master \s+ name \s+ \n /^ host \s+ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load \s+ node\.role \s+ master \s+ name \s+ \n
(\S+ \s+ (\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d*(\.\d+)? \s+ [-dc] \s+ [-*mx] \s+ (\S+\s?)+ \s+ \n)+ $/ (\S+ \s+ (\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ \d* \s+ (-)?\d*(\.\d+)? \s+ [-dc] \s+ [-*mx] \s+ (\S+\s?)+ \s+ \n)+ $/
- do: - do:
cat.nodes: cat.nodes: