Bug 977071 - Add run_info to structured log suite_start message and fix some small bugs. r=ahal

This commit is contained in:
James Graham 2014-02-10 20:21:18 +00:00
Родитель 17256c358d
Коммит 2f81ee2a85
7 изменённых файлов: 36 добавлений и 25 удалений

Просмотреть файл

@ -9,8 +9,7 @@ It simply wraps Python's logging_ module and adds a few convenience methods
for logging test results and events. for logging test results and events.
The structured submodule takes a different approach and implements a The structured submodule takes a different approach and implements a
JSON-based logging protocol designed for recording test results. JSON-based logging protocol designed for recording test results."""
"""
from logger import * from logger import *
from loglistener import LogMessageServer from loglistener import LogMessageServer
@ -22,3 +21,4 @@ except ImportError:
# Structured logging doesn't work on python 2.6 which is still used on some # Structured logging doesn't work on python 2.6 which is still used on some
# legacy test machines; https://bugzilla.mozilla.org/show_bug.cgi?id=864866 # legacy test machines; https://bugzilla.mozilla.org/show_bug.cgi?id=864866
pass pass

Просмотреть файл

@ -15,6 +15,7 @@ log_formatters = {
'xunit': (formatters.XUnitFormatter, "xUnit compatible XML"), 'xunit': (formatters.XUnitFormatter, "xUnit compatible XML"),
'html': (formatters.HTMLFormatter, "HTML report"), 'html': (formatters.HTMLFormatter, "HTML report"),
'mach': (formatters.MachFormatter, "Uncolored mach-like output"), 'mach': (formatters.MachFormatter, "Uncolored mach-like output"),
'mach_terminal': (formatters.MachTerminalFormatter, "Colored mach-like output for use in a tty"),
} }
@ -42,7 +43,7 @@ def add_logging_group(parser):
"and takes a filename to write that format to, " "and takes a filename to write that format to, "
"or '-' to write to stdout.") "or '-' to write to stdout.")
for name, (cls, help_str) in log_formatters.iteritems(): for name, (cls, help_str) in log_formatters.iteritems():
group.add_argument("--log-" + name, type=log_file, group.add_argument("--log-" + name, action="append", type=log_file,
help=help_str) help=help_str)
@ -51,8 +52,8 @@ def setup_logging(suite, args, defaults):
Configure a structuredlogger based on command line arguments. Configure a structuredlogger based on command line arguments.
:param suite: The name of the testsuite being run :param suite: The name of the testsuite being run
:param args: The Namespace object produced by argparse from parsing :param args: A dictionary of {argument_name:value} produced from
command line arguments from a parser with logging arguments. parsing the command line arguments for the application
:param defaults: A dictionary of {formatter name: output stream} to apply :param defaults: A dictionary of {formatter name: output stream} to apply
when there is no logging supplied on the command line. when there is no logging supplied on the command line.
@ -62,14 +63,15 @@ def setup_logging(suite, args, defaults):
prefix = "log_" prefix = "log_"
found = False found = False
found_stdout_logger = False found_stdout_logger = False
for name, value in args.iteritems(): for name, values in args.iteritems():
if name.startswith(prefix) and value is not None: if name.startswith(prefix) and values is not None:
found = True for value in values:
if value == sys.stdout: found = True
found_stdout_logger = True if value == sys.stdout:
formatter_cls = log_formatters[name[len(prefix):]][0] found_stdout_logger = True
logger.add_handler(handlers.StreamHandler(stream=value, formatter_cls = log_formatters[name[len(prefix):]][0]
formatter=formatter_cls())) logger.add_handler(handlers.StreamHandler(stream=value,
formatter=formatter_cls()))
#If there is no user-specified logging, go with the default options #If there is no user-specified logging, go with the default options
if not found: if not found:

Просмотреть файл

@ -8,4 +8,5 @@ from xunit import XUnitFormatter
from html import HTMLFormatter from html import HTMLFormatter
from machformatter import MachFormatter, MachTerminalFormatter from machformatter import MachFormatter, MachTerminalFormatter
JSONFormatter = lambda: json.dumps def JSONFormatter():
return lambda x: json.dumps(x) + "\n"

