Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 base64 | 5 import base64 |
| 6 import datetime | 6 import datetime |
| 7 import json | 7 import json |
| 8 import logging | 8 import logging |
| 9 | 9 |
| 10 from google.appengine.ext import ndb | 10 from google.appengine.ext import ndb |
| 11 | 11 |
| 12 from common import appengine_util | 12 from common import appengine_util |
| 13 from common import constants | 13 from common import constants |
| 14 from common import pubsub_util | 14 from common import pubsub_util |
| 15 from common.pipeline_wrapper import BasePipeline | 15 from common.pipeline_wrapper import BasePipeline |
| 16 from common.pipeline_wrapper import pipeline | 16 from common.pipeline_wrapper import pipeline |
| 17 from crash import fracas | 17 from crash import fracas |
| 18 from model import analysis_status | 18 from model import analysis_status |
| 19 from model.crash.crash_config import CrashConfig | 19 from model.crash.crash_config import CrashConfig |
| 20 from model.crash.fracas_crash_analysis import FracasCrashAnalysis | 20 from model.crash.fracas_crash_analysis import FracasCrashAnalysis |
| 21 | 21 |
| 22 | 22 |
| 23 class FracasBasePipeline(BasePipeline): | 23 class FracasBasePipeline(BasePipeline): |
| 24 def __init__(self, channel, platform, signature): | 24 def __init__(self, crash_identifiers): |
| 25 super(FracasBasePipeline, self).__init__( | 25 super(FracasBasePipeline, self).__init__(crash_identifiers) |
| 26 channel, platform, signature) | 26 self.crash_identifiers = crash_identifiers |
| 27 self.channel = channel | |
| 28 self.platform = platform | |
| 29 self.signature = signature | |
| 30 | 27 |
| 31 def run(self, *args, **kwargs): | 28 def run(self, *args, **kwargs): |
| 32 raise NotImplementedError() | 29 raise NotImplementedError() |
| 33 | 30 |
| 34 | 31 |
| 35 class FracasAnalysisPipeline(FracasBasePipeline): | 32 class FracasAnalysisPipeline(FracasBasePipeline): |
| 36 def _SetErrorIfAborted(self, aborted): | 33 def _SetErrorIfAborted(self, aborted): |
| 37 if not aborted: | 34 if not aborted: |
| 38 return | 35 return |
| 39 | 36 |
| 40 logging.error('Aborted analysis for %s, %s, %s', | 37 logging.error('Aborted analysis for %s', repr(self.crash_identifiers)) |
| 41 self.channel, self.platform, self.signature) | 38 analysis = FracasCrashAnalysis.Get(self.crash_identifiers) |
| 42 analysis = FracasCrashAnalysis.Get( | |
| 43 self.channel, self.platform, self.signature) | |
| 44 analysis.status = analysis_status.ERROR | 39 analysis.status = analysis_status.ERROR |
| 45 analysis.put() | 40 analysis.put() |
| 46 | 41 |
| 47 def finalized(self): | 42 def finalized(self): |
| 48 self._SetErrorIfAborted(self.was_aborted) | 43 self._SetErrorIfAborted(self.was_aborted) |
| 49 | 44 |
| 50 # Arguments number differs from overridden method - pylint: disable=W0221 | 45 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 51 def run(self, channel, platform, signature): | 46 def run(self, crash_identifiers): |
| 52 analysis = FracasCrashAnalysis.Get(channel, platform, signature) | 47 analysis = FracasCrashAnalysis.Get(crash_identifiers) |
| 53 | 48 |
| 54 # Update analysis status. | 49 # Update analysis status. |
| 55 analysis.pipeline_status_path = self.pipeline_status_path() | 50 analysis.pipeline_status_path = self.pipeline_status_path() |
| 56 analysis.status = analysis_status.RUNNING | 51 analysis.status = analysis_status.RUNNING |
| 57 analysis.started_time = datetime.datetime.utcnow() | 52 analysis.started_time = datetime.datetime.utcnow() |
| 58 analysis.findit_version = appengine_util.GetCurrentVersion() | 53 analysis.findit_version = appengine_util.GetCurrentVersion() |
| 59 analysis.put() | 54 analysis.put() |
| 60 | 55 |
| 61 # Run the analysis. | 56 # Run the analysis. |
| 62 result, tags = fracas.FindCulpritForChromeCrash( | 57 result, tags = fracas.FindCulpritForChromeCrash( |
| 63 channel, platform, signature, analysis.stack_trace, | 58 analysis.channel, analysis.platform, analysis.signature, |
| 64 analysis.crashed_version, analysis.versions_to_cpm) | 59 analysis.stack_trace, analysis.crashed_version, |
| 60 analysis.historic_metadata) | |
| 65 | 61 |
| 66 # Update analysis status and save the analysis result. | 62 # Update analysis status and save the analysis result. |
| 67 analysis.completed_time = datetime.datetime.utcnow() | 63 analysis.completed_time = datetime.datetime.utcnow() |
| 68 analysis.result = result | 64 analysis.result = result |
| 69 for tag_name, tag_value in tags.iteritems(): | 65 for tag_name, tag_value in tags.iteritems(): |
| 70 # TODO(http://crbug.com/602702): make it possible to add arbitrary tags. | 66 # TODO(http://crbug.com/602702): make it possible to add arbitrary tags. |
| 71 if hasattr(analysis, tag_name): | 67 if hasattr(analysis, tag_name): |
| 72 setattr(analysis, tag_name, tag_value) | 68 setattr(analysis, tag_name, tag_value) |
| 73 analysis.status = analysis_status.COMPLETED | 69 analysis.status = analysis_status.COMPLETED |
| 74 analysis.put() | 70 analysis.put() |
| 75 | 71 |
| 76 | 72 |
| 77 class PublishResultPipeline(FracasBasePipeline): | 73 class PublishResultPipeline(FracasBasePipeline): |
| 78 def finalized(self): | 74 def finalized(self): |
| 79 if self.was_aborted: # pragma: no cover. | 75 if self.was_aborted: # pragma: no cover. |
| 80 logging.error('Failed to publish analysis result for %s, %s, %s', | 76 logging.error('Failed to publish analysis result for %s', |
| 81 self.channel, self.platform, self.signature) | 77 repr(self.crash_identifiers)) |
| 82 | 78 |
| 83 # Arguments number differs from overridden method - pylint: disable=W0221 | 79 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 84 def run(self, channel, platform, signature): | 80 def run(self, crash_identifiers): |
| 85 analysis = FracasCrashAnalysis.Get(channel, platform, signature) | 81 analysis = FracasCrashAnalysis.Get(crash_identifiers) |
| 86 result = { | 82 result = { |
| 87 'channel': channel, | 83 'crash_identifiers': crash_identifiers, |
| 88 'platform': platform, | |
| 89 'signature': signature, | |
| 90 'result': analysis.result, | 84 'result': analysis.result, |
| 91 } | 85 } |
| 92 messages_data = [json.dumps(result, sort_keys=True)] | 86 messages_data = [json.dumps(result, sort_keys=True)] |
| 93 | 87 |
| 94 crash_config = CrashConfig.Get() | 88 crash_config = CrashConfig.Get() |
| 95 topic = crash_config.fracas['analysis_result_pubsub_topic'] | 89 topic = crash_config.fracas['analysis_result_pubsub_topic'] |
| 96 pubsub_util.PublishMessagesToTopic(messages_data, topic) | 90 pubsub_util.PublishMessagesToTopic(messages_data, topic) |
| 97 logging.info('Published analysis result for %s, %s, %s', | 91 logging.info('Published analysis result for %s', repr(crash_identifiers)) |
| 98 channel, platform, signature) | |
| 99 | 92 |
| 100 | 93 |
| 101 class FracasCrashWrapperPipeline(BasePipeline): | 94 class FracasCrashWrapperPipeline(BasePipeline): |
| 102 # Arguments number differs from overridden method - pylint: disable=W0221 | 95 # Arguments number differs from overridden method - pylint: disable=W0221 |
| 103 def run(self, channel, platform, signature): | 96 def run(self, crash_identifiers): |
| 104 run_analysis = yield FracasAnalysisPipeline(channel, platform, signature) | 97 run_analysis = yield FracasAnalysisPipeline(crash_identifiers) |
| 105 with pipeline.After(run_analysis): | 98 with pipeline.After(run_analysis): |
| 106 yield PublishResultPipeline(channel, platform, signature) | 99 yield PublishResultPipeline(crash_identifiers) |
| 107 | 100 |
| 108 | 101 |
| 109 @ndb.transactional | 102 @ndb.transactional |
| 110 def _NeedsNewAnalysis( | 103 def _NeedsNewAnalysis( |
| 111 channel, platform, signature, stack_trace, chrome_version, versions_to_cpm): | 104 crash_identifiers, chrome_version, signature, client_id, |
| 112 analysis = FracasCrashAnalysis.Get(channel, platform, signature) | 105 platform, stack_trace, channel, historic_metadata): |
| 106 analysis = FracasCrashAnalysis.Get(crash_identifiers) | |
| 113 if analysis and not analysis.failed: | 107 if analysis and not analysis.failed: |
| 114 # A new analysis is not needed if last one didn't complete or succeeded. | 108 # A new analysis is not needed if last one didn't complete or succeeded. |
| 115 # TODO(http://crbug.com/600535): re-analyze if stack trace or regression | 109 # TODO(http://crbug.com/600535): re-analyze if stack trace or regression |
| 116 # range changed. | 110 # range changed. |
| 111 print 'lala' | |
|
stgao
2016/05/04 05:55:43
nit: leftover of local debugging?
Sharu Jiang
2016/05/04 18:34:49
Sorry, commit it in a hurry, forgot to delete it.
| |
| 117 return False | 112 return False |
| 118 | 113 |
| 119 if not analysis: | 114 if not analysis: |
| 120 # A new analysis is needed if there is no analysis yet. | 115 # A new analysis is needed if there is no analysis yet. |
| 121 analysis = FracasCrashAnalysis.Create(channel, platform, signature) | 116 analysis = FracasCrashAnalysis.Create(crash_identifiers) |
| 122 | 117 |
| 123 analysis.Reset() | 118 analysis.Reset() |
| 119 | |
| 120 # Set common properties. | |
| 124 analysis.crashed_version = chrome_version | 121 analysis.crashed_version = chrome_version |
| 125 analysis.stack_trace = stack_trace | 122 analysis.stack_trace = stack_trace |
| 126 analysis.versions_to_cpm = versions_to_cpm | 123 analysis.signature = signature |
| 124 analysis.platform = platform | |
| 125 analysis.client_id = client_id | |
| 126 | |
| 127 # Set customized properties. | |
| 128 analysis.historic_metadata = historic_metadata | |
| 129 analysis.channel = channel | |
| 130 | |
| 131 # Set analysis progress properties. | |
| 127 analysis.status = analysis_status.PENDING | 132 analysis.status = analysis_status.PENDING |
| 128 analysis.requested_time = datetime.datetime.utcnow() | 133 analysis.requested_time = datetime.datetime.utcnow() |
| 134 | |
| 129 analysis.put() | 135 analysis.put() |
| 136 | |
| 130 return True | 137 return True |
| 131 | 138 |
| 132 | 139 |
| 133 def ScheduleNewAnalysisForCrash( | 140 def ScheduleNewAnalysisForCrash( |
| 134 channel, platform, signature, stack_trace, chrome_version, versions_to_cpm, | 141 crash_identifiers, chrome_version, signature, client_id, |
| 142 platform, stack_trace, channel, historic_metadata, | |
| 135 queue_name=constants.DEFAULT_QUEUE): | 143 queue_name=constants.DEFAULT_QUEUE): |
| 136 """Schedules an analysis.""" | 144 """Schedules an analysis.""" |
| 137 crash_config = CrashConfig.Get() | 145 crash_config = CrashConfig.Get() |
| 138 if platform not in crash_config.fracas.get( | 146 if platform not in crash_config.fracas.get( |
| 139 'supported_platform_list_by_channel', {}).get(channel, []): | 147 'supported_platform_list_by_channel', {}).get(channel, []): |
| 140 # Bail out if either the channel or platform is not supported yet. | 148 # Bail out if either the channel or platform is not supported yet. |
| 141 return False | 149 return False |
| 142 | 150 |
| 143 if _NeedsNewAnalysis(channel, platform, signature, stack_trace, | 151 if _NeedsNewAnalysis(crash_identifiers, chrome_version, signature, client_id, |
| 144 chrome_version, versions_to_cpm): | 152 platform, stack_trace, channel, historic_metadata): |
| 145 analysis_pipeline = FracasCrashWrapperPipeline(channel, platform, signature) | 153 analysis_pipeline = FracasCrashWrapperPipeline(crash_identifiers) |
| 146 analysis_pipeline.target = appengine_util.GetTargetNameForModule( | 154 analysis_pipeline.target = appengine_util.GetTargetNameForModule( |
| 147 constants.CRASH_BACKEND_FRACAS) | 155 constants.CRASH_BACKEND_FRACAS) |
| 148 analysis_pipeline.start(queue_name=queue_name) | 156 analysis_pipeline.start(queue_name=queue_name) |
| 149 logging.info('New analysis is scheduled for %s, %s, %s', | 157 logging.info('New analysis is scheduled for %s', repr(crash_identifiers)) |
| 150 channel, platform, signature) | |
| 151 return True | 158 return True |
| 152 | 159 |
| 153 return False | 160 return False |
| OLD | NEW |