Update oslo-incubator log.py to a01f79c

This updates the log module from oslo-incubator to
a01f79c3050962fd744239956e9654407d14ea1f

 $ git checkout a01f79c3050962fd744239956e9654407d14ea1f
 $ python update.py --nodeps --base keystone \
     --dest-dir ../keystone --modules log

This includes a fix for the deprecated logger that caused the
deprecated message to be printed multiple times rather than once.

Change-Id: I6174b064205adcdc9fb966a9e01eb5190b5b730e
Closes-Bug: #904307
Closes-Bug: #1266812
This commit is contained in:
Brant Knudson 2014-02-12 13:17:16 -06:00
parent a68e93dc2e
commit 40cff90166
4 changed files with 143 additions and 33 deletions

View File

@ -22,11 +22,11 @@ SYNOPSIS
[--log-config-append PATH] [--log-date-format DATE_FORMAT] [--log-config-append PATH] [--log-date-format DATE_FORMAT]
[--log-dir LOG_DIR] [--log-file PATH] [--log-dir LOG_DIR] [--log-file PATH]
[--log-format FORMAT] [--nodebug] [--nostandard-threads] [--log-format FORMAT] [--nodebug] [--nostandard-threads]
[--nouse-syslog] [--noverbose] [--nouse-syslog] [--nouse-syslog-rfc-format] [--noverbose]
[--pydev-debug-host PYDEV_DEBUG_HOST] [--pydev-debug-host PYDEV_DEBUG_HOST]
[--pydev-debug-port PYDEV_DEBUG_PORT] [--standard-threads] [--pydev-debug-port PYDEV_DEBUG_PORT] [--standard-threads]
[--syslog-log-facility SYSLOG_LOG_FACILITY] [--use-syslog] [--syslog-log-facility SYSLOG_LOG_FACILITY] [--use-syslog]
[--verbose] [--version] [--use-syslog-rfc-format] [--verbose] [--version]
DESCRIPTION DESCRIPTION
=========== ===========
@ -74,6 +74,8 @@ OPTIONS
--nodebug The inverse of --debug --nodebug The inverse of --debug
--nostandard-threads The inverse of --standard-threads --nostandard-threads The inverse of --standard-threads
--nouse-syslog The inverse of --use-syslog --nouse-syslog The inverse of --use-syslog
--nouse-syslog-rfc-format
The inverse of --use-syslog-rfc-format
--noverbose The inverse of --verbose --noverbose The inverse of --verbose
--pydev-debug-host PYDEV_DEBUG_HOST --pydev-debug-host PYDEV_DEBUG_HOST
Host to connect to for remote debugger. Host to connect to for remote debugger.
@ -81,8 +83,15 @@ OPTIONS
Port to connect to for remote debugger. Port to connect to for remote debugger.
--standard-threads Do not monkey-patch threading system modules. --standard-threads Do not monkey-patch threading system modules.
--syslog-log-facility SYSLOG_LOG_FACILITY --syslog-log-facility SYSLOG_LOG_FACILITY
syslog facility to receive log lines Syslog facility to receive log lines
--use-syslog Use syslog for logging. --use-syslog Use syslog for logging. Existing syslog format is
DEPRECATED during I, and then will be changed in J to
honor RFC5424
--use-syslog-rfc-format
(Optional) Use syslog rfc5424 format for logging. If
enabled, will add APP-NAME (RFC5424) before the MSG
part of the syslog message. The old format without
APP-NAME is deprecated in I, and will be removed in J.
--verbose, -v Print more verbose output (set logging level to INFO --verbose, -v Print more verbose output (set logging level to INFO
instead of default WARNING level). instead of default WARNING level).
--version show program's version number and exit --version show program's version number and exit

View File

