Package ipapython :: Module ipa_log_manager
[hide private]
[frames] | no frames]

Source Code for Module ipapython.ipa_log_manager

  1  # Authors: John Dennis <jdennis@redhat.com> 
  2  # 
  3  # Copyright (C) 2011  Red Hat 
  4  # see file 'COPYING' for use and warranty information 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 18   
 19  #------------------------------------------------------------------------------- 
 20   
 21  # Module exports 
 22  __all__ = ['log_mgr', 'root_logger', 'standard_logging_setup', 
 23             'IPA_ROOT_LOGGER_NAME', 'ISO8601_UTC_DATETIME_FMT', 
 24             'LOGGING_FORMAT_STDERR', 'LOGGING_FORMAT_STDOUT', 'LOGGING_FORMAT_FILE'] 
 25   
 26  #------------------------------------------------------------------------------- 
 27   
 28  import sys 
 29  import re 
 30  import copy 
 31   
 32  from log_manager import LogManager, parse_log_level 
 33   
 34  #------------------------------------------------------------------------------- 
 35   
 36  # Our root logger, all loggers will be descendents of this. 
 37  IPA_ROOT_LOGGER_NAME = 'ipa' 
 38   
 39  # Format string for time.strftime() to produce a ISO 8601 date time 
 40  # formatted string in the UTC time zone. 
 41  ISO8601_UTC_DATETIME_FMT = '%Y-%m-%dT%H:%M:%SZ' 
 42   
 43  # Logging format string for use with logging stderr handlers 
 44  LOGGING_FORMAT_STDERR = 'ipa: %(levelname)s: %(message)s' 
 45   
 46  # Logging format string for use with logging stdout handlers 
 47  LOGGING_FORMAT_STDOUT = '[%(asctime)s %(name)s] <%(levelname)s>: %(message)s' 
 48   
 49  # Logging format string for use with logging file handlers 
 50  LOGGING_FORMAT_FILE = '\t'.join([ 
 51      '%(asctime)s', 
 52      '%(process)d', 
 53      '%(threadName)s', 
 54      '%(name)s', 
 55      '%(levelname)s', 
 56      '%(message)s', 
 57  ]) 
 58   
 59  # Used by standard_logging_setup() for console message 
 60  LOGGING_FORMAT_STANDARD_CONSOLE = '%(name)-12s: %(levelname)-8s %(message)s' 
 61   
 62  # Used by standard_logging_setup() for file message 
 63  LOGGING_FORMAT_STANDARD_FILE = '%(asctime)s %(levelname)s %(message)s' 
 64   
 65  #------------------------------------------------------------------------------- 
 66   
