175 lines
5.6 KiB
Python
Raw Normal View History

# 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.
#
"""Context and Formatter"""
import logging
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)
def setup_handler_logging_level(handler_type, level):
"""Setup of the handler for set the logging level
:param handler_type: type of logging handler
:param level: logging level
:return: None
"""
# Set the handler logging level of FileHandler(--log-file)
# and StreamHandler
for h in logging.getLogger('').handlers:
if type(h) is handler_type:
h.setLevel(level)
def setup_logging(shell, cloud_config):
"""Get one cloud configuration from configuration file and setup logging
:param shell: instance of openstackclient shell
:param cloud_config:
instance of the cloud specified by --os-cloud
in the configuration file
:return: None
"""
log_level = log_level_from_config(cloud_config.config)
set_warning_filter(log_level)
log_file = cloud_config.config.get('log_file', None)
if log_file:
# setup the logging context
formatter = _FileFormatter(config=cloud_config)
# setup the logging handler
log_handler = _setup_handler_for_logging(
logging.FileHandler,
log_level,
file_name=log_file,
formatter=formatter,
)
if log_level == logging.DEBUG:
# DEBUG only.
# setup the operation_log
shell.enable_operation_logging = True
shell.operation_log.setLevel(logging.DEBUG)
shell.operation_log.addHandler(log_handler)
def _setup_handler_for_logging(handler_type, level, file_name, formatter):
"""Setup of the handler
Setup of the handler for addition of the logging handler,
changes of the logging format, change of the logging level,
:param handler_type: type of logging handler
:param level: logging level
:param file_name: name of log-file
:param formatter: instance of logging.Formatter
:return: logging handler
"""
root_logger = logging.getLogger('')
handler = None
# Setup handler for FileHandler(--os-cloud)
handler = logging.FileHandler(
filename=file_name,
)
handler.setFormatter(formatter)
handler.setLevel(level)
# If both `--log-file` and `--os-cloud` are specified,
# the log is output to each file.
root_logger.addHandler(handler)
return handler