OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2015 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 logging | |
6 | |
7 from pipeline_utils.appengine_third_party_pipeline_src_pipeline import pipeline | |
8 | |
9 from common.http_client_appengine import HttpClientAppengine as HttpClient | |
10 from model.step import Step | |
11 from waterfall import buildbot | |
12 from waterfall import extractors | |
13 from waterfall import lock_util | |
14 from waterfall.base_pipeline import BasePipeline | |
15 | |
16 | |
17 class ExtractSignalPipeline(BasePipeline): | |
18 """A pipeline to extract failure signals from each failed step. | |
19 | |
20 Input: | |
21 It is output of pipeline DetectFirstFailurePipeline. | |
22 | |
23 Output: | |
24 It is a json like below: | |
qyearsley
2015/01/15 21:15:03
The below is a dict, not JSON. It is true that the
stgao
2015/01/16 20:21:39
Good point.
Docstring was updated.
| |
25 { | |
26 'step_name1': waterfall.failure_signal.FailureSignal.ToJson(), | |
27 ... | |
28 } | |
29 """ | |
30 | |
31 HTTP_CLIENT = HttpClient() | |
32 | |
33 # Arguments number differs from overridden method - pylint: disable=W0221 | |
34 def run(self, failure_info): | |
qyearsley
2015/01/15 21:15:03
Rather than putting Input and Output above, I sugg
stgao
2015/01/16 20:21:39
Done.
| |
35 signals = {} | |
36 | |
37 master_name = failure_info['master_name'] | |
38 builder_name = failure_info['builder_name'] | |
39 build_number = failure_info['build_number'] | |
40 for step_name in failure_info['failed_steps']: | |
41 step = Step.GetStep(master_name, builder_name, build_number, step_name) | |
42 if step and step.log_data: | |
43 stdio_log = step.log_data | |
44 else: | |
45 if not lock_util.WaitUntilDownloadAllowed( | |
46 master_name): # pragma: no cover | |
47 raise pipeline.Retry('Failed to pull stdio of step %s of master %s' | |
48 % (step_name, master_name)) | |
49 | |
50 # TODO: do test-level analysis instead of step-level. | |
51 stdio_log = buildbot.GetStepStdio( | |
52 master_name, builder_name, build_number, step_name, | |
53 self.HTTP_CLIENT) | |
54 if not stdio_log: # pragma: no cover | |
55 raise pipeline.Retry('Failed to pull stdio of step %s of master %s' | |
56 % (step_name, master_name)) | |
57 | |
58 # Save stdio in datastore and avoid downloading again during retry. | |
59 if not step: # pragma: no cover | |
60 step = Step.CreateStep( | |
61 master_name, builder_name, build_number, step_name) | |
62 | |
63 step.log_data = stdio_log | |
64 try: | |
65 step.put() | |
66 except Exception as e: # pragma: no cover | |
67 # Sometimes, the stdio log is too large to save in datastore. | |
68 logging.exception(e) | |
69 | |
70 # TODO: save result in datastore? | |
71 signals[step_name] = extractors.ExtractSignal( | |
72 master_name, builder_name, step_name, None, stdio_log).ToJson() | |
qyearsley
2015/01/15 21:15:03
Looking at the FailureSignal.ToJson method[1] - it
stgao
2015/01/16 20:21:39
Good point.
But let's do the rename in a separate
qyearsley
2015/01/16 22:55:25
SGTM
| |
73 | |
74 return signals | |
OLD | NEW |