From 863fab4007c610eabf77124a0763292f5ac79b6e Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Fri, 26 Feb 2016 14:12:56 -0500 Subject: [PATCH] Add start time and duration to tasks Tasks now contain timestamps indicating when the tasks were created and current run time --- .../cluster/node/tasks/list/TaskInfo.java | 33 ++++++++++++++++++- .../common/xcontent/XContentBuilder.java | 19 ++++++++++- .../java/org/elasticsearch/tasks/Task.java | 20 ++++++++++- .../node/tasks/TransportTasksActionTests.java | 6 ++++ 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TaskInfo.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TaskInfo.java index d71c576093eb0..c027bfa7ab4cb 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TaskInfo.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TaskInfo.java @@ -29,6 +29,7 @@ import org.elasticsearch.tasks.TaskId; import java.io.IOException; +import java.util.concurrent.TimeUnit; /** * Information about a currently running task. @@ -50,17 +51,24 @@ public class TaskInfo implements Writeable, ToXContent { private final String description; + private final long startTime; + + private final long runningTimeNanos; + private final Task.Status status; private final TaskId parentTaskId; - public TaskInfo(DiscoveryNode node, long id, String type, String action, String description, Task.Status status, TaskId parentTaskId) { + public TaskInfo(DiscoveryNode node, long id, String type, String action, String description, Task.Status status, long startTime, + long runningTimeNanos, TaskId parentTaskId) { this.node = node; this.taskId = new TaskId(node.getId(), id); this.type = type; this.action = action; this.description = description; this.status = status; + this.startTime = startTime; + this.runningTimeNanos = runningTimeNanos; this.parentTaskId = parentTaskId; } @@ -75,6 +83,8 @@ public TaskInfo(StreamInput in) throws IOException { } else { status = null; } + startTime = in.readLong(); + runningTimeNanos = in.readLong(); parentTaskId = new TaskId(in); } @@ -110,6 +120,23 @@ public Task.Status getStatus() { return status; } + /** + * Returns the task start time + */ + public long getStartTime() { + return startTime; + } + + /** + * Returns the task running time + */ + public long getRunningTimeNanos() { + return runningTimeNanos; + } + + /** + * Returns the parent task id + */ public TaskId getParentTaskId() { return parentTaskId; } @@ -132,6 +159,8 @@ public void writeTo(StreamOutput out) throws IOException { } else { out.writeBoolean(false); } + out.writeLong(startTime); + out.writeLong(runningTimeNanos); parentTaskId.writeTo(out); } @@ -147,6 +176,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (description != null) { builder.field("description", description); } + builder.dateValueField("start_time_in_millis", "start_time", startTime); + builder.timeValueField("running_time_in_nanos", "running_time", runningTimeNanos, TimeUnit.NANOSECONDS); if (parentTaskId.isSet() == false) { builder.field("parent_task_id", parentTaskId.toString()); } diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java index 7ac098f5a64ce..8ca53af186c4f 100644 --- a/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java +++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java @@ -48,7 +48,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.function.BiConsumer; +import java.util.concurrent.TimeUnit; /** * @@ -961,6 +961,23 @@ public XContentBuilder dateValueField(XContentBuilderString rawFieldName, XConte return this; } + public XContentBuilder timeValueField(String rawFieldName, String readableFieldName, long rawTime, TimeUnit timeUnit) throws + IOException { + if (humanReadable) { + field(readableFieldName, new TimeValue(rawTime, timeUnit).toString()); + } + field(rawFieldName, rawTime); + return this; + } + + public XContentBuilder dateValueField(String rawFieldName, String readableFieldName, long rawTimestamp) throws IOException { + if (humanReadable) { + field(readableFieldName, defaultDatePrinter.print(rawTimestamp)); + } + field(rawFieldName, rawTimestamp); + return this; + } + public XContentBuilder byteSizeField(XContentBuilderString rawFieldName, XContentBuilderString readableFieldName, ByteSizeValue byteSizeValue) throws IOException { if (humanReadable) { field(readableFieldName, byteSizeValue.toString()); diff --git a/core/src/main/java/org/elasticsearch/tasks/Task.java b/core/src/main/java/org/elasticsearch/tasks/Task.java index 5aa034b799773..2334d10e11b2f 100644 --- a/core/src/main/java/org/elasticsearch/tasks/Task.java +++ b/core/src/main/java/org/elasticsearch/tasks/Task.java @@ -40,16 +40,26 @@ public class Task { private final TaskId parentTask; + private final long startTime; + + private final long startTimeNanos; + public Task(long id, String type, String action, String description) { this(id, type, action, description, TaskId.EMPTY_TASK_ID); } public Task(long id, String type, String action, String description, TaskId parentTask) { + this(id, type, action, description, parentTask, System.currentTimeMillis(), System.nanoTime()); + } + + public Task(long id, String type, String action, String description, TaskId parentTask, long startTime, long startTimeNanos) { this.id = id; this.type = type; this.action = action; this.description = description; this.parentTask = parentTask; + this.startTime = startTime; + this.startTimeNanos = startTimeNanos; } /** @@ -69,7 +79,8 @@ public TaskInfo taskInfo(DiscoveryNode node, boolean detailed) { description = getDescription(); status = getStatus(); } - return new TaskInfo(node, getId(), getType(), getAction(), description, status, parentTask); + return new TaskInfo(node, getId(), getType(), getAction(), description, status, startTime, System.nanoTime() - startTimeNanos, + parentTask); } /** @@ -100,6 +111,13 @@ public String getDescription() { return description; } + /** + * Returns the task start time + */ + public long getStartTime() { + return startTime; + } + /** * Returns id of the parent task or NO_PARENT_ID if the task doesn't have any parent tasks */ diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java index b4464dc9f58d5..e1501f9b14c93 100644 --- a/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java +++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TransportTasksActionTests.java @@ -63,6 +63,7 @@ import static org.elasticsearch.action.support.PlainActionFuture.newFuture; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.not; public class TransportTasksActionTests extends TaskManagerTestCase { @@ -461,10 +462,12 @@ public void testTaskManagementOptOut() throws Exception { } public void testTasksDescriptions() throws Exception { + long minimalStartTime = System.currentTimeMillis(); setupTestNodes(Settings.EMPTY); connectNodes(testNodes); CountDownLatch checkLatch = new CountDownLatch(1); ActionFuture future = startBlockingTestNodesAction(checkLatch); + long maximumStartTimeNanos = System.nanoTime(); // Check task counts using transport with filtering TestNode testNode = testNodes[randomIntBetween(0, testNodes.length - 1)]; @@ -478,12 +481,15 @@ public void testTasksDescriptions() throws Exception { } // Check task counts using transport with detailed description + long minimalDurationNanos = System.nanoTime() - maximumStartTimeNanos; listTasksRequest.detailed(true); // same request only with detailed description response = testNode.transportListTasksAction.execute(listTasksRequest).get(); assertEquals(testNodes.length, response.getPerNodeTasks().size()); for (Map.Entry> entry : response.getPerNodeTasks().entrySet()) { assertEquals(1, entry.getValue().size()); assertEquals("CancellableNodeRequest[Test Request, true]", entry.getValue().get(0).getDescription()); + assertThat(entry.getValue().get(0).getStartTime(), greaterThanOrEqualTo(minimalStartTime)); + assertThat(entry.getValue().get(0).getRunningTimeNanos(), greaterThanOrEqualTo(minimalDurationNanos)); } // Release all tasks and wait for response