`dict.get()` returns `None` by default, if a key wasn't found. Removing `None` as second argument to avoid redundancy. Change-Id: Ia82f7469cd019509bbeccbfe54b15eeedc7bb6ea
		
			
				
	
	
		
			199 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#   Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
						|
#   not use this file except in compliance with the License. You may obtain
 | 
						|
#   a copy of the License at
 | 
						|
#
 | 
						|
#        http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
#
 | 
						|
#   Unless required by applicable law or agreed to in writing, software
 | 
						|
#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
						|
#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
						|
#   License for the specific language governing permissions and limitations
 | 
						|
#   under the License.
 | 
						|
#
 | 
						|
 | 
						|
"""Application logging"""
 | 
						|
 | 
						|
import logging
 | 
						|
import sys
 | 
						|
import warnings
 | 
						|
 | 
						|
 | 
						|
def get_loggers():
 | 
						|
    loggers = {}
 | 
						|
    for logkey in logging.Logger.manager.loggerDict.keys():
 | 
						|
        loggers[logkey] = logging.getLevelName(logging.getLogger(logkey).level)
 | 
						|
    return loggers
 | 
						|
 | 
						|
 | 
						|
def log_level_from_options(options):
 | 
						|
    # if --debug, --quiet or --verbose is not specified,
 | 
						|
    # the default logging level is warning
 | 
						|
    log_level = logging.WARNING
 | 
						|
    if options.verbose_level == 0:
 | 
						|
        # --quiet
 | 
						|
        log_level = logging.ERROR
 | 
						|
    elif options.verbose_level == 2:
 | 
						|
        # One --verbose
 | 
						|
        log_level = logging.INFO
 | 
						|
    elif options.verbose_level >= 3:
 | 
						|
        # Two or more --verbose
 | 
						|
        log_level = logging.DEBUG
 | 
						|
    return log_level
 | 
						|
 | 
						|
 | 
						|
def log_level_from_string(level_string):
 | 
						|
    log_level = {
 | 
						|
        'critical': logging.CRITICAL,
 | 
						|
        'error': logging.ERROR,
 | 
						|
        'warning': logging.WARNING,
 | 
						|
        'info': logging.INFO,
 | 
						|
        'debug': logging.DEBUG,
 | 
						|
    }.get(level_string, logging.WARNING)
 | 
						|
    return log_level
 | 
						|
 | 
						|
 | 
						|
def log_level_from_config(config):
 | 
						|
    # Check the command line option
 | 
						|
    verbose_level = config.get('verbose_level')
 | 
						|
    if config.get('debug', False):
 | 
						|
        verbose_level = 3
 | 
						|
    if verbose_level == 0:
 | 
						|
        verbose_level = 'error'
 | 
						|
    elif verbose_level == 1:
 | 
						|
        # If a command line option has not been specified, check the
 | 
						|
        # configuration file
 | 
						|
        verbose_level = config.get('log_level', 'warning')
 | 
						|
    elif verbose_level == 2:
 | 
						|
        verbose_level = 'info'
 | 
						|
    else:
 | 
						|
        verbose_level = 'debug'
 | 
						|
    return log_level_from_string(verbose_level)
 | 
						|
 | 
						|
 | 
						|
def set_warning_filter(log_level):
 | 
						|
    if log_level == logging.ERROR:
 | 
						|
        warnings.simplefilter("ignore")
 | 
						|
    elif log_level == logging.WARNING:
 | 
						|
        warnings.simplefilter("ignore")
 | 
						|
    elif log_level == logging.INFO:
 | 
						|
        warnings.simplefilter("once")
 | 
						|
 | 
						|
 | 
						|
class _FileFormatter(logging.Formatter):
 | 
						|
    """Customize the logging format for logging handler"""
 | 
						|
    _LOG_MESSAGE_BEGIN = (
 | 
						|
        '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s ')
 | 
						|
    _LOG_MESSAGE_CONTEXT = '[%(cloud)s %(username)s %(project)s] '
 | 
						|
    _LOG_MESSAGE_END = '%(message)s'
 | 
						|
    _LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
 | 
						|
 | 
						|
    def __init__(self, options=None, config=None, **kwargs):
 | 
						|
        context = {}
 | 
						|
        if options:
 | 
						|
            context = {
 | 
						|
                'cloud': getattr(options, 'cloud', ''),
 | 
						|
                'project': getattr(options, 'os_project_name', ''),
 | 
						|
                'username': getattr(options, 'username', ''),
 | 
						|
            }
 | 
						|
        elif config:
 | 
						|
            context = {
 | 
						|
                'cloud': config.config.get('cloud', ''),
 | 
						|
                'project': config.auth.get('project_name', ''),
 | 
						|
                'username': config.auth.get('username', ''),
 | 
						|
            }
 | 
						|
        if context:
 | 
						|
            self.fmt = (self._LOG_MESSAGE_BEGIN +
 | 
						|
                        (self._LOG_MESSAGE_CONTEXT % context) +
 | 
						|
                        self._LOG_MESSAGE_END)
 | 
						|
        else:
 | 
						|
            self.fmt = self._LOG_MESSAGE_BEGIN + self._LOG_MESSAGE_END
 | 
						|
        logging.Formatter.__init__(self, self.fmt, self._LOG_DATE_FORMAT)
 | 
						|
 | 
						|
 | 
						|
