Bug 1344346 - [mozharness] Ensure StructuredOutputParser runs 'process_output' messages through the error lists, r?jgraham
Currently the StructuredOutputParser validates all unstructured output against a series of error lists (regexes). However,
before this happens, the mochitest harness is converting all unstructured output to structured 'process_output' messages.
This means that Gecko output is not being checked against the error regexes.
This change ensure that in addition to unstructured output, we also validate 'process_output' messages against the error
lists.
MozReview-Commit-ID: DG6sZqpg5aw
--- a/testing/mozharness/mozharness/mozilla/structuredlog.py
+++ b/testing/mozharness/mozharness/mozilla/structuredlog.py
@@ -42,25 +42,20 @@ class StructuredOutputParser(OutputParse
def _get_mozlog_module(self):
try:
import mozlog
except ImportError:
self.fatal("A script class using structured logging must inherit "
"from the MozbaseMixin to ensure that mozlog is available.")
return mozlog
- def _handle_unstructured_output(self, line):
- if self.strict:
- self.critical(("Test harness output was not a valid structured log message: "
- "\n%s") % line)
- self.update_levels(TBPL_FAILURE, log.CRITICAL)
- return
+ def _handle_unstructured_output(self, line, log_output=True):
+ self.log_output = log_output
super(StructuredOutputParser, self).parse_single_line(line)
-
def parse_single_line(self, line):
"""Parses a line of log output from the child process and passes
it to mozlog to update the overall status of the run.
Re-emits the logged line in human-readable format.
"""
level = INFO
tbpl_level = TBPL_SUCCESS
@@ -69,22 +64,32 @@ class StructuredOutputParser(OutputParse
candidate_data = json.loads(line)
if (isinstance(candidate_data, dict) and
'action' in candidate_data and candidate_data['action'] in self.log_actions):
data = candidate_data
except ValueError:
pass
if data is None:
- self._handle_unstructured_output(line)
+ if self.strict:
+ self.critical(("Test harness output was not a valid structured log message: "
+ "\n%s") % line)
+ self.update_levels(TBPL_FAILURE, log.CRITICAL)
+ else:
+ self._handle_unstructured_output(line)
return
self.handler(data)
action = data["action"]
+ if action == "process_output":
+ # Run process output through the error lists, but make sure the super parser
+ # doesn't print them to stdout (they should go through the log formatter).
+ self._handle_unstructured_output(data['data'], log_output=False)
+
if action == "log":
level = getattr(log, data["level"].upper())
log_data = self.formatter(data)
if log_data is not None:
self.log(log_data, level=level)
self.update_levels(tbpl_level, level)