# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Upload a single build command stats file to appengine.""" from __future__ import print_function import re import sys from chromite.cbuildbot import constants from chromite.lib import commandline from chromite.lib import cros_build_lib from chromite.lib import cros_logging as logging from chromite.lib import stats FILE_LOAD_ERROR = 'Error loading %s' UNCAUGHT_ERROR = 'Uncaught command stats exception.' class LoadError(RuntimeError): """Error during loading of stats file.""" class StatsLoader(object): """Loads stats from a file.""" @classmethod def LoadFile(cls, stat_file): """Return a Stats object constructed from contents of |stat_file|.""" with open(stat_file, 'r') as f: first_line = f.readline().rstrip() match = re.match(r'Chromium OS .+ Version (\d+)$', first_line) if not match: raise LoadError('Stats file not in expected format') version = int(match.group(1)) loader = cls._GetLinesLoader(version) if not loader: raise LoadError('Stats file version %s not supported.' % version) return loader(f.readlines()) @classmethod def _GetLinesLoader(cls, version): LOADERS = ( None, cls._LoadLinesV1, # Version 1 loader (at index 1) ) if version < len(LOADERS) and version >= 0: return LOADERS[version] return None @classmethod def _LoadLinesV1(cls, stat_lines): """Load stat lines in Version 1 format.""" data = {} for line in stat_lines: # Each line has following format: # attribute_name Rest of line is value for attribute_name # Note that some attributes may have no value after their name. attr, _sep, value = line.rstrip().partition(' ') if not attr: attr = line.rstrip() data[attr] = value return stats.Stats(**data) def main(argv): """Main function.""" # This is not meant to be a user-friendly script. It takes one and # only one argument, which is a build stats file to be uploaded epilog = ( 'This script is not intended to be run manually. It is used as' ' part of the build command statistics project.' ) in_golo = cros_build_lib.GetHostDomain().endswith(constants.GOLO_DOMAIN) debug_level = commandline.ArgumentParser.DEFAULT_LOG_LEVEL if in_golo: debug_level = 'debug' parser = commandline.ArgumentParser( epilog=epilog, default_log_level=debug_level) parser.add_argument( 'build_stats_file', nargs=1, default=None) options = parser.parse_args(argv) try: cmd_stats = StatsLoader.LoadFile(options.build_stats_file[0]) except LoadError: logging.error(FILE_LOAD_ERROR, options.build_stats_file[0], exc_info=True) sys.exit(1) try: stats.StatsUploader.Upload(cmd_stats) except Exception: logging.error(UNCAUGHT_ERROR, exc_info=True) sys.exit(1)