class LogConfigurator(object):
 | 
						|
 | 
						|
    _CONSOLE_MESSAGE_FORMAT = '%(message)s'
 | 
						|
 | 
						|
    def __init__(self, options):
 | 
						|
        self.root_logger = logging.getLogger('')
 | 
						|
        self.root_logger.setLevel(logging.DEBUG)
 | 
						|
 | 
						|
        # Force verbose_level 3 on --debug
 | 
						|
        self.dump_trace = False
 | 
						|
        if options.debug:
 | 
						|
            options.verbose_level = 3
 | 
						|
            self.dump_trace = True
 | 
						|
 | 
						|
        # Always send higher-level messages to the console via stderr
 | 
						|
        self.console_logger = logging.StreamHandler(sys.stderr)
 | 
						|
        log_level = log_level_from_options(options)
 | 
						|
        self.console_logger.setLevel(log_level)
 | 
						|
        formatter = logging.Formatter(self._CONSOLE_MESSAGE_FORMAT)
 | 
						|
        self.console_logger.setFormatter(formatter)
 | 
						|
        self.root_logger.addHandler(self.console_logger)
 | 
						|
 | 
						|
        # Set the warning filter now
 | 
						|
        set_warning_filter(log_level)
 | 
						|
 | 
						|
        # Set up logging to a file
 | 
						|
        self.file_logger = None
 | 
						|
        log_file = options.log_file
 | 
						|
        if log_file:
 | 
						|
            self.file_logger = logging.FileHandler(filename=log_file)
 | 
						|
            self.file_logger.setFormatter(_FileFormatter(options=options))
 | 
						|
            self.file_logger.setLevel(log_level)
 | 
						|
            self.root_logger.addHandler(self.file_logger)
 | 
						|
 | 
						|
        # Requests logs some stuff at INFO that we don't want
 | 
						|
        # unless we have DEBUG
 | 
						|
        requests_log = logging.getLogger("requests")
 | 
						|
 | 
						|
        # Other modules we don't want DEBUG output for
 | 
						|
        cliff_log = logging.getLogger('cliff')
 | 
						|
        stevedore_log = logging.getLogger('stevedore')
 | 
						|
        iso8601_log = logging.getLogger("iso8601")
 | 
						|
 | 
						|
        if options.debug:
 | 
						|
            # --debug forces traceback
 | 
						|
            requests_log.setLevel(logging.DEBUG)
 | 
						|
        else:
 | 
						|
            requests_log.setLevel(logging.ERROR)
 | 
						|
 | 
						|
        cliff_log.setLevel(logging.ERROR)
 | 
						|
        stevedore_log.setLevel(logging.ERROR)
 | 
						|
        iso8601_log.setLevel(logging.ERROR)
 | 
						|
 | 
						|
    def configure(self, cloud_config):
 | 
						|
        log_level = log_level_from_config(cloud_config.config)
 | 
						|
        set_warning_filter(log_level)
 | 
						|
        self.dump_trace = cloud_config.config.get('debug', self.dump_trace)
 | 
						|
        self.console_logger.setLevel(log_level)
 | 
						|
 | 
						|
        log_file = cloud_config.config.get('log_file')
 | 
						|
        if log_file:
 | 
						|
            if not self.file_logger:
 | 
						|
                self.file_logger = logging.FileHandler(filename=log_file)
 | 
						|
            formatter = _FileFormatter(cloud_config=cloud_config)
 | 
						|
            self.file_logger.setFormatter(formatter)
 | 
						|
            self.file_logger.setFormatter(_FileFormatter(config=cloud_config))
 | 
						|
            self.file_logger.setLevel(log_level)
 | 
						|
            self.root_logger.addHandler(self.file_logger)
 | 
						|
 | 
						|
        logconfig = cloud_config.config.get('logging')
 | 
						|
        if logconfig:
 | 
						|
            highest_level = logging.NOTSET
 | 
						|
            for k in logconfig.keys():
 | 
						|
                level = log_level_from_string(logconfig[k])
 | 
						|
                logging.getLogger(k).setLevel(level)
 | 
						|
                if (highest_level < level):
 | 
						|
                    highest_level = level
 | 
						|
            self.console_logger.setLevel(highest_level)
 | 
						|
            if self.file_logger:
 | 
						|
                self.file_logger.setLevel(highest_level)
 | 
						|
            # loggers that are not set will use the handler level, so we
 | 
						|
            # need to set the global level for all the loggers
 | 
						|
            for logkey in logging.Logger.manager.loggerDict.keys():
 | 
						|
                logger = logging.getLogger(logkey)
 | 
						|
                if logger.level == logging.NOTSET:
 | 
						|
                    logger.setLevel(log_level)
 |