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

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

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

Powered by Google App Engine
This is Rietveld 408576698