@ -85,6 +85,8 @@ OPTIONS
--nodebug The inverse of --debug --nodebug The inverse of --debug
--nostandard-threads The inverse of --standard-threads --nostandard-threads The inverse of --standard-threads
--nouse-syslog The inverse of --use-syslog --nouse-syslog The inverse of --use-syslog
--nouse-syslog-rfc-format
The inverse of --use-syslog-rfc-format
--noverbose The inverse of --verbose --noverbose The inverse of --verbose
--pydev-debug-host PYDEV_DEBUG_HOST --pydev-debug-host PYDEV_DEBUG_HOST
Host to connect to for remote debugger. Host to connect to for remote debugger.
@ -92,8 +94,15 @@ OPTIONS
Port to connect to for remote debugger. Port to connect to for remote debugger.
--standard-threads Do not monkey-patch threading system modules. --standard-threads Do not monkey-patch threading system modules.
--syslog-log-facility SYSLOG_LOG_FACILITY --syslog-log-facility SYSLOG_LOG_FACILITY
syslog facility to receive log lines Syslog facility to receive log lines
--use-syslog Use syslog for logging. --use-syslog Use syslog for logging. Existing syslog format is
DEPRECATED during I, and then will be changed in J to
honor RFC5424
--use-syslog-rfc-format
(Optional) Use syslog rfc5424 format for logging. If
enabled, will add APP-NAME (RFC5424) before the MSG
part of the syslog message. The old format without
APP-NAME is deprecated in I, and will be removed in J.
--verbose, -v Print more verbose output (set logging level to INFO --verbose, -v Print more verbose output (set logging level to INFO
instead of default WARNING level). instead of default WARNING level).
--version show program's version number and exit --version show program's version number and exit

View File

@ -354,29 +354,29 @@
# Log output to standard error (boolean value) # Log output to standard error (boolean value)
#use_stderr=true #use_stderr=true
# format string to use for log messages with context (string # Format string to use for log messages with context (string
# value) # value)
#logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s #logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s
# format string to use for log messages without context # Format string to use for log messages without context
# (string value) # (string value)
#logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s #logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
# data to append to log format when level is DEBUG (string # Data to append to log format when level is DEBUG (string
# value) # value)
#logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d #logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d
# prefix each line of exception output with this format # Prefix each line of exception output with this format
# (string value) # (string value)
#logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s #logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
# list of logger=LEVEL pairs (list value) # List of logger=LEVEL pairs (list value)
#default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,iso8601=WARN #default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN
# publish error events (boolean value) # Publish error events (boolean value)
#publish_errors=false #publish_errors=false
# make deprecations fatal (boolean value) # Make deprecations fatal (boolean value)
#fatal_deprecations=false #fatal_deprecations=false
# If an instance is passed with the log message, format it # If an instance is passed with the log message, format it
@ -416,10 +416,18 @@
# Deprecated group/name - [DEFAULT]/logdir # Deprecated group/name - [DEFAULT]/logdir
#log_dir=<None> #log_dir=<None>
# Use syslog for logging. (boolean value) # Use syslog for logging. Existing syslog format is DEPRECATED
# during I, and then will be changed in J to honor RFC5424
# (boolean value)
#use_syslog=false #use_syslog=false
# syslog facility to receive log lines (string value) # (Optional) Use syslog rfc5424 format for logging. If
# enabled, will add APP-NAME (RFC5424) before the MSG part of
# the syslog message. The old format without APP-NAME is
# deprecated in I, and will be removed in J. (boolean value)
#use_syslog_rfc_format=false
# Syslog facility to receive log lines (string value)
#syslog_log_facility=LOG_USER #syslog_log_facility=LOG_USER

View File

