https://bugs.webkit.org/show_bug.cgi?id=143617
Reviewed by Chris Dumez.
* public/api/analysis-tasks.php:
(fetch_and_push_bugs_to_tasks): Added total and finished numbers of build requests associated
with the fetched analysis tasks as buildRequestCount and finishedBuildRequestCount respectively.
* public/v2/analysis.js:
(App.AnalysisTask.formattedCreatedAt): Added.
(App.AnalysisTask._addLeadingZero): Added.
(App.AnalysisTask.buildRequestCount): Added.
(App.AnalysisTask.finishedBuildRequestCount): Added.
(App.AnalysisTask.statusLabel): Added. Status total and finished numbers of build requests.
(App.AnalysisTask.testGroups):
(App.AnalysisTask.triggerable):
(App.AnalysisTask.label):
* public/v2/app.css: Tweaked style rules for the analysis page.
* public/v2/app.js:
(App.buildPopup): Sort the list of platforms by name.
(App.AnalysisRoute.model): Sort the list of analysis tasks by the order they are created.
(App.AnalysisTaskController._fetchedManifest): Added elementId to associate bug tracker names
such as "Bugzilla" with the corresponding text field.
* public/v2/index.html: Added a bunch of columns to the analysis page and also wrapped the table
showing A/B testing results in a div with overflow: scroll so that it always leaves enough space
for the accompanying graph.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@182641
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-04-10 Ryosuke Niwa <rniwa@webkit.org>
+
+ Make the analysis page more useful
+ https://bugs.webkit.org/show_bug.cgi?id=143617
+
+ Reviewed by Chris Dumez.
+
+ * public/api/analysis-tasks.php:
+ (fetch_and_push_bugs_to_tasks): Added total and finished numbers of build requests associated
+ with the fetched analysis tasks as buildRequestCount and finishedBuildRequestCount respectively.
+ * public/v2/analysis.js:
+ (App.AnalysisTask.formattedCreatedAt): Added.
+ (App.AnalysisTask._addLeadingZero): Added.
+ (App.AnalysisTask.buildRequestCount): Added.
+ (App.AnalysisTask.finishedBuildRequestCount): Added.
+ (App.AnalysisTask.statusLabel): Added. Status total and finished numbers of build requests.
+ (App.AnalysisTask.testGroups):
+ (App.AnalysisTask.triggerable):
+ (App.AnalysisTask.label):
+
+ * public/v2/app.css: Tweaked style rules for the analysis page.
+
+ * public/v2/app.js:
+ (App.buildPopup): Sort the list of platforms by name.
+ (App.AnalysisRoute.model): Sort the list of analysis tasks by the order they are created.
+ (App.AnalysisTaskController._fetchedManifest): Added elementId to associate bug tracker names
+ such as "Bugzilla" with the corresponding text field.
+
+ * public/v2/index.html: Added a bunch of columns to the analysis page and also wrapped the table
+ showing A/B testing results in a div with overflow: scroll so that it always leaves enough space
+ for the accompanying graph.
+
2015-04-09 Ryosuke Niwa <rniwa@webkit.org>
Perf dashboard should automatically select ranges for A/B testing
array_push($associated_task['bugs'], $bug['id']);
}
+ $task_build_counts = $db->query_and_fetch_all('SELECT
+ testgroup_task AS "task",
+ count(testgroup_id) as "total",
+ sum(case when request_status = \'failed\' or request_status = \'completed\' then 1 else 0 end) as "finished"
+ FROM analysis_test_groups, build_requests
+ WHERE request_group = testgroup_id AND testgroup_task = ANY($1) GROUP BY testgroup_task',
+ array('{' . implode(', ', $task_ids) . '}'));
+ if (!is_array($task_build_counts))
+ exit_with_error('FailedToFetchTestGroups');
+
+ foreach ($task_build_counts as $build_count) {
+ $task = &$task_by_id[$build_count['task']];
+ $task['buildRequestCount'] = $build_count['total'];
+ $task['finishedBuildRequestCount'] = $build_count['finished'];
+ }
+
return $bugs;
}
App.AnalysisTask = App.NameLabelModel.extend({
author: DS.attr('string'),
createdAt: DS.attr('date'),
+ formattedCreatedAt: function () {
+ var format = d3.time.format("%Y-%m-%d");
+ return format(this.get('createdAt'));
+ }.property('createdAt'),
platform: DS.belongsTo('platform'),
metric: DS.belongsTo('metric'),
startRun: DS.attr('number'),
endRun: DS.attr('number'),
bugs: DS.hasMany('bugs'),
- testGroups: function (key, value, oldValue) {
+ buildRequestCount: DS.attr('number'),
+ finishedBuildRequestCount: DS.attr('number'),
+ statusLabel: function ()
+ {
+ var total = this.get('buildRequestCount');
+ var finished = this.get('finishedBuildRequestCount');
+ if (!total)
+ return 'Empty';
+ if (total != finished)
+ return finished + ' out of ' + total;
+ return 'Done';
+ }.property('buildRequestCount', 'finishedBuildRequestCount'),
+ testGroups: function (key, value, oldValue)
+ {
return this.store.find('testGroup', {task: this.get('id')});
}.property(),
- triggerable: function () {
+ triggerable: function ()
+ {
return this.store.find('triggerable', {task: this.get('id')}).then(function (triggerables) {
return triggerables.objectAt(0);
}, function (error) {
return null;
});
}.property(),
- label: function () {
+ label: function ()
+ {
var label = this.get('name');
var bugs = this.get('bugs').map(function (bug) { return bug.get('label'); }).join(' / ');
return bugs ? label + ' (' + bugs + ')' : label;
.popup li .label {
display: block;
+ font-size: 0.8rem;
max-width: 15rem;
text-overflow: ellipsis;
overflow: hidden;
}
#analysis-tasks,
-.analysis-group > table {
+.analysis-group table {
border: solid 0px #999;
border-collapse: collapse;
}
#analysis-tasks thead,
-.analysis-group > table thead {
+.analysis-group table thead {
color: #c93;
}
#analysis-tasks th,
-.analysis-group > table th {
+.analysis-group table th {
font-weight: normal;
}
#analysis-tasks td,
#analysis-tasks th,
-.analysis-group > table td,
-.analysis-group > table th {
+.analysis-group table td,
+.analysis-group table th {
padding: 0.2rem 0.5rem;
}
+#analysis-tasks .status,
+#analysis-tasks .author,
+#analysis-tasks .created-at,
+#analysis-tasks .platform-name {
+ white-space: nowrap;
+}
+
+#analysis-tasks .test-name {
+}
+
#analysis-tasks tbody td,
#analysis-tasks tbody th,
-.analysis-group > table tbody td,
-.analysis-group > table tbody th {
+.analysis-group table tbody td,
+.analysis-group table tbody th {
border-top: solid 1px #ddd;
}
-.analysis-group .results .summary td {
+.analysis-group table .summary td {
vertical-align: top;
}
-.analysis-group .results thead td {
+.analysis-group table thead td {
text-align: center;
}
-.analysis-group .results .config-letter,
-.analysis-group .results .summary {
+.analysis-group table .config-letter,
+.analysis-group table .summary {
cursor: pointer;
}
display: none;
}
-.analysis-group .results {
+.analysis-group .table-container {
margin: 0.5rem;
- margin-right: 20rem;
+ margin-right: 19rem;
+ overflow: scroll;
}
.analysis-group .reference-chart {
App.buildPopup = function(store, action, position)
{
return App.Manifest.fetch(store).then(function () {
- return App.Manifest.get('platforms').map(function (platform) {
+ return App.Manifest.get('platforms').sortBy('label').map(function (platform) {
return App.PlatformProxyForPopup.create({content: platform,
action: action, position: position});
});
App.AnalysisRoute = Ember.Route.extend({
model: function () {
return this.store.findAll('analysisTask').then(function (tasks) {
- return Ember.Object.create({'tasks': tasks});
+ return Ember.Object.create({'tasks': tasks.sortBy('createdAt').toArray().reverse()});
});
},
});
this.set('bugTrackers', App.Manifest.get('bugTrackers').map(function (bugTracker) {
var bugNumber = trackerIdToBugNumber[bugTracker.get('id')];
return Ember.ObjectProxy.create({
+ elementId: 'bug-' + bugTracker.get('id'),
content: bugTracker,
bugNumber: bugNumber,
editedBugNumber: bugNumber,
<table id="analysis-tasks">
<thead>
<tr>
- <td>ID</td>
<td>Name</td>
+ <td>Status</td>
+ <td>Author</td>
<td>Created at</td>
+ <td>Platform</td>
+ <td>Test</td>
</tr>
</thead>
<tbody>
{{#each model.tasks}}
<tr>
- <td>{{#link-to 'analysisTask' id}}{{id}}{{/link-to}}</td>
- <td>{{name}}</td>
- <td>{{createdAt}}</td>
+ <td class="task-name">{{#link-to 'analysisTask' id}}{{name}}{{/link-to}}</td>
+ <td class="status">{{statusLabel}}</td>
+ <td class="author">{{author}}</td>
+ <td class="created-at">{{formattedCreatedAt}}</td>
+ <td class="platform-name">{{platform.label}}</td>
+ <td class="test-name">{{metric.fullName}}</td>
</tr>
{{/each}}
</tbody>
<tbody>
{{#each bugTrackers}}
<tr>
- <th>{{label}}</th>
+ <th><label {{bind-attr for=elementId}}>{{label}}</label></th>
<td>
<form {{action "associateBug" this editedBugNumber on="submit"}}>
- {{input type=text value=editedBugNumber}}
+ {{input id=elementId type=text value=editedBugNumber}}
</form>
</td>
</tr>
<script type="text/x-handlebars" data-template-name="testGroup">
<section class="analysis-group">
<h1>{{name}}</h1>
- <table class="results">
- <thead>
- <tr>
- <td colspan="2">Configuration</td>
- {{#each repositories}}
- <td>{{name}}</td>
- {{/each}}
- <td>Results</td>
- <td>Status</td>
- </tr>
- </thead>
- {{#each configurations}}
- <tbody {{bind-attr class="showRequestList::hideRequests"}}>
- <tr class="summary" {{action toggleShowRequestList this}}>
- <td class="config-letter" colspan="2">{{summary.configLetter}}</td>
- {{#with summary}}
- {{partial "testGroupRow"}}
- {{/with}}
+ <div class="table-container">
+ <table class="results">
+ <thead>
+ <tr>
+ <td colspan="2">Configuration</td>
+ {{#each repositories}}
+ <td>{{name}}</td>
+ {{/each}}
+ <td>Results</td>
+ <td>Status</td>
</tr>
- {{#each requests}}
- <tr class="request">
+ </thead>
+ {{#each configurations}}
+ <tbody {{bind-attr class="showRequestList::hideRequests"}}>
+ <tr class="summary" {{action toggleShowRequestList this}}>
+ <td class="config-letter" colspan="2">{{summary.configLetter}}</td>
+ {{#with summary}}
+ {{partial "testGroupRow"}}
+ {{/with}}
+ </tr>
+ {{#each requests}}
+ <tr class="request">
+ {{#with ../this}}
+ <td class="config-letter" {{action toggleShowRequestList this}}></td>
+ {{/with}}
+ <td>Run {{orderLabel}}</td>
+ {{partial "testGroupRow"}}
+ </tr>
+ {{/each}}
+ </tbody>
+ {{/each}}
+ {{#each comparisons}}
+ <tbody>
+ <tr>
+ <td colspan="2">{{label}}</td>
{{#with ../this}}
- <td class="config-letter" {{action toggleShowRequestList this}}></td>
+ {{#each repositories}}
+ <td></td>
+ {{/each}}
{{/with}}
- <td>Run {{orderLabel}}</td>
- {{partial "testGroupRow"}}
+ <td colspan="2">{{result}}</td>
</tr>
- {{/each}}
- </tbody>
- {{/each}}
- {{#each comparisons}}
- <tbody>
- <tr>
- <td colspan="2">{{label}}</td>
- {{#with ../this}}
- {{#each repositories}}
- <td></td>
- {{/each}}
- {{/with}}
- <td colspan="2">{{result}}</td>
- </tr>
- </tbody>
- {{/each}}
- </table>
+ </tbody>
+ {{/each}}
+ </table>
+ </div>
<div class="reference-chart">
{{#if referenceChart}}
{{interactive-chart