# HG changeset patch # User Chris Manchester # Date 1553726568 0 # Node ID 827ad1eecbbb526dcc0ea154cdf2c8c3c2921c03 # Parent fa01e55c0a48703dbc78d3b6d704e660465ac66a Bug 1526072 - Record cpu utilization and clobber/full builds in build telemetry. r=nalexander Differential Revision: https://phabricator.services.mozilla.com/D22630 diff --git a/python/mach/mach/base.py b/python/mach/mach/base.py --- a/python/mach/mach/base.py +++ b/python/mach/mach/base.py @@ -7,16 +7,17 @@ from __future__ import absolute_import, class CommandContext(object): """Holds run-time state so it can easily be passed to command providers.""" def __init__(self, cwd=None, settings=None, log_manager=None, commands=None, **kwargs): self.cwd = cwd self.settings = settings self.log_manager = log_manager self.commands = commands + self.command_attrs = {} for k, v in kwargs.items(): setattr(self, k, v) class MachError(Exception): """Base class for all errors raised by mach itself.""" diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py --- a/python/mozbuild/mozbuild/controller/building.py +++ b/python/mozbuild/mozbuild/controller/building.py @@ -955,23 +955,28 @@ class CCacheStats(object): return '%.1f Mbytes' % (float(v) / CCacheStats.MiB) else: return '%.1f Kbytes' % (float(v) / CCacheStats.KiB) class BuildDriver(MozbuildObject): """Provides a high-level API for build actions.""" + def __init__(self, *args, **kwargs): + MozbuildObject.__init__(self, *args, **kwargs) + self.mach_context = None + def build(self, what=None, disable_extra_make_dependencies=None, jobs=0, directory=None, verbose=False, keep_going=False, mach_context=None): """Invoke the build backend. ``what`` defines the thing to build. If not defined, the default target is used. """ + self.mach_context = mach_context warnings_path = self._get_state_filename('warnings.json') monitor = self._spawn(BuildMonitor) monitor.init(warnings_path) ccache_start = monitor.ccache_stats() footer = BuildProgressFooter(self.log_manager.terminal, monitor) # Disable indexing in objdir because it is not necessary and can slow # down builds. @@ -1031,21 +1036,25 @@ class BuildDriver(MozbuildObject): if not os.path.isfile(mozpath.join(self.topobjdir, output)): return True dep_file = '%s.in' % backend_file return build_out_of_date(backend_file, dep_file) monitor.start_resource_recording() + self.mach_context.command_attrs['clobber'] = False config = None try: config = self.config_environment except Exception: - pass + # If we don't already have a config environment this is either + # a fresh objdir or $OBJDIR/config.status has been removed for + # some reason, which indicates a clobber of sorts. + self.mach_context.command_attrs['clobber'] = True # Record whether a clobber was requested so we can print # a special message later if the build fails. clobber_requested = False # Write out any changes to the current mozconfig in case # they should invalidate configure. self._write_mozconfig_json() @@ -1204,16 +1213,21 @@ class BuildDriver(MozbuildObject): "failing the build due to exception: {ex}.") if not status: # If the underlying build provided a failing status, pass # it through; otherwise, fail. status = 1 monitor.finish(record_usage=status == 0) + if status == 0: + usage = monitor.get_resource_usage() + if usage: + self.mach_context.command_attrs['usage'] = usage + # Print the collected compiler warnings. This is redundant with # inline output from the compiler itself. However, unlike inline # output, this list is sorted and grouped by file, making it # easier to triage output. # # Only do this if we had a successful build. If the build failed, # there are more important things in the log to look for than # whatever code we warned about. @@ -1512,16 +1526,18 @@ class BuildDriver(MozbuildObject): res = clobberer.maybe_do_clobber(os.getcwd(), auto_clobber, clobber_output) clobber_output.seek(0) for line in clobber_output.readlines(): self.log(logging.WARNING, 'clobber', {'msg': line.rstrip()}, '{msg}') clobber_required, clobber_performed, clobber_message = res + if self.mach_context is not None and clobber_performed: + self.mach_context.command_attrs['clobber'] = True if not clobber_required or clobber_performed: if clobber_performed and env.get('TINDERBOX_OUTPUT'): self.log(logging.WARNING, 'clobber', {'msg': 'TinderboxPrint: auto clobber'}, '{msg}') else: for line in clobber_message.splitlines(): self.log(logging.WARNING, 'clobber', {'msg': line.rstrip()}, '{msg}')