Просмотреть файл

@ -4,6 +4,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys import sys
import json
import datetime import datetime
import os import os

Просмотреть файл

@ -29,7 +29,7 @@ class BaseMachFormatter(base.BaseFormatter):
return "%s %s\n" % (self.generic_formatter(data), s) return "%s %s\n" % (self.generic_formatter(data), s)
def _get_test_id(self, data): def _get_test_id(self, data):
test_id = data["test"] test_id = data.get("test")
if isinstance(test_id, list): if isinstance(test_id, list):
test_id = tuple(test_id) test_id = tuple(test_id)
return test_id return test_id
@ -62,12 +62,13 @@ class BaseMachFormatter(base.BaseFormatter):
def test_status(self, data): def test_status(self, data):
test = self._get_test_id(data) test = self._get_test_id(data)
if test not in self.status_buffer: if test not in self.status_buffer:
self.buffer[test] = {"count": 0, "unexpected": 0, "pass": 0} self.status_buffer[test] = {"count": 0, "unexpected": 0, "pass": 0}
self.buffer[test]["count"] += 1 self.status_buffer[test]["count"] += 1
if "expected" in data: if "expected" in data:
self.buffer[test]["unexpected"] += 1 self.status_buffer[test]["unexpected"] += 1
if data["status"] == "PASS": if data["status"] == "PASS":
self.buffer[test]["pass"] += 1 self.status_buffer[test]["pass"] += 1
def process_output(self, data): def process_output(self, data):
return '"%s" (pid:%s command:%s)' % (data["data"], return '"%s" (pid:%s command:%s)' % (data["data"],
@ -132,9 +133,9 @@ class MachTerminalFormatter(BaseMachFormatter):
def __call__(self, data): def __call__(self, data):
s = BaseMachFormatter.__call__(self, data) s = BaseMachFormatter.__call__(self, data)
if s is not None: if s is not None:
t = self.terminal.blue(format_seconds(self._time(entry))) t = self.terminal.blue(format_seconds(self._time(data)))
return '%s %s' % (t, self._colorize(entry, s)) return '%s %s' % (t, self._colorize(data, s))
def _colorize(self, data, s): def _colorize(self, data, s):
if self.terminal is None: if self.terminal is None:
@ -155,6 +156,8 @@ class MachTerminalFormatter(BaseMachFormatter):
if color is not None: if color is not None:
result = color(s[:len_action]) + s[len_action:] result = color(s[:len_action]) + s[len_action:]
else:
result = s
return result return result

Просмотреть файл

@ -4,6 +4,8 @@
from threading import Lock from threading import Lock
from ..structuredlog import log_levels
class BaseHandler(object): class BaseHandler(object):
def __init__(self, formatter=str): def __init__(self, formatter=str):

Просмотреть файл

@ -104,12 +104,15 @@ class StructuredLogger(object):
all_data.update(data) all_data.update(data)
return all_data return all_data
def suite_start(self, tests): def suite_start(self, tests, run_info=None):
"""Log a suite_start message """Log a suite_start message
:param tests: List of test identifiers that will be run in the suite. :param tests: List of test identifiers that will be run in the suite.
""" """
self._log_data("suite_start", {"tests": tests}) data = {"tests": tests}
if run_info is not None:
data["run_info"] = run_info
self._log_data("suite_start", data)
def suite_end(self): def suite_end(self):
"""Log a suite_end message""" """Log a suite_end message"""
@ -171,8 +174,7 @@ class StructuredLogger(object):
self._log_data("test_end", data) self._log_data("test_end", data)
def process_output(self, process, data, command=None): def process_output(self, process, data, command=None):
""" """Log output from a managed process.
Log output from a managed process.
:param process: A unique identifier for the process producing the output :param process: A unique identifier for the process producing the output
(typically the pid) (typically the pid)