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

Side by Side Diff: appengine/findit/crash/findit_for_chromecrash.py

Issue 2378133004: [Findit] Rerun if the regression range is different. (Closed)
Patch Set: Fix nits. Created 4 years, 2 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 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 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 import logging 5 import logging
6 from collections import namedtuple 6 from collections import namedtuple
7 7
8 from common import chromium_deps 8 from common import chromium_deps
9 from crash import detect_regression_range 9 from crash import detect_regression_range
10 from crash import findit_for_crash 10 from crash import findit_for_crash
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 If nothing is found: { 90 If nothing is found: {
91 'found_suspects': False, 91 'found_suspects': False,
92 } 92 }
93 """ 93 """
94 cls_list = [result.ToDict() for result in self.cls] 94 cls_list = [result.ToDict() for result in self.cls]
95 95
96 # TODO(wrengr): reformulate the JSON stuff so we can drop fields which 96 # TODO(wrengr): reformulate the JSON stuff so we can drop fields which
97 # are empty; so that, in turn, we can get rid of the NullCulprit class. 97 # are empty; so that, in turn, we can get rid of the NullCulprit class.
98 return ( 98 return (
99 { 99 {
100 'found': (bool(self.project) 100 'found': (bool(self.project) or
101 or bool(self.components) 101 bool(self.components) or
102 or bool(cls_list) 102 bool(cls_list) or
103 or bool(self.regression_range)), 103 bool(self.regression_range)),
104 'regression_range': self.regression_range, 104 'regression_range': self.regression_range,
105 'suspected_project': self.project, 105 'suspected_project': self.project,
106 'suspected_components': self.components, 106 'suspected_components': self.components,
107 'suspected_cls': cls_list, 107 'suspected_cls': cls_list,
108 }, 108 },
109 { 109 {
110 'found_suspects': bool(cls_list), 110 'found_suspects': bool(cls_list),
111 'found_project': bool(self.project), 111 'found_project': bool(self.project),
112 'found_components': bool(self.components), 112 'found_components': bool(self.components),
113 'has_regression_range': bool(self.regression_range), 113 'has_regression_range': bool(self.regression_range),
(...skipping 30 matching lines...) Expand all
144 144
145 Even though this class has only one method, it is helpful because it 145 Even though this class has only one method, it is helpful because it
146 allows us to cache things which should outlive each call to that method. 146 allows us to cache things which should outlive each call to that method.
147 For example, we store a single ComponentClassifier object so that we 147 For example, we store a single ComponentClassifier object so that we
148 only compile the regexes for each Component object once, rather than 148 only compile the regexes for each Component object once, rather than
149 doing so on each call to FindCulprit. In addition, the class lets 149 doing so on each call to FindCulprit. In addition, the class lets
150 us cache various configuration options so that we need not depend 150 us cache various configuration options so that we need not depend
151 on CrashConfig; thereby decoupling the analysis itself from UX concerns 151 on CrashConfig; thereby decoupling the analysis itself from UX concerns
152 about deciding how to run those analyses. 152 about deciding how to run those analyses.
153 """ 153 """
154
155 # TODO(wrengr): remove the dependency on CrashConfig entirely, by 154 # TODO(wrengr): remove the dependency on CrashConfig entirely, by
156 # passing the relevant data as arguments to this constructor. 155 # passing the relevant data as arguments to this constructor.
157 def __init__(self): 156 def __init__(self):
158 crash_config = CrashConfig.Get() 157 crash_config = CrashConfig.Get()
159 component_classifier_config = crash_config.component_classifier 158 component_classifier_config = crash_config.component_classifier
160 159
161 # TODO(wrengr): why are these two different? 160 # TODO(wrengr): why are these two different?
162 component_classifier_top_n = component_classifier_config['top_n'] 161 component_classifier_top_n = component_classifier_config['top_n']
163 self._fracas_top_n = crash_config.fracas.get('top_n', _DEFAULT_TOP_N) 162 self._fracas_top_n = crash_config.fracas.get('top_n', _DEFAULT_TOP_N)
164 163
165 self.component_classifier = ComponentClassifier( 164 self.component_classifier = ComponentClassifier(
166 [Component(component_name, path_regex, function_regex) 165 [Component(component_name, path_regex, function_regex)
167 for path_regex, function_regex, component_name 166 for path_regex, function_regex, component_name
168 in component_classifier_config['path_function_component']], 167 in component_classifier_config['path_function_component']],
169 component_classifier_top_n) 168 component_classifier_top_n)
170 169
171 # TODO(wrengr); fix ProjectClassifier so it doesn't depend on CrashConfig. 170 # TODO(wrengr); fix ProjectClassifier so it doesn't depend on CrashConfig.
172 self.project_classifier = ProjectClassifier() 171 self.project_classifier = ProjectClassifier()
173 172
174
175 # TODO(wrengr): since this is the only method of interest, it would 173 # TODO(wrengr): since this is the only method of interest, it would
176 # be better IMO to rename it to __call__ to reduce verbosity. 174 # be better IMO to rename it to __call__ to reduce verbosity.
177 def FindCulprit(self, signature, platform, stack_trace, crashed_version, 175 def FindCulprit(self, signature, platform, stack_trace, crashed_version,
178 historic_metadata): 176 regression_range):
179 """Finds culprits for a Chrome crash. 177 """Finds culprits for a Chrome crash.
180 178
181 Args: 179 Args:
182 signature (str): The signature of a crash on the Chrome crash server. 180 signature (str): The signature of a crash on the Chrome crash server.
183 platform (str): The platform name, could be 'win', 'mac', 'linux', 181 platform (str): The platform name, could be 'win', 'mac', 'linux',
184 'android', 'ios', etc. 182 'android', 'ios', etc.
185 stack_trace (str): A string containing the stack trace of a crash. 183 stack_trace (str): A string containing the stack trace of a crash.
186 crashed_version (str): The version of Chrome in which the crash occurred. 184 crashed_version (str): The version of Chrome in which the crash occurred.
187 historic_metadata (list): list of dicts mapping from Chrome version to 185 regression_range (list or None): [good_version, bad_revision] or None.
188 historic metadata.
189 186
190 Returns: 187 Returns:
191 A Culprit object. 188 A Culprit object.
192 """ 189 """
193 crash_deps = chromium_deps.GetChromeDependency(crashed_version, platform) 190 crash_deps = chromium_deps.GetChromeDependency(crashed_version, platform)
194 stacktrace = ChromeCrashParser().Parse(stack_trace, crash_deps, signature) 191 stacktrace = ChromeCrashParser().Parse(stack_trace, crash_deps, signature)
195 if not stacktrace: 192 if not stacktrace:
196 logging.warning('Failed to parse the stacktrace %s', stack_trace) 193 logging.warning('Failed to parse the stacktrace %s', stack_trace)
197 # TODO(wrengr): refactor things so we don't need the NullCulprit class. 194 # TODO(wrengr): refactor things so we don't need the NullCulprit class.
198 return NullCulprit() 195 return NullCulprit()
199 196
200 # Get regression deps and crash deps. 197 # Get regression deps and crash deps.
201 regression_deps_rolls = {} 198 regression_deps_rolls = {}
202 regression_range = detect_regression_range.DetectRegressionRange(
203 historic_metadata)
204 if regression_range: 199 if regression_range:
205 last_good_version, first_bad_version = regression_range 200 last_good_version, first_bad_version = regression_range
206 logging.info('Find regression range %s:%s', last_good_version, 201 logging.info('Find regression range %s:%s', last_good_version,
207 first_bad_version) 202 first_bad_version)
208 regression_deps_rolls = chromium_deps.GetDEPSRollsDict( 203 regression_deps_rolls = chromium_deps.GetDEPSRollsDict(
209 last_good_version, first_bad_version, platform) 204 last_good_version, first_bad_version, platform)
210 205
211 suspected_cls = findit_for_crash.FindItForCrash( 206 suspected_cls = findit_for_crash.FindItForCrash(
212 stacktrace, regression_deps_rolls, crash_deps, self._fracas_top_n) 207 stacktrace, regression_deps_rolls, crash_deps, self._fracas_top_n)
213 208
214 crash_stack = stacktrace.crash_stack 209 crash_stack = stacktrace.crash_stack
215 suspected_project = self.project_classifier.Classify( 210 suspected_project = self.project_classifier.Classify(
216 suspected_cls, crash_stack) 211 suspected_cls, crash_stack)
217 212
218 suspected_components = self.component_classifier.Classify( 213 suspected_components = self.component_classifier.Classify(
219 suspected_cls, crash_stack) 214 suspected_cls, crash_stack)
220 215
221 return Culprit(suspected_project, suspected_components, suspected_cls, 216 return Culprit(suspected_project, suspected_components, suspected_cls,
222 regression_range) 217 regression_range)
OLDNEW
« no previous file with comments | « appengine/findit/crash/detect_regression_range.py ('k') | appengine/findit/crash/findit_for_client.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698