var message = v[12];
var type = "";
+ var node = "";
if (v11 !== "") {
+ if (!taskState.hasOwnProperty(v11)) {
+ taskState[v11] = {};
+ }
+
if (/^stderr /.test(message)) {
message = message.substr(7);
if (/^crunchstat: /.test(message)) {
}
} else {
if (/^success /.test(message)) {
- taskState[v11] = "success";
+ taskState[v11].outcome = "success";
+ taskState.success_count += 1;
}
else if (/^failure /.test(message)) {
- taskState[v11] = "failure";
+ taskState[v11].outcome = "failure";
+ taskState.failure_count += 1;
+ }
+ else {
+ var child = message.match(/^child \d+ started on (.*)/);
+ if (child != null) {
+ taskState[v11].node = child[1];
+ for (var i in logViewer.items) {
+ if (i > 0) {
+ var val = logViewer.items[i].values();
+ if (val.taskid === v11) {
+ val.node = child[1];
+ logViewer.items[i].values(val);
+ }
+ }
+ }
+ }
}
type = "task-dispatch";
}
+ node = taskState[v11].node;
} else {
if (/^status: /.test(message)) {
type = "job-status";
logViewer.add({
id: logViewer.items.length,
+ ts: ts,
timestamp: ts.toLocaleDateString() + " " + ts.toLocaleTimeString(),
taskid: v11,
+ node: node,
message: message,
type: type
});
logViewer.update();
}
-function sortByTaskThenId(a, b, opt) {
+function sortById(a, b, opt) {
a = a.values();
b = b.values();
- if (a["taskid"] === "" && b["taskid"] !== "") {
+ if (a["id"] > b["id"]) {
+ return 1;
+ }
+ if (a["id"] < b["id"]) {
+ return -1;
+ }
+ return 0;
+}
+
+function sortByTask(a, b, opt) {
+ var aa = a.values();
+ var bb = b.values();
+
+ if (aa["taskid"] === "" && bb["taskid"] !== "") {
return -1;
}
- if (a["taskid"] !== "" && b["taskid"] === "") {
+ if (aa["taskid"] !== "" && bb["taskid"] === "") {
return 1;
}
- if (a["taskid"] !== "" && b["taskid"] !== "") {
- if (a["taskid"] > b["taskid"]) {
+ if (aa["taskid"] !== "" && bb["taskid"] !== "") {
+ if (aa["taskid"] > bb["taskid"]) {
return 1;
}
- if (a["taskid"] < b["taskid"]) {
+ if (aa["taskid"] < bb["taskid"]) {
return -1;
}
}
- if (a["id"] > b["id"]) {
+ return sortById(a, b, opt);
+}
+
+function sortByNode(a, b, opt) {
+ var aa = a.values();
+ var bb = b.values();
+
+ if (aa["node"] === "" && bb["node"] !== "") {
+ return -1;
+ }
+ if (aa["node"] !== "" && bb["node"] === "") {
return 1;
}
- if (a["id"] < b["id"]) {
- return -1;
+
+ if (aa["node"] !== "" && bb["node"] !== "") {
+ if (aa["node"] > bb["node"]) {
+ return 1;
+ }
+ if (aa["node"] < bb["node"]) {
+ return -1;
+ }
+ }
+
+ return sortById(a, b, opt);
+}
+
+
+function dumbPluralize(n, s, p) {
+ if (typeof p === 'undefined') {
+ p = "s";
+ }
+ if (n == 0 || n > 1) {
+ return (s + p);
+ } else {
+ return s;
}
- return 0;
}
+
+function generateJobOverview(id, logViewer, taskState) {
+ var html = "";
+
+ var first = logViewer.items[1];
+ var last = logViewer.items[logViewer.items.length-1];
+
+ {
+ html += "<div>";
+ html += "Started at " + first.values().timestamp;
+
+ var duration = (last.values().ts.getTime() - first.values().ts.getTime()) / 1000;
+
+ var hours = 0;
+ var minutes = 0;
+ var seconds;
+
+ if (duration >= 3600) {
+ hours = Math.floor(duration / 3600);
+ duration -= (hours * 3600);
+ }
+ if (duration >= 60) {
+ minutes = Math.floor(duration / 60);
+ duration -= (minutes * 60);
+ }
+ seconds = duration;
+
+ var tcount = taskState.success_count + taskState.failure_count;
+
+ html += ". " + tcount + dumbPluralize(tcount, " task") + " completed in ";
+ if (hours > 0) {
+ html += hours + dumbPluralize(hours, " hour");
+ }
+ if (minutes > 0) {
+ html += " " + minutes + dumbPluralize(minutes, " minute");
+ }
+ if (seconds > 0) {
+ html += " " + seconds + dumbPluralize(seconds, " second");
+ }
+ html += ". " + taskState.success_count + dumbPluralize(taskState.success_count, " success", "es");
+ html += ", " + taskState.failure_count + dumbPluralize(taskState.failure_count, " failure");
+
+ html += ". Completed at " + last.values().timestamp;
+ html += "</div>";
+ }
+
+ $(id).html(html);
+}
\ No newline at end of file
page: 10000,
});
-var taskState = {};
+var taskState = {"success_count": 0, "failure_count": 0};
var makeFilter = function() {
var pass = [];
var v = false;
if (item.values().taskid !== "") {
for (a in pass) {
- if (pass[a] == "successful-tasks" && taskState[item.values().taskid] == "success") { v = true; }
- if (pass[a] == "failed-tasks" && taskState[item.values().taskid] == "failure") { v = true; }
+ if (pass[a] == "successful-tasks" && taskState[item.values().taskid].outcome == "success") { v = true; }
+ if (pass[a] == "failed-tasks" && taskState[item.values().taskid].outcome == "failure") { v = true; }
}
} else {
v = true;
logViewer.filter();
addToLogViewer(logViewer, data.split("\n"), taskState);
logViewer.filter(makeFilter());
+ generateJobOverview("#log-viewer-overview", logViewer, taskState);
$("#logloadspinner").detach();
});
<% else %>
});
$("#sort-by-time").on("change", function() {
- logViewer.sort("id");
+ logViewer.sort("id", {sortFunction: sortById});
});
$("#sort-by-task").on("change", function() {
- logViewer.sort("taskid", {sortFunction: sortByTaskThenId});
+ logViewer.sort("taskid", {sortFunction: sortByTask});
+});
+
+$("#sort-by-node").on("change", function() {
+ logViewer.sort("node", {sortFunction: sortByNode});
});
})();
<div id="log-viewer">
- <div class="radio-inline">
- <label><input id="sort-by-time" type="radio" name="sort-radio" checked> Sort by time</label>
- </div>
- <div class="radio-inline">
- <label><input id="sort-by-task" type="radio" name="sort-radio" > Sort by task</label>
- </div>
+ <h3>Overview</h3>
+ <div id="log-viewer-overview"></div>
- <div class="checkbox-inline">
- <label><input id="show-crunch" type="checkbox" checked="true" class="toggle-filter"> Show crunch output</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-job-status" type="checkbox" checked="true" class="toggle-filter"> Show job status</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-task-dispatch" type="checkbox" checked="true" class="toggle-filter"> Show task dispatch</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-task-output" type="checkbox" checked="true" class="toggle-filter"> Show task output</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-crunchstat" type="checkbox" checked="true" class="toggle-filter"> Show compute usage</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-successful-tasks" type="checkbox" checked="true" class="toggle-filter"> Show successful tasks</label>
- </div>
- <div class="checkbox-inline">
- <label><input id="show-failed-tasks" type="checkbox" checked="true" class="toggle-filter"> Show failed tasks</label>
- </div>
-
-<div class="pull-right">
+ <div class="h3">Log
+
+<span class="pull-right">
<button id="filter-all" class="btn">
Select all
</button>
<button id="filter-none" class="btn">
Select none
</button>
+</span>
</div>
+ <div>
+ <div class="radio-inline log-viewer-button" style="margin-left: 10px">
+ <label><input id="sort-by-time" type="radio" name="sort-radio" checked> Sort by time</label>
+ </div>
+ <div class="radio-inline log-viewer-button">
+ <label><input id="sort-by-node" type="radio" name="sort-radio" > Sort by node</label>
+ </div>
+
+ <div class="radio-inline log-viewer-button">
+ <label><input id="sort-by-task" type="radio" name="sort-radio" > Sort by task</label>
+ </div>
+ </div>
+
+ <div>
+ <div class="checkbox-inline log-viewer-button" style="margin-left: 10px">
+ <label><input id="show-crunch" type="checkbox" checked="true" class="toggle-filter"> Show crunch output</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-job-status" type="checkbox" checked="true" class="toggle-filter"> Show job status</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-task-dispatch" type="checkbox" checked="true" class="toggle-filter"> Show task dispatch</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-task-output" type="checkbox" checked="true" class="toggle-filter"> Show task output</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-crunchstat" type="checkbox" checked="true" class="toggle-filter"> Show compute usage</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-successful-tasks" type="checkbox" checked="true" class="toggle-filter"> Show successful tasks</label>
+ </div>
+ <div class="checkbox-inline log-viewer-button">
+ <label><input id="show-failed-tasks" type="checkbox" checked="true" class="toggle-filter"> Show failed tasks</label>
+ </div>
+ </div>
+
<table class="log-viewer-table">
<thead>
<tr>
<th class="id" data-sort="id"></th>
<th class="timestamp" data-sort="timestamp">Timestamp</th>
+ <th class="node" data-sort="taskid">Node</th>
<th class="type" data-sort="type">Log type</th>
<th class="taskid" data-sort="taskid">Task</th>
<th class="message" data-sort="message">Message</th>
<tr>
<td class="id"></td>
<td class="timestamp"></td>
+ <td class="node"></td>
<td class="type"></td>
<td class="taskid"></td>
<td class="message"></td>