зеркало из https://github.com/mozilla/gecko-dev.git
Bug 985857 - Automatically log mach output and add a command to display it. r=gps
This commit is contained in:
Родитель
eb5db88588
Коммит
ad90bd664a
|
@ -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."""
|
||||
|
|
Загрузка…
Ссылка в новой задаче