Bug 985857 - Automatically log mach output and add a command to display it. r=gps

This commit is contained in:
Mike Hommey 2015-06-05 13:59:05 +09:00
Родитель eb5db88588
Коммит ad90bd664a
2 изменённых файлов: 76 добавлений и 0 удалений

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

@ -700,6 +700,20 @@ class MachCommandBase(MozbuildObject):
sys.exit(1)
# Always keep a log of the last command, but don't do that for mach
# invokations from scripts (especially not the ones done by the build
# system itself).
if (self.log_manager and self.log_manager.terminal and
not getattr(self, 'NO_AUTO_LOG', False)):
self._ensure_state_subdir_exists('.')
logfile = self._get_state_filename('last_log.json')
try:
fd = open(logfile, "wb")
self.log_manager.add_json_handler(fd)
except Exception as e:
self.log(logging.WARNING, 'mach', {'error': e},
'Log will not be kept for this command: {error}.')
class MachCommandConditions(object):
"""A series of commonly used condition functions which can be applied to

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

@ -4,10 +4,13 @@
from __future__ import print_function, unicode_literals
import argparse
import itertools
import json
import logging
import operator
import os
import subprocess
import sys
import mozpack.path as mozpath
@ -566,6 +569,65 @@ class Doctor(MachCommandBase):
doctor = Doctor(self.topsrcdir, self.topobjdir, fix)
return doctor.check_all()
@CommandProvider
class Logs(MachCommandBase):
"""Provide commands to read mach logs."""
NO_AUTO_LOG = True
@Command('show-log', category='post-build',
description='Display mach logs')
@CommandArgument('log_file', nargs='?', type=argparse.FileType('rb'),
help='Filename to read log data from. Defaults to the log of the last '
'mach command.')
def show_log(self, log_file=None):
if not log_file:
path = self._get_state_filename('last_log.json')
log_file = open(path, 'rb')
if self.log_manager.terminal:
env = dict(os.environ)
if 'LESS' not in env:
# Sensible default flags if none have been set in the user
# environment.
env['LESS'] = 'FRX'
less = subprocess.Popen(['less'], stdin=subprocess.PIPE, env=env)
# Various objects already have a reference to sys.stdout, so we
# can't just change it, we need to change the file descriptor under
# it to redirect to less's input.
# First keep a copy of the sys.stdout file descriptor.
output_fd = os.dup(sys.stdout.fileno())
os.dup2(less.stdin.fileno(), sys.stdout.fileno())
startTime = 0
for line in log_file:
created, action, params = json.loads(line)
if not startTime:
startTime = created
self.log_manager.terminal_handler.formatter.start_time = \
created
if 'line' in params:
record = logging.makeLogRecord({
'created': created,
'name': self._logger.name,
'levelno': logging.INFO,
'msg': '{line}',
'params': params,
'action': action,
})
self._logger.handle(record)
if self.log_manager.terminal:
# Close less's input so that it knows that we're done sending data.
less.stdin.close()
# Since the less's input file descriptor is now also the stdout
# file descriptor, we still actually have a non-closed system file
# descriptor for less's input. Replacing sys.stdout's file
# descriptor with what it was before we replaced it will properly
# close less's input.
os.dup2(output_fd, sys.stdout.fileno())
less.wait()
@CommandProvider
class Warnings(MachCommandBase):
"""Provide commands for inspecting warnings."""