67 -class IPALogManager(LogManager):
68 ''' 69 Subclass the LogManager to enforce some IPA specfic logging 70 conventions. 71 72 * Default to timestamps in UTC. 73 * Default to ISO 8601 timestamp format. 74 * Default the message format. 75 ''' 76 77 log_logger_level_config_re = re.compile(r'^log_logger_level_(debug|info|warn|warning|error|critical|\d+)$') 78
79 - def __init__(self, configure_state=None):
80 ''' 81 :parameters: 82 configure_state 83 Used by clients of the log manager to track the 84 configuration state, may be any object. 85 ''' 86 87 super(IPALogManager, self).__init__(IPA_ROOT_LOGGER_NAME, configure_state)
88
89 - def configure_from_env(self, env, configure_state=None):
90 ''' 91 Read the loggger configuration from the Env config. The 92 following items may be configured: 93 94 Logger Levels 95 *log_logger_XXX = comma separated list of regexps* 96 97 Logger levels can be explicitly specified for specific loggers as 98 opposed to a global logging level. Specific loggers are indiciated 99 by a list of regular expressions bound to a level. If a logger's 100 name matches the regexp then it is assigned that level. The keys 101 in the Env config must begin with "log_logger_level\_" and then be 102 followed by a symbolic or numeric log level, for example:: 103 104 log_logger_level_debug = ipalib\.dn\..* 105 log_logger_level_35 = ipalib\.plugins\.dogtag 106 107 The first line says any logger belonging to the ipalib.dn module 108 will have it's level configured to debug. 109 110 The second line say the ipa.plugins.dogtag logger will be 111 configured to level 35. 112 113 Note: logger names are a dot ('.') separated list forming a path 114 in the logger tree. The dot character is also a regular 115 expression metacharacter (matches any character) therefore you 116 will usually need to escape the dot in the logger names by 117 preceeding it with a backslash. 118 119 The return value of this function is a dict with the following 120 format: 121 122 logger_regexps 123 List of (regexp, level) tuples 124 125 :parameters: 126 env 127 Env object configuration values are read from. 128 configure_state 129 If other than None update the log manger's configure_state 130 variable to this object. Clients of the log manager can 131 use configure_state to track the state of the log manager. 132 ''' 133 logger_regexps = [] 134 config = {'logger_regexps' : logger_regexps, 135 } 136 137 for attr in ('debug', 'verbose'): 138 value = getattr(env, attr, None) 139 if value is not None: 140 config[attr] = value 141 142 for attr in list(env): 143 # Get logger level configuration 144 match = IPALogManager.log_logger_level_config_re.search(attr) 145 if match: 146 value = match.group(1) 147 level = parse_log_level(value) 148 value = getattr(env, attr) 149 regexps = re.split('\s*,\s*', value) 150 # Add the regexp, it maps to the configured level 151 for regexp in regexps: 152 logger_regexps.append((regexp, level)) 153 continue 154 155 self.configure(config, configure_state) 156 return config
157
158 - def create_log_handlers(self, configs, logger=None, configure_state=None):
159 'Enforce some IPA specific configurations' 160 configs = copy.copy(configs) 161 162 for cfg in configs: 163 if not 'time_zone_converter' in cfg: 164 cfg['time_zone_converter'] = 'utc' 165 if not 'datefmt' in cfg: 166 cfg['datefmt'] = ISO8601_UTC_DATETIME_FMT 167 if not 'format' in cfg: 168 cfg['format'] = LOGGING_FORMAT_STDOUT 169 170 return super(IPALogManager, self).create_log_handlers(configs, logger, configure_state)
171 172 #------------------------------------------------------------------------------- 173
174 -def standard_logging_setup(filename=None, verbose=False, debug=False, filemode='w'):
175 handlers = [] 176 177 # File output is always logged at debug level 178 if filename is not None: 179 file_handler = dict(name='file', 180 filename=filename, 181 filemode=filemode, 182 permission=0600, 183 level='debug', 184 format=LOGGING_FORMAT_STANDARD_FILE) 185 handlers.append(file_handler) 186 187 if log_mgr.handlers.has_key('console'): 188 log_mgr.remove_handler('console') 189 level = 'error' 190 if verbose: 191 level = 'info' 192 if debug: 193 level = 'debug' 194 195 console_handler = dict(name='console', 196 stream=sys.stderr, 197 level=level, 198 format=LOGGING_FORMAT_STANDARD_CONSOLE) 199 handlers.append(console_handler) 200 201 202 # default_level must be debug becuase we want the file handler to 203 # always log at the debug level. 204 log_mgr.configure(dict(default_level='debug', 205 handlers=handlers), 206 configure_state='standard') 207 208 return log_mgr.root_logger
209 210 #------------------------------------------------------------------------------- 211 212 # Single shared instance of log manager 213 # 214 # By default always starts with stderr console handler at error level 215 # so messages generated before logging is fully configured have some 216 # place to got and won't get lost. 217 218 log_mgr = IPALogManager() 219 log_mgr.configure(dict(default_level='error', 220 handlers=[dict(name='console', 221 stream=sys.stderr)]), 222 configure_state='default') 223 root_logger = log_mgr.root_logger 224