ticket 2022 - modify codebase to utilize IPALogManager, obsoletes logging

change default_logger_level to debug in configure_standard_logging

add new ipa_log_manager module, move log_mgr there, also export
root_logger from log_mgr.

change all log_manager imports to ipa_log_manager and change
log_manager.root_logger to root_logger.

add missing import for parse_log_level()
This commit is contained in:
John Dennis
2011-11-23 09:36:18 +01:00
committed by Martin Kosek
parent 730f1228a9
commit 56401c1abe
44 changed files with 697 additions and 807 deletions
+1 -234
View File
@@ -508,42 +508,11 @@ import pwd
import logging
import re
import time
import copy
#-------------------------------------------------------------------------------
# Our root logger, all loggers will be descendents of this.
IPA_ROOT_LOGGER_NAME = 'ipa'
# Format string for time.strftime() to produce a ISO 8601 date time
# formatted string in the UTC time zone.
ISO8601_UTC_DATETIME_FMT = '%Y-%m-%dT%H:%M:%SZ'
# Default format
LOGGING_DEFAULT_FORMAT = '%(levelname)s %(message)s'
# Logging format string for use with logging stderr handlers
LOGGING_FORMAT_STDERR = 'ipa: %(levelname)s: %(message)s'
# Logging format string for use with logging stdout handlers
LOGGING_FORMAT_STDOUT = '[%(asctime)s %(name)s] <%(levelname)s>: %(message)s'
# Logging format string for use with logging file handlers
LOGGING_FORMAT_FILE = '\t'.join([
'%(asctime)s',
'%(process)d',
'%(threadName)s',
'%(name)s',
'%(levelname)s',
'%(message)s',
])
# Used by standard_logging_setup() for console message
LOGGING_FORMAT_STANDARD_CONSOLE = '%(name)-12s: %(levelname)-8s %(message)s'
# Used by standard_logging_setup() for file message
LOGGING_FORMAT_STANDARD_FILE = '%(asctime)s %(levelname)s %(message)s'
# Maps a logging level name to it's numeric value
log_level_name_map = {
'notset' : logging.NOTSET,
@@ -1100,7 +1069,7 @@ class LogManager(object):
# Create a logger for my_app.foo.bar
foo_bar_log = log_mgr.get_logger('foo.bar')
log_mgr.root_logger.info("Ready to process requests")
root_logger.info("Ready to process requests")
foo_bar_log.error("something went boom")
In the file my_app.log you would see::
@@ -1544,205 +1513,3 @@ class LogManager(object):
return logger
class IPALogManager(LogManager):
'''
Subclass the LogManager to enforce some IPA specfic logging
conventions.
* Default to timestamps in UTC.
* Default to ISO 8601 timestamp format.
* Default the message format.
'''
log_logger_level_config_re = re.compile(r'^log_logger_level_(debug|info|warn|warning|error|critical|\d+)$')
log_handler_level_config_re = re.compile(r'^log_handler_(\S+)_level$')
def __init__(self, configure_state=None):
'''
:parameters:
configure_state
Used by clients of the log manager to track the
configuration state, may be any object.
'''
super(IPALogManager, self).__init__(IPA_ROOT_LOGGER_NAME, configure_state)
def configure_from_env(self, env, configure_state=None):
'''
Read the loggger configuration from the Env config. The
following items may be configured:
Logger Levels
*log_logger_XXX = comma separated list of regexps*
Logger levels can be explicitly specified for specific loggers as
opposed to a global logging level. Specific loggers are indiciated
by a list of regular expressions bound to a level. If a logger's
name matches the regexp then it is assigned that level. The keys
in the Env config must begin with "log_logger_level\_" and then be
followed by a symbolic or numeric log level, for example::
log_logger_level_debug = ipalib\.dn\..*
log_logger_level_35 = ipalib\.plugins\.dogtag
The first line says any logger belonging to the ipalib.dn module
will have it's level configured to debug.
The second line say the ipa.plugins.dogtag logger will be
configured to level 35.
Note: logger names are a dot ('.') separated list forming a path
in the logger tree. The dot character is also a regular
expression metacharacter (matches any character) therefore you
will usually need to escape the dot in the logger names by
preceeding it with a backslash.
Handler Levels
*log_handler_XXX_level = level*
Handler levels may be specified with a key containing the
name of the handler (XXX) and whose value is the level. For
example::
log_handler_console_level = debug
Would set the console handler level to debug.
These are the predefined log handlers:
console
Writes to stderr.
file
Writes to the default log file.
The return value of this function is a dict with the following
format:
logger_regexps
List of (regexp, level) tuples
handlers
Dict, key is handler name, value is dict of handler config.
Handler config dict:
level
handler log level
:parameters:
env
Env object configuration values are read from.
configure_state
If other than None update the log manger's configure_state
variable to this object. Clients of the log manager can
use configure_state to track the state of the log manager.
'''
logger_regexps = []
handlers = {}
config = {'logger_regexps' : logger_regexps,
'handlers' : handlers,
}
for attr in ('debug', 'verbose'):
value = getattr(env, attr, None)
if value is not None:
config[attr] = value
for attr in list(env):
# Get logger level configuration
match = IPALogManager.log_logger_level_config_re.search(attr)
if match:
value = match.group(1)
level = parse_log_level(value)
value = getattr(env, attr)
regexps = re.split('\s*,\s*', value)
# Add the regexp, it maps to the configured level
for regexp in regexps:
print "%s %s" % (regexp, level)
logger_regexps.append((regexp, level))
continue
# Get handler configuration
match = IPALogManager.log_handler_level_config_re.search(attr)
if match:
value = getattr(env, attr)
try:
level = parse_log_level(value)
except Exception, e:
print >>sys.stderr, 'ERROR could not parse log handler level: %s=%s' % (attr, value)
continue
name = match.group(1)
print "%s %s" % (name, level)
handler_config = handlers.get(name)
if handler_config is None:
handler_config = {'name' : name}
handler_config['level'] = level
continue
self.configure(config, configure_state)
return config
def create_log_handlers(self, configs, logger=None, configure_state=None):
'Enforce some IPA specific configurations'
configs = copy.copy(configs)
for cfg in configs:
if not 'time_zone_converter' in cfg:
cfg['time_zone_converter'] = 'utc'
if not 'datefmt' in cfg:
cfg['datefmt'] = ISO8601_UTC_DATETIME_FMT
if not 'format' in cfg:
cfg['format'] = LOGGING_FORMAT_STDOUT
return super(IPALogManager, self).create_log_handlers(configs, logger, configure_state)
#-------------------------------------------------------------------------------
def standard_logging_setup(filename=None, verbose=False, debug=False, filemode='w'):
handlers = []
# File output is always logged at debug level
if filename is not None:
file_handler = dict(name='file',
filename=filename,
filemode=filemode,
permission=0600,
level='debug',
format=LOGGING_FORMAT_STANDARD_FILE)
handlers.append(file_handler)
if log_mgr.handlers.has_key('console'):
log_mgr.remove_handler('console')
level = 'error'
if verbose:
level = 'info'
if debug:
level = 'debug'
console_handler = dict(name='console',
stream=sys.stderr,
level=level,
format=LOGGING_FORMAT_STANDARD_CONSOLE)
handlers.append(console_handler)
log_mgr.configure(dict(default_level=level,
handlers=handlers),
configure_state='standard')
return log_mgr.root_logger
#-------------------------------------------------------------------------------
# Single shared instance of log manager
#
# By default always starts with stderr console handler at error level
# so messages generated before logging is fully configured have some
# place to got and won't get lost.
log_mgr = IPALogManager()
log_mgr.configure(dict(default_level='error',
handlers=[dict(name='console',
stream=sys.stderr)]),
configure_state='default')