Chromium Code Reviews| Index: client/utils/logging_utils.py |
| diff --git a/appengine/swarming/swarming_bot/logging_utils.py b/client/utils/logging_utils.py |
| similarity index 59% |
| rename from appengine/swarming/swarming_bot/logging_utils.py |
| rename to client/utils/logging_utils.py |
| index efddb9c99c8da8360341115449ff09bc87aa0568..f44880e7277ec0110f823163748f1883e1480be2 100644 |
| --- a/appengine/swarming/swarming_bot/logging_utils.py |
| +++ b/client/utils/logging_utils.py |
| @@ -1,16 +1,14 @@ |
| -# Copyright 2014 The Swarming Authors. All rights reserved. |
| -# Use of this source code is governed by the Apache v2.0 license that can be |
| -# found in the LICENSE file. |
| +# Copyright 2015 The Swarming Authors. All rights reserved. |
| +# Use of this source code is governed under the Apache License, Version 2.0 that |
| +# can be found in the LICENSE file. |
| -"""Utility relating to logging. |
| - |
| -TODO(maruel): Merge buffering and output related code from client/utils/tools.py |
| -in a single file. |
| -""" |
| +"""Utility relating to logging.""" |
| +import argparse |
| import codecs |
| import logging |
| import logging.handlers |
| +import optparse |
| import os |
| import sys |
| import tempfile |
| @@ -58,6 +56,10 @@ else: # Not Windows. |
| NoInheritRotatingFileHandler = logging.handlers.RotatingFileHandler |
| +# Levels used for logging. |
| +LEVELS = [logging.ERROR, logging.INFO, logging.DEBUG] |
| + |
| + |
| class CaptureLogs(object): |
| """Captures all the logs in a context.""" |
| def __init__(self, prefix, root=None): |
| @@ -134,6 +136,11 @@ def prepare_logging(filename, root=None): |
| Makes it log in UTC all the time. Prepare a rotating file based log. |
| """ |
| assert not find_stderr(root) |
| + # Other options are: |
| + # '%(levelname)5s %(relativeCreated)6d %(module)15s(%(lineno)3d): ' |
| + # '%(message)s' |
| + # or: |
| + # '%(asctime)s %(levelname)-8s %(module)15s(%(lineno)3d): %(message)s')) |
| formatter = UTCFormatter( |
| '%(process)d %(asctime)s: %(levelname)-5s %(message)s') |
|
Vadim Sh.
2015/07/15 18:46:38
consider also https://chromium.googlesource.com/in
|
| @@ -153,7 +160,8 @@ def prepare_logging(filename, root=None): |
| if filename: |
| try: |
| rotating_file = NoInheritRotatingFileHandler( |
| - filename, maxBytes=10 * 1024 * 1024, backupCount=5) |
| + filename, maxBytes=10 * 1024 * 1024, backupCount=5, |
| + encoding='utf-8') |
| rotating_file.setLevel(logging.DEBUG) |
| rotating_file.setFormatter(formatter) |
| logger.addHandler(rotating_file) |
| @@ -166,3 +174,81 @@ def set_console_level(level, root=None): |
| """Reset the console (stderr) logging level.""" |
| handler = find_stderr(root) |
| handler.setLevel(level) |
| + |
| + |
| +class OptionParserWithLogging(optparse.OptionParser): |
| + """Adds --verbose option.""" |
| + |
| + # Set to True to enable --log-file options. |
| + enable_log_file = True |
| + |
| + # Set in unit tests. |
| + logger_root = None |
| + |
| + def __init__(self, verbose=0, log_file=None, **kwargs): |
| + kwargs.setdefault('description', sys.modules['__main__'].__doc__) |
| + optparse.OptionParser.__init__(self, **kwargs) |
| + self.group_logging = optparse.OptionGroup(self, 'Logging') |
| + self.group_logging.add_option( |
| + '-v', '--verbose', |
| + action='count', |
| + default=verbose, |
| + help='Use multiple times to increase verbosity') |
| + if self.enable_log_file: |
| + self.group_logging.add_option( |
| + '-l', '--log-file', |
| + default=log_file, |
| + help='The name of the file to store rotating log details') |
| + self.group_logging.add_option( |
| + '--no-log', action='store_const', const='', dest='log_file', |
| + help='Disable log file') |
| + |
| + def parse_args(self, *args, **kwargs): |
| + # Make sure this group is always the last one. |
| + self.add_option_group(self.group_logging) |
| + |
| + options, args = optparse.OptionParser.parse_args(self, *args, **kwargs) |
| + prepare_logging(self.enable_log_file and options.log_file, self.logger_root) |
| + set_console_level( |
| + LEVELS[min(len(LEVELS) - 1, options.verbose)], self.logger_root) |
| + return options, args |
| + |
| + |
| +class ArgumentParserWithLogging(argparse.ArgumentParser): |
| + """Adds --verbose option.""" |
| + |
| + # Set to True to enable --log-file options. |
| + enable_log_file = True |
| + |
| + def __init__(self, verbose=0, log_file=None, **kwargs): |
| + kwargs.setdefault('description', sys.modules['__main__'].__doc__) |
| + kwargs.setdefault('conflict_handler', 'resolve') |
| + self.__verbose = verbose |
| + self.__log_file = log_file |
| + super(ArgumentParserWithLogging, self).__init__(**kwargs) |
| + |
| + def _add_logging_group(self): |
| + group = self.add_argument_group('Logging') |
| + group.add_argument( |
| + '-v', '--verbose', |
| + action='count', |
| + default=self.__verbose, |
| + help='Use multiple times to increase verbosity') |
| + if self.enable_log_file: |
| + group.add_argument( |
| + '-l', '--log-file', |
| + default=self.__log_file, |
| + help='The name of the file to store rotating log details') |
| + group.add_argument( |
| + '--no-log', action='store_const', const='', dest='log_file', |
| + help='Disable log file') |
| + |
| + def parse_args(self, *args, **kwargs): |
| + # Make sure this group is always the last one. |
| + self._add_logging_group() |
| + |
| + args = super(ArgumentParserWithLogging, self).parse_args(*args, **kwargs) |
| + prepare_logging(self.enable_log_file and args.log_file, self.logger_root) |
| + set_console_level( |
| + LEVELS[min(len(LEVELS) - 1, args.verbose)], self.logger_root) |
| + return args |