Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: Tools/GardeningServer/ui/ct-failure-analyzer.html

Issue 498523002: [Sheriff-o-matic] Use likely_revisions instead of first_failing/last_passing (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 <!-- 1 <!--
2 Copyright 2014 The Chromium Authors. All rights reserved. 2 Copyright 2014 The Chromium Authors. All rights reserved.
3 Use of this source code is governed by a BSD-style license that can be 3 Use of this source code is governed by a BSD-style license that can be
4 found in the LICENSE file. 4 found in the LICENSE file.
5 --> 5 -->
6 <link href="../model/ct-builder-revisions.html" rel="import"> 6 <link href="../model/ct-builder-revisions.html" rel="import">
7 7
8 <link rel="import" href="../lib/net.html"> 8 <link rel="import" href="../lib/net.html">
9 <link rel="import" href="../model/ct-failure.html"> 9 <link rel="import" href="../model/ct-failure.html">
10 <link rel="import" href="../model/ct-failure-group.html"> 10 <link rel="import" href="../model/ct-failure-group.html">
(...skipping 17 matching lines...) Expand all
28 "https://build.chromium.org/p/chromium.chrome", 28 "https://build.chromium.org/p/chromium.chrome",
29 "https://build.chromium.org/p/chromium.chromiumos", 29 "https://build.chromium.org/p/chromium.chromiumos",
30 "https://build.chromium.org/p/chromium.gpu", 30 "https://build.chromium.org/p/chromium.gpu",
31 "https://build.chromium.org/p/chromium.linux", 31 "https://build.chromium.org/p/chromium.linux",
32 "https://build.chromium.org/p/chromium.mac", 32 "https://build.chromium.org/p/chromium.mac",
33 "https://build.chromium.org/p/chromium.memory", 33 "https://build.chromium.org/p/chromium.memory",
34 "https://build.chromium.org/p/chromium.win" 34 "https://build.chromium.org/p/chromium.win"
35 ], 35 ],
36 }, 36 },
37 37
38 _failureListComparator: function(tree, a, b) { 38 _failureByTreeListComparator: function(tree, a, b) {
39 if (tree === undefined) 39 if (tree === undefined)
40 tree = 'chromium'; 40 tree = 'chromium';
41 41
42 var rev_a = a.failures[0].firstFailingRevisions; 42 if (!a.revisions || !a.revisions.length) {
43 var rev_b = b.failures[0].firstFailingRevisions; 43 if (!a.revisions || !b.revisions.length)
44
45 // Handle missing revision.
46 if (!rev_a) {
47 if (!rev_b) {
48 return 0; 44 return 0;
49 }
50 return -1; 45 return -1;
51 } else if (!rev_b) { 46 } else if (!b.revisions || !b.revisions.length) {
52 return 1; 47 return 1;
53 } 48 }
54 49
55 // Prioritize the tree's revision. 50 // At this point |a.revisions| and |b.revisions| are sorted lists of
56 if (rev_a[tree] != rev_b[tree]) 51 // revisions of the form '<tree>:<revision>', where <tree> is not
57 return rev_b[tree] - rev_a[tree]; 52 // necessarily |tree|. Get the latest revision, and favor those related
53 // to |tree|.
54 // FIXME: Sort by timestamp of the last (or first?) commit.
55 var _getLatestRevisionForTree = function(revisions) {
56 var i = 0;
57 var rev = revisions[revisions.length - 1 - i];
ojan 2014/08/25 18:09:40 Nit: I'd find this easier to read if you started w
Mathieu 2014/08/26 15:47:40 Acknowledged.
58 while (!rev.startsWith(tree)) {
ojan 2014/08/25 18:09:40 Nit: Lets check startsWith(tree + ':') to avoid is
Mathieu 2014/08/26 15:47:40 Acknowledged.
59 i++;
60 rev = revisions[revisions.length - 1 - i];
61 }
62 return rev;
63 };
64 var rev_a = _getLatestRevisionForTree(a.revisions, tree);
65 var rev_b = _getLatestRevisionForTree(b.revisions, tree);
58 66
59 // Compare other revisions in alphabetical order. 67 // Extract the <tree> and <revision> parts.
60 var keys = Object.keys(rev_a).sort(); 68 var a_split = rev_a.split(':');
61 for (var i = 0; i < keys.length; i++) { 69 var a_tree = a_split[0];
62 if (rev_a[keys[i]] != rev_b[keys[i]]) 70 var a_id = a_split[1];
63 return rev_b[keys[i]] - rev_a[keys[i]]; 71
72 var b_split = rev_b.split(':');
73 var b_tree = b_split[0];
74 var b_id = b_split[1];
75
76 // If trees mismatch, favor the one matching with |tree|. If none equal
77 // |tree|, b is favored.
78 if (a_tree != b_tree)
79 return b_tree == tree ? 1 : -1;
80
81 if (rev_a == rev_b) {
ojan 2014/08/25 18:09:40 Can we move this check right after line 65? I thin
Mathieu 2014/08/26 15:47:40 Acknowledged.
82 // In case of tree-revision equality, try a fallback.
ojan 2014/08/25 18:09:40 This comment is a little confusing. Would be more
Mathieu 2014/08/26 15:47:40 Acknowledged.
83 var a_last = a.revisions.last();
84 var b_last = b.revisions.last();
85 if (a_last == b_last)
86 return 0;
87 return a_last < b_last ? 1 : -1;
64 } 88 }
65 return 0; 89
90 return b_id == a_id ? 0 : (b_id > a_id) ? 1 : -1;
ojan 2014/08/25 18:09:41 Can this just be the following? return b_id - a_id
Mathieu 2014/08/26 15:47:40 Acknowledged.
Mathieu 2014/08/26 15:47:40 Acknowledged.
66 }, 91 },
67 92
68 update: function() { 93 update: function() {
69 var annotationPromise = CTFailureGroup.fetchAnnotations(); 94 var annotationPromise = CTFailureGroup.fetchAnnotations();
70 net.json('http://sheriff-o-matic.appspot.com/alerts').then(function(data ) { 95 net.json('http://sheriff-o-matic.appspot.com/alerts').then(function(data ) {
71 annotationPromise.then(function(annotations) { 96 annotationPromise.then(function(annotations) {
72 // FIXME: Don't special-case the blink master. 97 // FIXME: Don't special-case the blink master.
73 this.builderLatestRevisions = new CTBuilderRevisions(data.latest_bui lder_info['chromium.webkit']); 98 this.builderLatestRevisions = new CTBuilderRevisions(data.latest_bui lder_info['chromium.webkit']);
74 this.failures = {}; 99 this.failures = {};
75 this.lastUpdateDate = new Date(data.date * 1000); 100 this.lastUpdateDate = new Date(data.date * 1000);
76 data.range_groups.forEach(function(group) { 101 // Update |failures| with the appropriate CTFailureGroup's for each tree.
77 this._processFailuresForGroup(group, data.alerts, annotations); 102 data.range_groups.forEach(function(rangeGroup) {
103 this._processFailuresForRangeGroup(rangeGroup, data.alerts, annota tions);
78 }.bind(this)); 104 }.bind(this));
105 // Sort failure groups so that newer failures are shown at the top o f the UI.
79 Object.keys(this.failures, function (tree, failuresByTree) { 106 Object.keys(this.failures, function (tree, failuresByTree) {
80 this.failures[tree].sort(this._failureListComparator.bind(this, tr ee)); 107 this.failures[tree].sort(this._failureByTreeListComparator.bind(th is, tree));
81 }.bind(this)); 108 }.bind(this));
82 }.bind(this)); 109 }.bind(this));
83 }.bind(this)); 110 }.bind(this));
84 }, 111 },
85 112
86 _failureComparator: function(a, b) { 113 _failureComparator: function(a, b) {
87 if (a.step > b.step) 114 if (a.step > b.step)
88 return 1; 115 return 1;
89 if (a.step < b.step) 116 if (a.step < b.step)
90 return -1 117 return -1
91 if (a.testName > b.testName) 118 if (a.testName > b.testName)
92 return 1; 119 return 1;
93 if (a.testName < b.testName) 120 if (a.testName < b.testName)
94 return -1 121 return -1
95 return 0; 122 return 0;
96 }, 123 },
97 124
98 _processFailuresForGroup: function(group, failures, annotations) { 125 _processFailuresForRangeGroup: function(rangeGroup, alerts, annotations) {
99 var failuresByReason = {};
100
101 var masterToTree = {}; 126 var masterToTree = {};
102 Object.keys(this._trees, function(tree, masters) { 127 Object.keys(this._trees, function(tree, masters) {
103 masters.forEach(function(master) { 128 masters.forEach(function(master) {
104 masterToTree[master] = tree; 129 masterToTree[master] = tree;
105 }); 130 });
106 }); 131 });
107 132
108 group.failure_keys.forEach(function(failure_key) { 133 // A rangeGroup may be related to multiple alerts (via |failure_keys|). Categorize
109 var failure = failures.find(function(item) { return item.key == failur e_key; }); 134 // these failures by reason (cause of failure), so that they can be grou ped in the UI
135 // (via a CTFailureGroup). Failures will be grouped in |failuresByReason |.
136 var failuresByReason = {};
137 rangeGroup.failure_keys.forEach(function(failure_key) {
138 var failure = alerts.find(function(item) { return item.key == failure_ key; });
139 // Establish the key to uniquely identify a failure by reason.
110 var reason, failureType; 140 var reason, failureType;
111 if (failure.reason) { 141 if (failure.reason) {
112 // FIXME: Store the actual failure type in a different field instead of smashing it into the reason. 142 // FIXME: Store the actual failure type in a different field instead of smashing it into the reason.
113 var parts = failure.reason.split(':'); 143 var parts = failure.reason.split(':');
114 reason = parts[0]; 144 reason = parts[0];
115 failureType = parts[1] || 'FAIL'; 145 failureType = parts[1] || 'FAIL';
116 } else { 146 } else {
117 reason = null; 147 reason = null;
118 failureType = 'UNKNOWN'; 148 failureType = 'UNKNOWN';
119 } 149 }
120 150
121 var failureKey = JSON.stringify({ 151 var failureKey = JSON.stringify({
122 step: failure.step_name, 152 step: failure.step_name,
123 reason: reason, 153 reason: reason,
124 }); 154 });
125 155
156 // FIXME: Figure out what tree masters that aren't in masterToTree
157 // we should have.
126 var tree = masterToTree[failure.master_url]; 158 var tree = masterToTree[failure.master_url];
127 159
128 // FIXME: Use a model class instead of a dumb object. 160 // FIXME: Use a model class instead of a dumb object.
129 if (!failuresByReason[failureKey]) 161 if (!failuresByReason[failureKey])
130 failuresByReason[failureKey] = {}; 162 failuresByReason[failureKey] = {};
131 if (!failuresByReason[failureKey][tree]) 163 if (!failuresByReason[failureKey][tree])
132 failuresByReason[failureKey][tree] = {}; 164 failuresByReason[failureKey][tree] = {};
133 failuresByReason[failureKey][tree][failure.builder_name] = { 165 failuresByReason[failureKey][tree][failure.builder_name] = {
134 // FIXME: Rename to failureType. 166 // FIXME: Rename to failureType.
135 actual: failureType, 167 actual: failureType,
136 lastFailingBuild: failure.last_failing_build, 168 lastFailingBuild: failure.last_failing_build,
137 earliestFailingBuild: failure.failing_build, 169 earliestFailingBuild: failure.failing_build,
138 masterUrl: failure.master_url, 170 masterUrl: failure.master_url,
139 failingBuildCount: failure.failing_build_count, 171 failingBuildCount: failure.failing_build_count,
140 }; 172 };
141 }.bind(this)); 173 }.bind(this));
142 174
175 if (!Object.keys(failuresByReason).length)
176 return;
177
143 var groupedFailures = {}; 178 var groupedFailures = {};
144 Object.keys(failuresByReason, function(failureKey, resultsByTree) { 179 Object.keys(failuresByReason, function(failureKey, resultsByTree) {
145 var failure = JSON.parse(failureKey); 180 var failure = JSON.parse(failureKey);
146 Object.keys(resultsByTree, function(tree, resultsByBuilder) { 181 Object.keys(resultsByTree, function(tree, resultsByBuilder) {
147 if (!groupedFailures[tree]) 182 if (!groupedFailures[tree])
148 groupedFailures[tree] = []; 183 groupedFailures[tree] = [];
149 groupedFailures[tree].push(new CTFailure(failure.step, failure.reaso n, resultsByBuilder, group.merged_first_failing, group.merged_last_passing)); 184 groupedFailures[tree].push(
185 new CTFailure(failure.step, failure.reason, resultsByBuilder));
150 }) 186 })
151 }); 187 });
152 188
153 Object.keys(groupedFailures, function(tree, failures) { 189 Object.keys(groupedFailures, function(tree, failures) {
154 failures.sort(this._failureComparator); 190 failures.sort(this._failureComparator);
155 191
156 if (!this.failures[tree]) 192 if (!this.failures[tree])
157 this.failures[tree] = []; 193 this.failures[tree] = [];
158 // FIXME: Need a better identifier for a failure group; 194 // FIXME: Need a better identifier for a failure group;
159 var key = group.sort_key; 195 var key = rangeGroup.sort_key;
160 this.failures[tree].push(new CTFailureGroup(key, failures, annotations [key])); 196 this.failures[tree].push(
197 new CTFailureGroup(key, failures, rangeGroup.likely_revisions,
198 annotations[key]));
161 }.bind(this)); 199 }.bind(this));
162 }, 200 },
163 }); 201 });
164 </script> 202 </script>
165 </polymer-element> 203 </polymer-element>
OLDNEW
« no previous file with comments | « Tools/GardeningServer/model/test/ct-failure-group-tests.html ('k') | Tools/GardeningServer/ui/test/ct-commit-list-tests.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698