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 <[email protected]> Authored: Tue Oct 1 16:21:44 2013 -0700 Committer: Brenden Matthews <[email protected]> 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 }); });
