Chromium Code Reviews| Index: appengine/swarming/elements/res/imp/botpage/bot-page-data.html |
| diff --git a/appengine/swarming/elements/res/imp/botpage/bot-page-data.html b/appengine/swarming/elements/res/imp/botpage/bot-page-data.html |
| index f0e8e0a981ad649b6a8ceda86bcdf830be8a37cb..3a395d5365753edf328ddf91e20f2589ebbb0b9d 100644 |
| --- a/appengine/swarming/elements/res/imp/botpage/bot-page-data.html |
| +++ b/appengine/swarming/elements/res/imp/botpage/bot-page-data.html |
| @@ -32,17 +32,25 @@ |
| --> |
| -<link rel="import" href="/res/imp/common/common-behavior.html"> |
| +<link rel="import" href="bot-page-shared-behavior.html"> |
| <dom-module id="bot-page-data"> |
| <script> |
| (function(){ |
| + // Time to wait before requesting a new bot. This is to allow a user to |
| + // type in a name and not have it make one set of requests for each |
| + // keystroke. |
| + var BOT_ID_DEBOUNCE_MS = 400; |
| + var lastRequest; |
| + |
| + var BOT_TIMES = ["first_seen_ts", "last_seen_ts"]; |
| + var TASK_TIMES = ["started_ts", "completed_ts", "abandoned_ts", "modified_ts"]; |
| Polymer({ |
| is: 'bot-page-data', |
| behaviors: [ |
| - SwarmingBehaviors.CommonBehavior, |
| + SwarmingBehaviors.BotPageBehavior, |
| ], |
| properties: { |
| @@ -106,25 +114,65 @@ |
| request: function(){ |
| if (!this.bot_id || !this.auth_headers) { |
| - console.log("bot_id and auth_headers can't be empty"); |
| return; |
| } |
| - var baseUrl = "/_ah/api/swarming/v1/bot/"+this.bot_id; |
| - this._getJsonAsync("_bot", baseUrl + "/get", |
| - "_busy1", this.auth_headers); |
| - // We limit the fields on these two queries to make them faster. |
| - this._getJsonAsync("_events", |
| - baseUrl + "/events?fields=items(event_type%2Cmessage%2Cquarantined%2Ctask_id%2Cts%2Cversion)", |
| - "_busy2", this.auth_headers); |
| - this._getJsonAsync("_tasks", |
| - baseUrl + "/tasks?fields=items(abandoned_ts%2Cbot_version%2Ccompleted_ts%2Cduration%2Cexit_code%2Cfailure%2Cinternal_failure%2Cmodified_ts%2Cname%2Cstarted_ts%2Cstate%2Ctask_id%2Ctry_number)", |
| - "_busy3", this.auth_headers); |
| + if (lastRequest) { |
| + clearTimeout(lastRequest); |
| + } |
| + |
| + lastRequest = setTimeout(function(){ |
|
stephana
2016/09/01 15:16:18
IMO the Polymer async method is preferrable, i.e.
kjlubick
2016/09/01 17:24:08
I did not know about Polymer's async. Thanks!
|
| + lastRequest = undefined; |
| + var baseUrl = "/_ah/api/swarming/v1/bot/"+this.bot_id; |
| + this._getJsonAsync("_bot", baseUrl + "/get", |
| + "_busy1", this.auth_headers); |
| + // We limit the fields on these two queries to make them faster. |
| + this._getJsonAsync("_events", |
| + baseUrl + "/events?fields=items(event_type%2Cmessage%2Cquarantined%2Ctask_id%2Cts%2Cversion)", |
| + "_busy2", this.auth_headers); |
| + this._getJsonAsync("_tasks", |
| + baseUrl + "/tasks?fields=items(abandoned_ts%2Cbot_version%2Ccompleted_ts%2Cduration%2Cexit_code%2Cfailure%2Cinternal_failure%2Cmodified_ts%2Cname%2Cstarted_ts%2Cstate%2Ctask_id%2Ctry_number)", |
| + "_busy3", this.auth_headers); |
| + }.bind(this), BOT_ID_DEBOUNCE_MS); |
| + |
| }, |
| _parseBot: function(bot) { |
| if (!bot) { |
| return {}; |
| } |
| + // Do any preprocessing here |
| + bot.state = bot.state || "{}"; |
| + bot.state = JSON.parse(bot.state); |
| + |
| + // get the disks in an easier to deal with format, sorted by size. |
| + var disks = bot.state.disks || {}; |
| + var keys = Object.keys(disks); |
| + if (!keys.length) { |
| + bot.disks = [{"id": "unknown", "mb": 0}]; |
| + } else { |
| + bot.disks = []; |
| + for (var i = 0; i < keys.length; i++) { |
| + bot.disks.push({"id":keys[i], "mb":disks[keys[i]].free_mb}); |
| + } |
| + // Sort these so the biggest disk comes first. |
| + bot.disks.sort(function(a, b) { |
| + return b.mb - a.mb; |
| + }); |
| + } |
| + |
| + // Date.toString() looks like "Mon Aug 29 2016 09:03:41 GMT-0400 (EDT)" |
| + // we want to extract the time zone part and append it to the |
| + // locale time. |
|
stephana
2016/09/01 15:16:18
This seems something that the Date object should p
kjlubick
2016/09/01 17:24:08
The Date Object will only give me the TimeZoneOffs
|
| + var str = (new Date()).toString(); |
| + var timeZone = str.substring(str.indexOf("(")) |
| + |
| + BOT_TIMES.forEach(function(time) { |
| + if (bot[time]) { |
| + bot[time] = new Date(bot[time]); |
| + var locale = bot[time].toLocaleString(); |
| + bot["human_"+time] = locale + " " + timeZone; |
| + } |
| + }); |
| return bot; |
| }, |
| @@ -132,14 +180,72 @@ |
| if (!events || !events.items) { |
| return []; |
| } |
| - return events.items; |
| + var events = events.items; |
| + var str = (new Date()).toString(); |
| + var timeZone = str.substring(str.indexOf("(")) |
| + events.forEach(function(event){ |
| + // Do any preprocessing here |
| + if (event.ts) { |
| + event.ts = new Date(event.ts); |
| + var locale = event.ts.toLocaleString(); |
| + event.human_ts = locale + " " + timeZone; |
| + } |
| + }); |
| + |
| + // Sort the most recent events first. |
| + events.sort(function(a,b) { |
| + return b.ts - a.ts; |
| + }); |
| + |
| + return events; |
| }, |
| _parseTasks: function(tasks) { |
| if (!tasks || !tasks.items) { |
| return []; |
| } |
| - return tasks.items; |
| + var tasks = tasks.items; |
| + |
| + // Date.toString() looks like "Mon Aug 29 2016 09:03:41 GMT-0400 (EDT)" |
| + // we want to extract the time zone part and append it to the |
| + // locale time. |
| + var str = (new Date()).toString(); |
| + var timeZone = str.substring(str.indexOf("(")) |
|
stephana
2016/09/01 15:16:18
Same as above. Instead of copying the code there s
kjlubick
2016/09/01 17:24:08
Done. Created formatDate();
|
| + tasks.forEach(function(task){ |
| + // Do any preprocessing here |
| + TASK_TIMES.forEach(function(time) { |
| + if (task[time]) { |
| + task[time] = new Date(task[time]); |
| + var locale = task[time].toLocaleString(); |
| + task["human_"+time] = locale + " " + timeZone; |
| + } |
| + }); |
| + |
| + |
| + if (task.duration) { |
| + task.human_duration = sk.human.strDuration(task.duration) || "0s"; |
| + } else { |
| + var end = task.completed_ts || task.abandoned_ts || task.modified_ts || new Date(); |
| + task.human_duration = this._timeDiffExact(task.started_ts, end); |
| + } |
| + |
| + task.state = task.state || "UNKNOWN"; |
| + if (task.state === "COMPLETED") { |
| + if (task.failure) { |
| + task.state = "FAILURE"; |
| + } else { |
| + task.state = "SUCCESS"; |
| + } |
| + } |
| + |
| + }.bind(this)); |
| + |
| + // Sort the most recent tasks first. |
| + tasks.sort(function(a,b) { |
| + return b.started_ts - a.started_ts; |
| + }); |
| + |
| + return tasks; |
| } |
| }); |