 05800c4722
			
		
	
	05800c4722
	
	
	
		
			
			At one point this file contained the context for logging, but the reason for its existence is now for logging. Implements: blueprint logging-migration Change-Id: I4ba42bbef97b09d31236ac8c01b6fb23827b8bee
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.9 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 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_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'
 | |
| 
 | |
|     log_level = {
 | |
|         'critical': logging.CRITICAL,
 | |
|         'error': logging.ERROR,
 | |
|         'warning': logging.WARNING,
 | |
|         'info': logging.INFO,
 | |
|         'debug': logging.DEBUG,
 | |
|     }.get(verbose_level, logging.WARNING)
 | |
|     return log_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', None)
 | |
|         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)
 |