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

Side by Side Diff: appengine/findit/handlers/triage_analysis.py

Issue 2086113004: [Findit] Show build analysis references in UI for Findit Cross-platform auto-triage (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@build-matching
Patch Set: Created 4 years, 6 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
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """This module is to handle manual triage of analysis result. 5 """This module is to handle manual triage of analysis result.
6 6
7 This handler will flag the analysis result as correct or incorrect. 7 This handler will flag the analysis result as correct or incorrect.
8 TODO: work on an automatic or semi-automatic way to triage analysis result. 8 TODO: work on an automatic or semi-automatic way to triage analysis result.
9 """ 9 """
10 10
(...skipping 28 matching lines...) Expand all
39 39
40 or could look like: 40 or could look like:
41 41
42 (step_name, revision) 42 (step_name, revision)
43 """ 43 """
44 potential_culprit_tuple_list = [] 44 potential_culprit_tuple_list = []
45 45
46 # Iterates through the failures, tests, and suspected_cls, appending potential 46 # Iterates through the failures, tests, and suspected_cls, appending potential
47 # (step_name, test_name, revision) and (step_name, revision) culprit tuples to 47 # (step_name, test_name, revision) and (step_name, revision) culprit tuples to
48 # the list. 48 # the list.
49
49 for failure in analysis.result['failures']: 50 for failure in analysis.result['failures']:
50 if failure.get('tests'): 51 if failure.get('tests'):
51 for test in failure['tests']: 52 for test in failure['tests']:
52 for suspected_cl in test.get('suspected_cls', []): 53 for suspected_cl in test.get('suspected_cls', []):
53 potential_culprit_tuple_list.append(( 54 potential_culprit_tuple_list.append((
54 failure['step_name'], 55 failure['step_name'],
55 test['test_name'], 56 test['test_name'],
56 suspected_cl['revision'])) 57 suspected_cl['revision']))
57 else: 58 else:
58 for suspected_cl in failure['suspected_cls']: 59 for suspected_cl in failure['suspected_cls']:
(...skipping 22 matching lines...) Expand all
81 82
82 # Both analyses must have non-empty potential culprit lists. 83 # Both analyses must have non-empty potential culprit lists.
83 if not potential_culprit_tuple_list_1 or not potential_culprit_tuple_list_2: 84 if not potential_culprit_tuple_list_1 or not potential_culprit_tuple_list_2:
84 return False 85 return False
85 86
86 # Both analyses must have matching potential culprit lists. 87 # Both analyses must have matching potential culprit lists.
87 return (sorted(potential_culprit_tuple_list_1) == 88 return (sorted(potential_culprit_tuple_list_1) ==
88 sorted(potential_culprit_tuple_list_2)) 89 sorted(potential_culprit_tuple_list_2))
89 90
90 91
91 def _AppendTriageHistoryRecord(analysis, is_correct, user_name): 92 def _AppendTriageHistoryRecord(
93 analysis, is_correct, user_name, duplicate=False):
92 """Appends a triage history record to the given analysis. 94 """Appends a triage history record to the given analysis.
93 95
94 Args: 96 Args:
95 analysis: The analysis to which to append the history record. 97 analysis: The analysis to which to append the history record.
96 correct: True if the history record should indicate a correct judgement, 98 correct: True if the history record should indicate a correct judgement,
chanli 2016/06/24 18:24:20 Did you rebase your patch? I remembered you have c
97 otherwise False. 99 otherwise False.
98 user_name: The user_name of the person to include in the triage record. 100 user_name: The user_name of the person to include in the triage record.
chanli 2016/06/24 18:24:20 Add description of 'duplicate' here
josiahk 2016/06/27 19:33:25 Done.
99 """ 101 """
100 if is_correct: 102 if is_correct:
101 if analysis.suspected_cls: 103 if analysis.suspected_cls:
102 analysis.result_status = result_status.FOUND_CORRECT 104 if duplicate:
105 analysis.result_status = result_status.FOUND_CORRECT_DUPLICATE
106 else:
107 analysis.result_status = result_status.FOUND_CORRECT
103 analysis.culprit_cls = analysis.suspected_cls 108 analysis.culprit_cls = analysis.suspected_cls
104 else: 109 else:
105 analysis.result_status = result_status.NOT_FOUND_CORRECT 110 analysis.result_status = result_status.NOT_FOUND_CORRECT
106 analysis.culprit_cls = None 111 analysis.culprit_cls = None
107 else: 112 else:
108 analysis.culprit_cls = None 113 analysis.culprit_cls = None
109 if analysis.suspected_cls: 114 if analysis.suspected_cls:
110 analysis.result_status = result_status.FOUND_INCORRECT 115 if duplicate:
116 analysis.result_status = result_status.FOUND_INCORRECT_DUPLICATE
117 else:
118 analysis.result_status = result_status.FOUND_INCORRECT
111 else: 119 else:
112 analysis.result_status = result_status.NOT_FOUND_INCORRECT 120 analysis.result_status = result_status.NOT_FOUND_INCORRECT
113 121
114 triage_record = { 122 triage_record = {
115 'triage_timestamp': calendar.timegm(datetime.utcnow().timetuple()), 123 'triage_timestamp': calendar.timegm(datetime.utcnow().timetuple()),
116 'user_name': user_name, 124 'user_name': user_name,
117 'result_status': analysis.result_status, 125 'result_status': analysis.result_status,
118 'version': analysis.version, 126 'version': analysis.version,
119 } 127 }
120 if not analysis.triage_history: 128 if not analysis.triage_history:
121 analysis.triage_history = [] 129 analysis.triage_history = []
122 analysis.triage_history.append(triage_record) 130 analysis.triage_history.append(triage_record)
123 131
124 analysis.put() 132 analysis.put()
125 133
126 134
127 @ndb.transactional 135 @ndb.transactional
128 def _UpdateAnalysisResultStatus( 136 def _UpdateAnalysisResultStatus(
129 master_name, builder_name, build_number, is_correct, user_name=None): 137 master_name, builder_name, build_number, is_correct, user_name=None):
130 analysis = WfAnalysis.Get(master_name, builder_name, build_number) 138 analysis = WfAnalysis.Get(master_name, builder_name, build_number)
131 if not analysis or not analysis.completed: 139 if not analysis or not analysis.completed:
132 return False, None 140 return False, None
133 141
142 analysis.triage_reference_analysis_master_name = None
143 analysis.triage_reference_analysis_builder_name = None
144 analysis.triage_reference_analysis_build_number = None
chanli 2016/06/24 18:24:20 These lines are not needed.
145
134 _AppendTriageHistoryRecord(analysis, is_correct, user_name) 146 _AppendTriageHistoryRecord(analysis, is_correct, user_name)
135 147
136 return True, analysis 148 return True, analysis
137 149
138 150
139 def _GetDuplicateAnalyses(original_analysis): 151 def _GetDuplicateAnalyses(original_analysis):
140 start_time = (original_analysis.build_start_time - 152 start_time = (original_analysis.build_start_time -
141 timedelta(hours=MATCHING_ANALYSIS_HOURS_AGO_START)) 153 timedelta(hours=MATCHING_ANALYSIS_HOURS_AGO_START))
142 end_time = (original_analysis.build_start_time + 154 end_time = (original_analysis.build_start_time +
143 timedelta(hours=MATCHING_ANALYSIS_HOURS_AGO_END)) 155 timedelta(hours=MATCHING_ANALYSIS_HOURS_AGO_END))
(...skipping 15 matching lines...) Expand all
159 return [analysis for analysis in analysis_results if 171 return [analysis for analysis in analysis_results if
160 _DoAnalysesMatch(original_analysis, analysis) and 172 _DoAnalysesMatch(original_analysis, analysis) and
161 original_analysis.key is not analysis.key and 173 original_analysis.key is not analysis.key and
162 analysis.completed] 174 analysis.completed]
163 175
164 176
165 def _TriageDuplicateResults(original_analysis, is_correct, user_name=None): 177 def _TriageDuplicateResults(original_analysis, is_correct, user_name=None):
166 matching_analyses = _GetDuplicateAnalyses(original_analysis) 178 matching_analyses = _GetDuplicateAnalyses(original_analysis)
167 179
168 for analysis in matching_analyses: 180 for analysis in matching_analyses:
169 _AppendTriageHistoryRecord(analysis, is_correct, user_name) 181 analysis.triage_reference_analysis_master_name = (
182 original_analysis.master_name)
183 analysis.triage_reference_analysis_builder_name = (
184 original_analysis.builder_name)
185 analysis.triage_reference_analysis_build_number = (
186 original_analysis.build_number)
187 _AppendTriageHistoryRecord(analysis, is_correct, user_name, duplicate=True)
188
189 return len(matching_analyses)
170 190
171 191
172 class TriageAnalysis(BaseHandler): 192 class TriageAnalysis(BaseHandler):
173 PERMISSION_LEVEL = Permission.CORP_USER 193 PERMISSION_LEVEL = Permission.CORP_USER
174 194
175 def HandleGet(self): # pragma: no cover 195 def HandleGet(self): # pragma: no cover
176 return self.HandlePost() 196 return self.HandlePost()
177 197
178 def HandlePost(self): 198 def HandlePost(self):
179 """Sets the manual triage result for the analysis. 199 """Sets the manual triage result for the analysis.
180 200
181 Mark the analysis result as correct/wrong/etc. 201 Mark the analysis result as correct/wrong/etc.
182 TODO: make it possible to set the real culprit CLs. 202 TODO: make it possible to set the real culprit CLs.
183 """ 203 """
184 url = self.request.get('url').strip() 204 url = self.request.get('url').strip()
185 build_info = buildbot.ParseBuildUrl(url) 205 build_info = buildbot.ParseBuildUrl(url)
186 if not build_info: 206 if not build_info:
187 return {'data': {'success': False}} 207 return {'data': {'success': False}}
188 master_name, builder_name, build_number = build_info 208 master_name, builder_name, build_number = build_info
189 209
190 is_correct = self.request.get('correct').lower() == 'true' 210 is_correct = self.request.get('correct').lower() == 'true'
191 # As the permission level is CORP_USER, we could assume the current user 211 # As the permission level is CORP_USER, we could assume the current user
192 # already logged in. 212 # already logged in.
193 user_name = users.get_current_user().email().split('@')[0] 213 user_name = users.get_current_user().email().split('@')[0]
194 success, original_analysis = _UpdateAnalysisResultStatus( 214 success, original_analysis = _UpdateAnalysisResultStatus(
195 master_name, builder_name, build_number, is_correct, user_name) 215 master_name, builder_name, build_number, is_correct, user_name)
216 num_duplicate_analyses = 0
196 if success: 217 if success:
197 _TriageDuplicateResults(original_analysis, is_correct, user_name) 218 num_duplicate_analyses = _TriageDuplicateResults(
198 return {'data': {'success': success}} 219 original_analysis, is_correct, user_name)
220 return {'data': {'success': success,
221 'num_duplicate_analyses': num_duplicate_analyses}}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698