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

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

Issue 2663063007: [Predator] Switch from anonymous dict to CrashData. (Closed)
Patch Set: Rebase and fix delta test. Created 3 years, 10 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 6
7 from google.appengine.ext import ndb 7 from google.appengine.ext import ndb
8 8
9 from common import appengine_util 9 from common import appengine_util
10 from common.chrome_dependency_fetcher import ChromeDependencyFetcher
10 from crash import detect_regression_range 11 from crash import detect_regression_range
11 from crash.chromecrash_parser import ChromeCrashParser 12 from crash.chromecrash_parser import ChromeCrashParser
13 from crash.chrome_crash_data import ChromeCrashData
12 from crash.findit import Findit 14 from crash.findit import Findit
13 from crash.loglinear.changelist_classifier import LogLinearChangelistClassifier 15 from crash.loglinear.changelist_classifier import LogLinearChangelistClassifier
14 from crash.loglinear.changelist_features.touch_crashed_file_meta import ( 16 from crash.loglinear.changelist_features.touch_crashed_file_meta import (
15 TouchCrashedFileMetaFeature) 17 TouchCrashedFileMetaFeature)
16 from crash.loglinear.feature import WrapperMetaFeature 18 from crash.loglinear.feature import WrapperMetaFeature
17 from crash.loglinear.weight import MetaWeight 19 from crash.loglinear.weight import MetaWeight
18 from crash.loglinear.weight import Weight 20 from crash.loglinear.weight import Weight
19 from crash.predator import Predator 21 from crash.predator import Predator
20 from crash.type_enums import CrashClient 22 from crash.type_enums import CrashClient
21 from model.crash.cracas_crash_analysis import CracasCrashAnalysis 23 from model.crash.cracas_crash_analysis import CracasCrashAnalysis
22 from model.crash.crash_config import CrashConfig
23 from model.crash.fracas_crash_analysis import FracasCrashAnalysis 24 from model.crash.fracas_crash_analysis import FracasCrashAnalysis
24 25
25 # TODO(katesonia): Remove the default value after adding validity check to 26 # TODO(katesonia): Remove the default value after adding validity check to
26 # config. 27 # config.
27 _FRACAS_FEEDBACK_URL_TEMPLATE = 'https://%s/crash/fracas-result-feedback?key=%s' 28 _FRACAS_FEEDBACK_URL_TEMPLATE = 'https://%s/crash/fracas-result-feedback?key=%s'
28 29
29 # TODO(wrengr): [Note#1] in many places below we have to do some ugly
30 # defaulting in case crash_data is missing certain keys. If we had
31 # crash_data be a proper class, rather than an anonymous dict, then we
32 # could clean all this up by having the properties themselves do the check
33 # and return the default whenever keys are missing. This would also
34 # let us do things like have regression_range be automatically computed
35 # from historical_metadata (when historical_metadata is provided and
36 # regression_range is not).
37 30
38 31 class FinditForChromeCrash(Findit): # pylint: disable=W0223
39 class FinditForChromeCrash(Findit):
40 """Find culprits for crash reports from the Chrome Crash server.""" 32 """Find culprits for crash reports from the Chrome Crash server."""
41 33
42 @classmethod 34 @classmethod
43 def _ClientID(cls): # pragma: no cover 35 def _ClientID(cls): # pragma: no cover
44 if cls is FinditForChromeCrash: 36 if cls is FinditForChromeCrash:
45 logging.warning('FinditForChromeCrash is abstract, ' 37 logging.warning('FinditForChromeCrash is abstract, '
46 'but someone constructed an instance and called _ClientID') 38 'but someone constructed an instance and called _ClientID')
47 else: 39 else:
48 logging.warning( 40 logging.warning(
49 'FinditForChromeCrash subclass %s forgot to implement _ClientID', 41 'FinditForChromeCrash subclass %s forgot to implement _ClientID',
50 cls.__name__) 42 cls.__name__)
51 raise NotImplementedError() 43 raise NotImplementedError()
52 44
53 def __init__(self, get_repository, config): 45 def __init__(self, get_repository, config):
54 super(FinditForChromeCrash, self).__init__(get_repository, config) 46 super(FinditForChromeCrash, self).__init__(get_repository, config)
55
56 # TODO(http://crbug.com/687670): Move meta weight initial value to config.
57 meta_weight = MetaWeight({ 47 meta_weight = MetaWeight({
58 'TouchCrashedFileMeta': MetaWeight({ 48 'TouchCrashedFileMeta': MetaWeight({
59 'MinDistance': Weight(1.), 49 'MinDistance': Weight(1.),
60 'TopFrameIndex': Weight(1.), 50 'TopFrameIndex': Weight(1.),
61 'TouchCrashedFile': Weight(1.), 51 'TouchCrashedFile': Weight(1.),
62 }) 52 })
63 }) 53 })
64 meta_feature = WrapperMetaFeature( 54 meta_feature = WrapperMetaFeature(
65 [TouchCrashedFileMetaFeature(get_repository)]) 55 [TouchCrashedFileMetaFeature(get_repository)])
66 56
67 # The top_n is the number of frames we want to check to get component or 57 self._predator = Predator(LogLinearChangelistClassifier(get_repository,
68 # project classifications. 58 meta_feature,
69 self._predator = Predator( 59 meta_weight),
70 cl_classifier = LogLinearChangelistClassifier(get_repository, 60 self._component_classifier,
71 meta_feature, 61 self._project_classifier)
72 meta_weight),
73 project_classifier = self._project_classifier,
74 component_classifier = self._component_classifier)
75 62
76 self._stacktrace_parser = ChromeCrashParser() 63 def _Predator(self): # pragma: no cover
64 return self._predator
77 65
78 def _InitializeAnalysis(self, model, crash_data): 66 def _CheckPolicy(self, crash_data):
79 super(FinditForChromeCrash, self)._InitializeAnalysis(model, crash_data) 67 """Checks if ``CrashData`` meets policy requirements."""
80 # TODO(wrengr): see Note#1 68 if not super(FinditForChromeCrash, self)._CheckPolicy(crash_data):
81 customized_data = crash_data.get('customized_data', {})
82 model.channel = customized_data.get('channel', None)
83 model.historical_metadata = customized_data.get('historical_metadata', [])
84
85 # TODO(wrengr): see Note#1, which would allow us to lift this
86 # implementation to the Findit base class.
87 @ndb.transactional
88 def _NeedsNewAnalysis(self, crash_data):
89 crash_identifiers = crash_data['crash_identifiers']
90 historical_metadata = crash_data['customized_data']['historical_metadata']
91 model = self.GetAnalysis(crash_identifiers)
92 # N.B., for mocking reasons, we must not call DetectRegressionRange
93 # directly, but rather must access it indirectly through the module.
94 new_regression_range = detect_regression_range.DetectRegressionRange(
95 historical_metadata)
96 if (model and not model.failed and
97 new_regression_range == model.regression_range):
98 logging.info('The analysis of %s has already been done.',
99 repr(crash_identifiers))
100 return False 69 return False
101 70
102 if not model: 71 if crash_data.platform not in self.client_config[
103 model = self.CreateAnalysis(crash_identifiers) 72 'supported_platform_list_by_channel'].get(crash_data.channel, []):
73 # Bail out if either the channel or platform is not supported yet.
74 logging.info('Analysis of channel %s, platform %s is not supported.',
75 crash_data.channel, crash_data.platform)
76 return False
104 77
105 crash_data['regression_range'] = new_regression_range
106 self._InitializeAnalysis(model, crash_data)
107 model.put()
108 return True 78 return True
109 79
110 def CheckPolicy(self, crash_data): 80 def GetCrashData(self, raw_crash_data):
111 crash_identifiers = crash_data['crash_identifiers'] 81 """Returns parsed ``ChromeCrashData`` from raw json crash data."""
112 platform = crash_data['platform'] 82 return ChromeCrashData(raw_crash_data,
113 # TODO(wrengr): see Note#1 83 ChromeDependencyFetcher(self._get_repository),
114 channel = crash_data.get('customized_data', {}).get('channel', None) 84 top_n_frames=self.client_config['top_n'])
115 # TODO(katesonia): Remove the default value after adding validity check to
116 # config.
117 if platform not in self.client_config.get(
118 'supported_platform_list_by_channel', {}).get(channel, []):
119 # Bail out if either the channel or platform is not supported yet.
120 logging.info('Analysis of channel %s, platform %s is not supported. '
121 'No analysis is scheduled for %s',
122 channel, platform, repr(crash_identifiers))
123 return None
124
125 signature = crash_data['signature']
126 # TODO(wrengr): can this blacklist stuff be lifted to the base class?
127 # TODO(katesonia): Remove the default value after adding validity check to
128 # config.
129 for blacklist_marker in self.client_config.get(
130 'signature_blacklist_markers', []):
131 if blacklist_marker in signature:
132 logging.info('%s signature is not supported. '
133 'No analysis is scheduled for %s', blacklist_marker,
134 repr(crash_identifiers))
135 return None
136
137 # TODO(wrengr): should we clone ``crash_data`` rather than mutating it?
138 crash_data['platform'] = self.RenamePlatform(platform)
139 return crash_data
140
141 def ProcessResultForPublishing(self, result, key): # pragma: no cover.
142 """Client specific processing of result data for publishing."""
143 # This method needs to get overwritten by subclasses FinditForCracas and
144 # FinditForFracas.
145 raise NotImplementedError()
146 85
147 86
148 # TODO(http://crbug.com/659346): we misplaced the coverage tests; find them! 87 # TODO(http://crbug.com/659346): we misplaced the coverage tests; find them!
149 class FinditForCracas(FinditForChromeCrash): # pragma: no cover 88 class FinditForCracas( # pylint: disable=W0223
89 FinditForChromeCrash): # pragma: no cover
90
150 @classmethod 91 @classmethod
151 def _ClientID(cls): 92 def _ClientID(cls):
152 return CrashClient.CRACAS 93 return CrashClient.CRACAS
153 94
154 def CreateAnalysis(self, crash_identifiers): 95 def CreateAnalysis(self, crash_identifiers):
155 # TODO: inline CracasCrashAnalysis.Create stuff here. 96 # TODO: inline CracasCrashAnalysis.Create stuff here.
156 return CracasCrashAnalysis.Create(crash_identifiers) 97 return CracasCrashAnalysis.Create(crash_identifiers)
157 98
158 def GetAnalysis(self, crash_identifiers): 99 def GetAnalysis(self, crash_identifiers):
159 # TODO: inline CracasCrashAnalysis.Get stuff here. 100 # TODO: inline CracasCrashAnalysis.Get stuff here.
160 return CracasCrashAnalysis.Get(crash_identifiers) 101 return CracasCrashAnalysis.Get(crash_identifiers)
161 102
162 def ProcessResultForPublishing(self, result, key): # pragma: no cover. 103 def ProcessResultForPublishing(self, result, key): # pragma: no cover.
163 """Cracas specific processing of result data for publishing.""" 104 """Cracas specific processing of result data for publishing."""
164 # TODO(katesonia) Add feedback page link information to result after 105 # TODO(katesonia) Add feedback page link information to result after
165 # feedback page of Cracas is added. 106 # feedback page of Cracas is added.
166 return result 107 return result
167 108
168 109
169 class FinditForFracas(FinditForChromeCrash): 110 class FinditForFracas(FinditForChromeCrash): # pylint: disable=W0223
170 @classmethod 111 @classmethod
171 def _ClientID(cls): 112 def _ClientID(cls):
172 return CrashClient.FRACAS 113 return CrashClient.FRACAS
173 114
174 def CreateAnalysis(self, crash_identifiers): 115 def CreateAnalysis(self, crash_identifiers):
175 # TODO: inline FracasCrashAnalysis.Create stuff here. 116 # TODO: inline FracasCrashAnalysis.Create stuff here.
176 return FracasCrashAnalysis.Create(crash_identifiers) 117 return FracasCrashAnalysis.Create(crash_identifiers)
177 118
178 def GetAnalysis(self, crash_identifiers): 119 def GetAnalysis(self, crash_identifiers):
179 # TODO: inline FracasCrashAnalysis.Get stuff here. 120 # TODO: inline FracasCrashAnalysis.Get stuff here.
180 return FracasCrashAnalysis.Get(crash_identifiers) 121 return FracasCrashAnalysis.Get(crash_identifiers)
181 122
182 def ProcessResultForPublishing(self, result, key): 123 def ProcessResultForPublishing(self, result, key):
183 """Fracas specific processing of result data for publishing.""" 124 """Fracas specific processing of result data for publishing."""
184 result['feedback_url'] = _FRACAS_FEEDBACK_URL_TEMPLATE % ( 125 result['feedback_url'] = _FRACAS_FEEDBACK_URL_TEMPLATE % (
185 appengine_util.GetDefaultVersionHostname(), key) 126 appengine_util.GetDefaultVersionHostname(), key)
186 return result 127 return result
OLDNEW
« no previous file with comments | « appengine/findit/crash/findit.py ('k') | appengine/findit/crash/loglinear/changelist_classifier.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698