Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import copy | |
| 6 import logging | |
| 7 | |
| 8 from common import time_util | |
| 9 from crash.chromecrash_parser import ChromeCrashParser | |
| 10 from crash.component_classifier import Component | |
| 11 from crash.component_classifier import ComponentClassifier | |
| 12 from crash.crash_report import CrashReport | |
| 13 from crash.culprit import NullCulprit | |
| 14 from crash.project_classifier import ProjectClassifier | |
| 15 from crash.type_enums import CrashClient | |
| 16 from model import analysis_status | |
| 17 from model.crash.cracas_crash_analysis import CracasCrashAnalysis | |
| 18 from model.crash.crash_config import CrashConfig | |
| 19 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | |
| 20 | |
| 21 # TODO: this class depends on ndb stuff, and should therefore move to | |
| 22 # ./findit/appengine as part of the big reorganization | |
| 23 class Findit(object): | |
| 24 def __init__(self): | |
| 25 # TODO(wrengr): are the clients similar enough that we can initialize | |
| 26 # Azalea here? | |
| 27 # TODO(wrengr): because self.client is volatile, we need some way | |
| 28 # of updating the Azelea instance whenever the config changes. How to | |
| 29 # do that cleanly? | |
| 30 self.azalea = None | |
| 31 | |
| 32 # This is a method rather than an attribute to ensure it can't be changed. | |
| 33 @classmethod | |
| 34 def ClientID(cls): | |
| 35 """Reify the name of this class as a CrashClient id, for serialization.""" | |
| 36 raise NotImplementedError() | |
| 37 | |
| 38 @property | |
| 39 def client_id(self): | |
| 40 """Get the client id from the class of this object. | |
| 41 | |
| 42 N.B., this property is static and should not be overridden.""" | |
| 43 return self.__class__.ClientID() | |
| 44 | |
| 45 # TODO(wrengr): can we remove the dependency on CrashConfig | |
| 46 # entirely? It'd be better to receive method calls whenever things | |
| 47 # change, so that we know the change happened (and what in particular | |
| 48 # changed) so that we cna update our internal state as appropriate. | |
| 49 @property | |
| 50 def config(self): | |
| 51 """Get the current value of the client config. | |
| 52 | |
| 53 N.B., this property is volatile and may change asynchronously.""" | |
| 54 return CrashConfig.Get().GetClientConfig(self.client_id) | |
| 55 | |
| 56 # TODO(wrengr): rename to CanonicalizePlatform or something like that. | |
| 57 def RenamePlatform(self, platform): | |
| 58 """Remap the platform to a different one, based on the config.""" | |
| 59 # TODO(katesonia): Remove the default value after adding validity check to | |
| 60 # config. | |
| 61 return self.config.get('platform_rename', {}).get(platform, platform) | |
| 62 | |
| 63 # TODO(wrengr): the crash_identifiers are only used for logging. Do | |
| 64 # we really need them here? | |
| 65 # TODO(wrengr): what does "policy" actually mean here? All we do is | |
| 66 # convert one report into another; should have a better name. | |
| 67 # TODO(wrengr): FinditForChromeCrash needs the channel for logging and | |
| 68 # bailing out for unsupported channels. Can we avoid needing it there, | |
| 69 # or can we instead pass it in **kwargs? | |
| 70 def CheckPolicy(self, crash_identifiers, report, channel): | |
| 71 """Check whether the report satisfies this client's policy. | |
| 72 | |
| 73 Args: | |
| 74 crash_identifiers (??): ?? | |
| 75 report (CrashReport): The report we're checking. | |
| 76 channel (str): ?? | |
| 77 | |
| 78 Returns: | |
| 79 If satisfied, we return a new report which may update some | |
| 80 fields. Otherwise returns None. | |
| 81 """ | |
| 82 return None | |
|
Sharu Jiang
2016/10/12 17:46:29
shouldn't this raise NotImplementedError()?
wrengr
2016/10/12 21:14:51
That's what I originally had, but a lot of the uni
Sharu Jiang
2016/10/12 22:35:03
For those Not Implemented methods, we can simply s
| |
| 83 | |
| 84 def CreateAnalysis(self, crash_identifiers): | |
| 85 return None | |
|
Sharu Jiang
2016/10/12 17:46:29
Ditto.
wrengr
2016/10/12 21:14:51
Ditto.
| |
| 86 | |
| 87 def GetAnalysis(self, crash_identifiers): | |
| 88 return None | |
|
Sharu Jiang
2016/10/12 17:46:29
Ditto.
wrengr
2016/10/12 21:14:51
ditto.
| |
| 89 | |
| 90 # TODO(wrengr): FinditForChromeCrash used to also set |channel| and | |
| 91 # |historical_metadata|. However, the values for those aren't clear from | |
| 92 # the one callsite for |UpdateAnalysis| (i.e., in crash_pipeline.py) | |
| 93 def ResetAnalysis(self, model, report): | |
|
Sharu Jiang
2016/10/12 22:35:03
The create order should be:
client-input-messeage
wrengr
2016/10/18 23:13:54
It's not clear to me when/why one would call Reset
| |
| 94 """Copies the CrashReport into the ndb.Model, but does not |put()| it. | |
| 95 | |
| 96 This method is distinguished from UpdateAnalysis in that we modify | |
| 97 the |model| but do not |put()| it. This is the method that subclasses | |
| 98 should extend (not override) in order to perform any additional work | |
| 99 needed to reset their ndb.Models.""" | |
| 100 model.Reset() | |
| 101 | |
| 102 # Set common properties. | |
| 103 model.crashed_version = report.crashed_version | |
| 104 model.stack_trace = str(report.stacktrace) # TODO(wrengr): fix this | |
| 105 model.signature = report.signature | |
| 106 model.platform = report.platform | |
| 107 model.client_id = self.client_id | |
| 108 | |
| 109 # Set progress properties. | |
| 110 model.status = analysis_status.PENDING | |
| 111 model.requested_time = time_util.GetUTCNow() | |
| 112 | |
| 113 def UpdateAnalysis(self, model, report): | |
| 114 """Update the CrashAnalysis ndb.Model and then put it. | |
| 115 | |
| 116 This method simply calls ResetAnalysis and then calls |put()| on the | |
| 117 modified model. We distinguish it from that method because we need | |
| 118 subclasses to do extra work to reset their own parts of the ndb.Model, | |
| 119 but we need the call to |put()| to happen after those changes have | |
| 120 been executed. For now, this seems like the cleanest split.""" | |
| 121 self.ResetAnalysis(model, report) | |
| 122 model.put() | |
| 123 | |
| 124 def FindCulprit(self, mode, **kwargs): | |
| 125 """Given a CrashAnalysis ndb.Model, return a Culprit.""" | |
| 126 return ( | |
| 127 {'found': False}, | |
| 128 {'found_suspects': False, 'has_regression_range': False}) | |
| 129 | |
| 130 | |
| 131 # TODO(katesonia): Implement this class. | |
| 132 class FinditForClusterfuzz(Findit): | |
|
Sharu Jiang
2016/10/12 17:46:29
Why is this in findit.py?
wrengr
2016/10/12 21:14:51
Because it's as-yet too short to bother breaking o
Sharu Jiang
2016/10/12 22:35:03
Can you break it out to findit_for_clustefuzz.py?
wrengr
2016/10/18 23:13:54
Done.
| |
| 133 @classmethod | |
| 134 def ClientID(cls): | |
| 135 return CrashClient.CLUSTERFUZZ | |
| 136 | |
| 137 def __init__(self): | |
| 138 logging.info('Client %s is not supported by findit right now', | |
| 139 self.client_id) | |
| 140 raise NotImplementedError() | |
| 141 | |
| 142 def CreateAnalysis(self, crash_identifiers): | |
| 143 raise NotImplementedError() | |
| 144 | |
| 145 def GetAnalysis(self, crash_identifiers): | |
| 146 raise NotImplementedError() | |
| 147 | |
| 148 def ResetAnalysis(self, model, report, *args, **kwargs): | |
| 149 super(FinditForClusterfuzz, self).ResetAnalysis(model, report) | |
| 150 raise NotImplementedError() | |
| 151 | |
| 152 def CheckPolicy(self, crash_identifiers, report, channel): | |
| 153 return report | |
| 154 | |
| 155 def FindCulprit(self, model, **kwargs): | |
| 156 raise NotImplementedError() | |
| OLD | NEW |