@ -115,10 +115,21 @@ logging_cli_opts = [
'--log-file paths'), '--log-file paths'),
cfg.BoolOpt('use-syslog', cfg.BoolOpt('use-syslog',
default=False, default=False,
help='Use syslog for logging.'), help='Use syslog for logging. '
'Existing syslog format is DEPRECATED during I, '
'and then will be changed in J to honor RFC5424'),
cfg.BoolOpt('use-syslog-rfc-format',
# TODO(bogdando) remove or use True after existing
# syslog format deprecation in J
default=False,
help='(Optional) Use syslog rfc5424 format for logging. '
'If enabled, will add APP-NAME (RFC5424) before the '
'MSG part of the syslog message. The old format '
'without APP-NAME is deprecated in I, '
'and will be removed in J.'),
cfg.StrOpt('syslog-log-facility', cfg.StrOpt('syslog-log-facility',
default='LOG_USER', default='LOG_USER',
help='syslog facility to receive log lines') help='Syslog facility to receive log lines')
] ]
generic_log_opts = [ generic_log_opts = [
@ -132,18 +143,18 @@ log_opts = [
default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
'%(name)s [%(request_id)s %(user_identity)s] ' '%(name)s [%(request_id)s %(user_identity)s] '
'%(instance)s%(message)s', '%(instance)s%(message)s',
help='format string to use for log messages with context'), help='Format string to use for log messages with context'),
cfg.StrOpt('logging_default_format_string', cfg.StrOpt('logging_default_format_string',
default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
'%(name)s [-] %(instance)s%(message)s', '%(name)s [-] %(instance)s%(message)s',
help='format string to use for log messages without context'), help='Format string to use for log messages without context'),
cfg.StrOpt('logging_debug_format_suffix', cfg.StrOpt('logging_debug_format_suffix',
default='%(funcName)s %(pathname)s:%(lineno)d', default='%(funcName)s %(pathname)s:%(lineno)d',
help='data to append to log format when level is DEBUG'), help='Data to append to log format when level is DEBUG'),
cfg.StrOpt('logging_exception_prefix', cfg.StrOpt('logging_exception_prefix',
default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s '
'%(instance)s', '%(instance)s',
help='prefix each line of exception output with this format'), help='Prefix each line of exception output with this format'),
cfg.ListOpt('default_log_levels', cfg.ListOpt('default_log_levels',
default=[ default=[
'amqp=WARN', 'amqp=WARN',
@ -153,14 +164,15 @@ log_opts = [
'sqlalchemy=WARN', 'sqlalchemy=WARN',
'suds=INFO', 'suds=INFO',
'iso8601=WARN', 'iso8601=WARN',
'requests.packages.urllib3.connectionpool=WARN'
], ],
help='list of logger=LEVEL pairs'), help='List of logger=LEVEL pairs'),
cfg.BoolOpt('publish_errors', cfg.BoolOpt('publish_errors',
default=False, default=False,
help='publish error events'), help='Publish error events'),
cfg.BoolOpt('fatal_deprecations', cfg.BoolOpt('fatal_deprecations',
default=False, default=False,
help='make deprecations fatal'), help='Make deprecations fatal'),
# NOTE(mikal): there are two options here because sometimes we are handed # NOTE(mikal): there are two options here because sometimes we are handed
# a full instance (and could include more information), and other times we # a full instance (and could include more information), and other times we
@ -292,18 +304,39 @@ class ContextAdapter(BaseLoggerAdapter):
self.logger = logger self.logger = logger
self.project = project_name self.project = project_name
self.version = version_string self.version = version_string
self._deprecated_messages_sent = dict()
@property @property
def handlers(self): def handlers(self):
return self.logger.handlers return self.logger.handlers
def deprecated(self, msg, *args, **kwargs): def deprecated(self, msg, *args, **kwargs):
"""Call this method when a deprecated feature is used.
If the system is configured for fatal deprecations then the message
is logged at the 'critical' level and :class:`DeprecatedConfig` will
be raised.
Otherwise, the message will be logged (once) at the 'warn' level.
:raises: :class:`DeprecatedConfig` if the system is configured for
fatal deprecations.
"""
stdmsg = _("Deprecated: %s") % msg stdmsg = _("Deprecated: %s") % msg
if CONF.fatal_deprecations: if CONF.fatal_deprecations:
self.critical(stdmsg, *args, **kwargs) self.critical(stdmsg, *args, **kwargs)
raise DeprecatedConfig(msg=stdmsg) raise DeprecatedConfig(msg=stdmsg)
else:
self.warn(stdmsg, *args, **kwargs) # Using a list because a tuple with dict can't be stored in a set.
sent_args = self._deprecated_messages_sent.setdefault(msg, list())
if args in sent_args:
# Already logged this message, so don't log it again.
return
sent_args.append(args)
self.warn(stdmsg, *args, **kwargs)
def process(self, msg, kwargs): def process(self, msg, kwargs):
# NOTE(mrodden): catch any Message/other object and # NOTE(mrodden): catch any Message/other object and
@ -420,12 +453,12 @@ def _load_log_config(log_config_append):
raise LogConfigError(log_config_append, str(exc)) raise LogConfigError(log_config_append, str(exc))
def setup(product_name): def setup(product_name, version='unknown'):
"""Setup logging.""" """Setup logging."""
if CONF.log_config_append: if CONF.log_config_append:
_load_log_config(CONF.log_config_append) _load_log_config(CONF.log_config_append)
else: else:
_setup_logging_from_conf() _setup_logging_from_conf(product_name, version)
sys.excepthook = _create_logging_excepthook(product_name) sys.excepthook = _create_logging_excepthook(product_name)
@ -459,15 +492,32 @@ def _find_facility_from_conf():
return facility return facility
def _setup_logging_from_conf(): class RFCSysLogHandler(logging.handlers.SysLogHandler):
def __init__(self, *args, **kwargs):
self.binary_name = _get_binary_name()
super(RFCSysLogHandler, self).__init__(*args, **kwargs)
def format(self, record):
msg = super(RFCSysLogHandler, self).format(record)
msg = self.binary_name + ' ' + msg
return msg
def _setup_logging_from_conf(project, version):
log_root = getLogger(None).logger log_root = getLogger(None).logger
for handler in log_root.handlers: for handler in log_root.handlers:
log_root.removeHandler(handler) log_root.removeHandler(handler)
if CONF.use_syslog: if CONF.use_syslog:
facility = _find_facility_from_conf() facility = _find_facility_from_conf()
syslog = logging.handlers.SysLogHandler(address='/dev/log', # TODO(bogdando) use the format provided by RFCSysLogHandler
facility=facility) # after existing syslog format deprecation in J
if CONF.use_syslog_rfc_format:
syslog = RFCSysLogHandler(address='/dev/log',
facility=facility)
else:
syslog = logging.handlers.SysLogHandler(address='/dev/log',
facility=facility)
log_root.addHandler(syslog) log_root.addHandler(syslog)
logpath = _get_log_file_path() logpath = _get_log_file_path()
@ -501,7 +551,9 @@ def _setup_logging_from_conf():
log_root.info('Deprecated: log_format is now deprecated and will ' log_root.info('Deprecated: log_format is now deprecated and will '
'be removed in the next release') 'be removed in the next release')
else: else:
handler.setFormatter(ContextFormatter(datefmt=datefmt)) handler.setFormatter(ContextFormatter(project=project,
version=version,
datefmt=datefmt))
if CONF.debug: if CONF.debug:
log_root.setLevel(logging.DEBUG) log_root.setLevel(logging.DEBUG)
@ -559,10 +611,42 @@ class ContextFormatter(logging.Formatter):
For information about what variables are available for the formatter see: For information about what variables are available for the formatter see:
http://docs.python.org/library/logging.html#formatter http://docs.python.org/library/logging.html#formatter
If available, uses the context value stored in TLS - local.store.context
""" """
def __init__(self, *args, **kwargs):
"""Initialize ContextFormatter instance
Takes additional keyword arguments which can be used in the message
format string.
:keyword project: project name
:type project: string
:keyword version: project version
:type version: string
"""
self.project = kwargs.pop('project', 'unknown')
self.version = kwargs.pop('version', 'unknown')
logging.Formatter.__init__(self, *args, **kwargs)
def format(self, record): def format(self, record):
"""Uses contextstring if request_id is set, otherwise default.""" """Uses contextstring if request_id is set, otherwise default."""
# store project info
record.project = self.project
record.version = self.version
# store request info
context = getattr(local.store, 'context', None)
if context:
d = _dictify_context(context)
for k, v in d.items():
setattr(record, k, v)
# NOTE(sdague): default the fancier formatting params # NOTE(sdague): default the fancier formatting params
# to an empty string so we don't throw an exception if # to an empty string so we don't throw an exception if
# they get used # they get used