You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by br...@apache.org on 2013/11/14 20:19:14 UTC
git commit: Added list of TaskStatuses to Task message.
Updated Branches:
refs/heads/master bb4db98a9 -> 480f8a71f
Added list of TaskStatuses to Task message.
Task now includes repeated task status with timestamps. This permits
caltulating the start/finish time for tasks (among other things).
To support this, a timestamp was added to the TaskStatus message which
is also passed to frameworks when there are state transitions.
Review: https://reviews.apache.org/r/14434
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/480f8a71
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/480f8a71
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/480f8a71
Branch: refs/heads/master
Commit: 480f8a71f6ad8c0698937249445e6405e6443c9c
Parents: bb4db98
Author: Brenden Matthews <br...@airbnb.com>
Authored: Tue Oct 1 16:21:44 2013 -0700
Committer: Brenden Matthews <br...@airbnb.com>
Committed: Thu Nov 14 11:19:07 2013 -0800
----------------------------------------------------------------------
include/mesos/mesos.proto | 5 +--
src/common/protobuf_utils.hpp | 1 +
src/exec/exec.cpp | 1 +
src/master/http.cpp | 19 +++++++++++
src/master/master.cpp | 5 +++
src/messages/messages.proto | 2 +-
src/slave/slave.cpp | 16 ++++++---
src/slave/slave.hpp | 2 +-
src/webui/master/static/framework.html | 45 ++++++++++++++++++++++++++
src/webui/master/static/frameworks.html | 2 +-
src/webui/master/static/js/controllers.js | 4 +++
11 files changed, 92 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index ad4ba5b..655f867 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -394,6 +394,7 @@ message TaskStatus {
optional string message = 4; // Possible message explaining state.
optional bytes data = 3;
optional SlaveID slave_id = 5;
+ optional double timestamp = 6;
}
@@ -434,8 +435,8 @@ message Parameter {
required string key = 1;
required string value = 2;
}
-
-
+
+
/**
* Collection of Parameter.
*/
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/common/protobuf_utils.hpp
----------------------------------------------------------------------
diff --git a/src/common/protobuf_utils.hpp b/src/common/protobuf_utils.hpp
index 19a49ab..c83cbd6 100644
--- a/src/common/protobuf_utils.hpp
+++ b/src/common/protobuf_utils.hpp
@@ -66,6 +66,7 @@ inline StatusUpdate createStatusUpdate(
status->mutable_slave_id()->MergeFrom(slaveId);
status->set_state(state);
status->set_message(message);
+ status->set_timestamp(update.timestamp());
return update;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/exec/exec.cpp
----------------------------------------------------------------------
diff --git a/src/exec/exec.cpp b/src/exec/exec.cpp
index 4a598f5..c866838 100644
--- a/src/exec/exec.cpp
+++ b/src/exec/exec.cpp
@@ -495,6 +495,7 @@ protected:
update->mutable_slave_id()->MergeFrom(slaveId);
update->mutable_status()->MergeFrom(status);
update->set_timestamp(Clock::now().secs());
+ update->mutable_status()->set_timestamp(update->timestamp());
update->set_uuid(UUID::random().toBytes());
message.set_pid(self());
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index f2a535a..deb5c97 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -38,6 +38,7 @@
#include "common/attributes.hpp"
#include "common/build.hpp"
#include "common/type_utils.hpp"
+#include "common/protobuf_utils.hpp"
#include "logging/logging.hpp"
@@ -121,6 +122,17 @@ JSON::Object model(const Attributes& attributes)
}
+// Returns a JSON object modeled on a TaskStatus.
+JSON::Object model(const TaskStatus& status)
+{
+ JSON::Object object;
+ object.values["state"] = TaskState_Name(status.state());
+ object.values["timestamp"] = status.timestamp();
+
+ return object;
+}
+
+
// Returns a JSON object modeled on a Task.
// TODO(bmahler): Expose the executor name / source.
JSON::Object model(const Task& task)
@@ -133,6 +145,13 @@ JSON::Object model(const Task& task)
object.values["slave_id"] = task.slave_id().value();
object.values["state"] = TaskState_Name(task.state());
object.values["resources"] = model(task.resources());
+
+ JSON::Array array;
+ foreach (const TaskStatus& status, task.statuses()) {
+ array.values.push_back(model(status));
+ }
+ object.values["statuses"] = array;
+
return object;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 8e14a07..abab6ce 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -1417,6 +1417,11 @@ void Master::statusUpdate(const StatusUpdate& update, const UPID& pid)
LOG(INFO) << "Status update " << update << " from " << pid;
+ // TODO(brenden) Consider wiping the `data` and `message` fields?
+ if (task->state() == status.state()) {
+ task->mutable_statuses()->RemoveLast();
+ }
+ task->add_statuses()->CopyFrom(status);
task->set_state(status.state());
// Handle the task appropriately if it's terminated.
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/messages/messages.proto
----------------------------------------------------------------------
diff --git a/src/messages/messages.proto b/src/messages/messages.proto
index a5dded2..71f68a0 100644
--- a/src/messages/messages.proto
+++ b/src/messages/messages.proto
@@ -46,9 +46,9 @@ message Task {
required SlaveID slave_id = 5;
required TaskState state = 6;
repeated Resource resources = 7;
+ repeated TaskStatus statuses = 8;
}
-
// Describes a role, which are used to group frameworks for allocation
// decisions, depending on the allocation policy being used.
// The weight field can be used to indicate forms of priority.
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index 13cb418..bb98fce 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -1812,7 +1812,7 @@ void Slave::statusUpdate(const StatusUpdate& update, const UPID& pid)
stats.tasks[update.status().state()]++;
stats.validStatusUpdates++;
- executor->updateTaskState(status.task_id(), status.state());
+ executor->updateTaskState(status);
// Handle the task appropriately if it is terminated.
// TODO(vinod): Revisit these semantics when we disallow duplicate
@@ -3250,7 +3250,7 @@ void Executor::recoverTask(const TaskState& state)
// Read updates to get the latest state of the task.
foreach (const StatusUpdate& update, state.updates) {
- updateTaskState(state.id, update.status().state());
+ updateTaskState(update.status());
// Terminate the task if it received a terminal update.
// We ignore duplicate terminal updates by checking if
@@ -3271,10 +3271,16 @@ void Executor::recoverTask(const TaskState& state)
}
-void Executor::updateTaskState(const TaskID& taskId, mesos::TaskState state)
+void Executor::updateTaskState(const TaskStatus& status)
{
- if (launchedTasks.contains(taskId)) {
- launchedTasks[taskId]->set_state(state);
+ if (launchedTasks.contains(status.task_id())) {
+ Task* task = launchedTasks[status.task_id()];
+ // TODO(brenden): Consider wiping the `data` and `message` fields?
+ if (task->state() == status.state()) {
+ task->mutable_statuses()->RemoveLast();
+ }
+ task->add_statuses()->CopyFrom(status);
+ task->set_state(status.state());
}
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/slave/slave.hpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 68526f3..b39eaf4 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -366,7 +366,7 @@ struct Executor
void completeTask(const TaskID& taskId);
void checkpointTask(const TaskInfo& task);
void recoverTask(const state::TaskState& state);
- void updateTaskState(const TaskID& taskId, TaskState state);
+ void updateTaskState(const TaskStatus& status);
// Returns true if there are any queued/launched/terminated tasks.
bool incompleteTasks();
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/webui/master/static/framework.html
----------------------------------------------------------------------
diff --git a/src/webui/master/static/framework.html b/src/webui/master/static/framework.html
index 6e5cd9f..368f0f3 100644
--- a/src/webui/master/static/framework.html
+++ b/src/webui/master/static/framework.html
@@ -74,6 +74,10 @@
ng-click="selectColumn('active_tasks', 'state')">
State
</th>
+ <th ng-class="columnClass('active_tasks', 'start_time')"
+ ng-click="selectColumn('active_tasks', 'start_time')">
+ Started
+ </th>
<th ng-class="columnClass('active_tasks', 'host')"
ng-click="selectColumn('active_tasks', 'host')">
Host
@@ -91,6 +95,17 @@
<td>{{task.name}}</td>
<td>{{task.state | truncateMesosState}}</td>
<td>
+ <abbr title="{{task.start_time | isoDate}}">
+ {{task.start_time | relativeDate}}</abbr>
+ <button class="btn btn-mini btn-toggle"
+ clipboard
+ data-clipboard-text="{{task.start_time | isoDate}}"
+ tooltip="Copy start time"
+ tooltip-placement="right"
+ tooltip-trigger="clipboardhover">
+ </button>
+ </td>
+ <td>
<span data-ng-show="slaves[task.slave_id]">
{{slaves[task.slave_id].hostname}}
</span>
@@ -126,6 +141,14 @@
ng-click="selectColumn('completed_tasks', 'state')">
State
</th>
+ <th ng-class="columnClass('completed_tasks', 'start_time')"
+ ng-click="selectColumn('completed_tasks', 'start_time')">
+ Started
+ </th>
+ <th ng-class="columnClass('completed_tasks', 'finish_time')"
+ ng-click="selectColumn('completed_tasks', 'finish_time')">
+ Stopped
+ </th>
<th ng-class="columnClass('completed_tasks', 'host')"
ng-click="selectColumn('completed_tasks', 'host')">
Host
@@ -140,6 +163,28 @@
<td>{{task.name}}</td>
<td>{{task.state | truncateMesosState}}</td>
<td>
+ <abbr title="{{task.start_time | isoDate}}">
+ {{task.start_time | relativeDate}}</abbr>
+ <button class="btn btn-mini btn-toggle"
+ clipboard
+ data-clipboard-text="{{task.start_time | isoDate}}"
+ tooltip="Copy start time"
+ tooltip-placement="right"
+ tooltip-trigger="clipboardhover">
+ </button>
+ </td>
+ <td>
+ <abbr title="{{task.finish_time | isoDate}}">
+ {{task.finish_time | relativeDate}}</abbr>
+ <button class="btn btn-mini btn-toggle"
+ clipboard
+ data-clipboard-text="{{task.finish_time | isoDate}}"
+ tooltip="Copy finish time"
+ tooltip-placement="right"
+ tooltip-trigger="clipboardhover">
+ </button>
+ </td>
+ <td>
<a data-ng-show="slaves[task.slave_id]"
href="#/slaves/{{task.slave_id}}/frameworks/{{task.framework_id}}/executors/{{task.executor_id}}">
{{slaves[task.slave_id].hostname}}
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/webui/master/static/frameworks.html
----------------------------------------------------------------------
diff --git a/src/webui/master/static/frameworks.html b/src/webui/master/static/frameworks.html
index 7c243d4..6cf5194 100644
--- a/src/webui/master/static/frameworks.html
+++ b/src/webui/master/static/frameworks.html
@@ -98,4 +98,4 @@
</tbody>
</table>
</div>
-</div>
\ No newline at end of file
+</div>
http://git-wip-us.apache.org/repos/asf/mesos/blob/480f8a71/src/webui/master/static/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/controllers.js b/src/webui/master/static/js/controllers.js
index 8f65679..6f74859 100644
--- a/src/webui/master/static/js/controllers.js
+++ b/src/webui/master/static/js/controllers.js
@@ -221,11 +221,15 @@
if (!task.executor_id) {
task.executor_id = task.id;
}
+ task.start_time = task.statuses[0].timestamp * 1000
+ task.finish_time = task.statuses[task.statuses.length - 1].timestamp * 1000
});
_.each(framework.completed_tasks, function(task) {
if (!task.executor_id) {
task.executor_id = task.id;
}
+ task.start_time = task.statuses[0].timestamp * 1000
+ task.finish_time = task.statuses[task.statuses.length - 1].timestamp * 1000
});
});