Package logilab :: Package common :: Module logging_ext
[frames] | no frames]

Source Code for Module logilab.common.logging_ext

  1  # -*- coding: utf-8 -*- 
  2  # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  3  # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  4  # 
  5  # This file is part of logilab-common. 
  6  # 
  7  # logilab-common is free software: you can redistribute it and/or modify it under 
  8  # the terms of the GNU Lesser General Public License as published by the Free 
  9  # Software Foundation, either version 2.1 of the License, or (at your option) any 
 10  # later version. 
 11  # 
 12  # logilab-common is distributed in the hope that it will be useful, but WITHOUT 
 13  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 14  # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 15  # details. 
 16  # 
 17  # You should have received a copy of the GNU Lesser General Public License along 
 18  # with logilab-common.  If not, see <http://www.gnu.org/licenses/>. 
 19  """Extends the logging module from the standard library.""" 
 20   
 21  __docformat__ = "restructuredtext en" 
 22   
 23  import os 
 24  import sys 
 25  import logging 
 26   
 27  from logilab.common.textutils import colorize_ansi 
 28   
 29   
30 -def set_log_methods(cls, logger):
31 """bind standard logger's methods as methods on the class""" 32 cls.__logger = logger 33 for attr in ('debug', 'info', 'warning', 'error', 'critical', 'exception'): 34 setattr(cls, attr, getattr(logger, attr))
35 36
37 -def xxx_cyan(record):
38 if 'XXX' in record.message: 39 return 'cyan'
40
41 -class ColorFormatter(logging.Formatter):
42 """ 43 A color Formatter for the logging standard module. 44 45 By default, colorize CRITICAL and ERROR in red, WARNING in orange, INFO in 46 green and DEBUG in yellow. 47 48 self.colors is customizable via the 'color' constructor argument (dictionary). 49 50 self.colorfilters is a list of functions that get the LogRecord 51 and return a color name or None. 52 """ 53
54 - def __init__(self, fmt=None, datefmt=None, colors=None):
55 logging.Formatter.__init__(self, fmt, datefmt) 56 self.colorfilters = [] 57 self.colors = {'CRITICAL': 'red', 58 'ERROR': 'red', 59 'WARNING': 'magenta', 60 'INFO': 'green', 61 'DEBUG': 'yellow', 62 } 63 if colors is not None: 64 assert isinstance(colors, dict) 65 self.colors.update(colors)
66
67 - def format(self, record):
68 msg = logging.Formatter.format(self, record) 69 if record.levelname in self.colors: 70 color = self.colors[record.levelname] 71 return colorize_ansi(msg, color) 72 else: 73 for cf in self.colorfilters: 74 color = cf(record) 75 if color: 76 return colorize_ansi(msg, color) 77 return msg
78
79 -def set_color_formatter(logger=None, **kw):
80 """ 81 Install a color formatter on the 'logger'. If not given, it will 82 defaults to the default logger. 83 84 Any additional keyword will be passed as-is to the ColorFormatter 85 constructor. 86 """ 87 if logger is None: 88 logger = logging.getLogger() 89 if not logger.handlers: 90 logging.basicConfig() 91 format_msg = logger.handlers[0].formatter._fmt 92 fmt = ColorFormatter(format_msg, **kw) 93 fmt.colorfilters.append(xxx_cyan) 94 logger.handlers[0].setFormatter(fmt)
95 96 97 LOG_FORMAT = '%(asctime)s - (%(name)s) %(levelname)s: %(message)s' 98 LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S' 99
100 -def get_handler(debug=False, syslog=False, logfile=None, rotation_parameters=None):
101 """get an apropriate handler according to given parameters""" 102 if os.environ.get('APYCOT_ROOT'): 103 handler = logging.StreamHandler(sys.stdout) 104 if debug: 105 handler = logging.StreamHandler() 106 elif logfile is None: 107 if syslog: 108 from logging import handlers 109 handler = handlers.SysLogHandler() 110 else: 111 handler = logging.StreamHandler() 112 else: 113 try: 114 if rotation_parameters is None: 115 handler = logging.FileHandler(logfile) 116 else: 117 from logging.handlers import TimedRotatingFileHandler 118 handler = TimedRotatingFileHandler( 119 logfile, **rotation_parameters) 120 except IOError: 121 handler = logging.StreamHandler() 122 return handler
123
124 -def get_threshold(debug=False, logthreshold=None):
125 if logthreshold is None: 126 if debug: 127 logthreshold = logging.DEBUG 128 else: 129 logthreshold = logging.ERROR 130 elif isinstance(logthreshold, basestring): 131 logthreshold = getattr(logging, THRESHOLD_MAP.get(logthreshold, 132 logthreshold)) 133 return logthreshold
134
135 -def get_formatter(logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT):
136 isatty = hasattr(sys.__stdout__, 'isatty') and sys.__stdout__.isatty() 137 if isatty and sys.platform != 'win32': 138 fmt = ColorFormatter(logformat, logdateformat) 139 def col_fact(record): 140 if 'XXX' in record.message: 141 return 'cyan' 142 if 'kick' in record.message: 143 return 'red'
144 fmt.colorfilters.append(col_fact) 145 else: 146 fmt = logging.Formatter(logformat, logdateformat) 147 return fmt 148
149 -def init_log(debug=False, syslog=False, logthreshold=None, logfile=None, 150 logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT, fmt=None, 151 rotation_parameters=None, handler=None):
152 """init the log service""" 153 logger = logging.getLogger() 154 if handler is None: 155 handler = get_handler(debug, syslog, logfile, rotation_parameters) 156 # only addHandler and removeHandler method while I would like a setHandler 157 # method, so do it this way :$ 158 logger.handlers = [handler] 159 logthreshold = get_threshold(debug, logthreshold) 160 logger.setLevel(logthreshold) 161 if fmt is None: 162 if debug: 163 fmt = get_formatter(logformat=logformat, logdateformat=logdateformat) 164 else: 165 fmt = logging.Formatter(logformat, logdateformat) 166 handler.setFormatter(fmt) 167 return handler
168 169 # map logilab.common.logger thresholds to logging thresholds 170 THRESHOLD_MAP = {'LOG_DEBUG': 'DEBUG', 171 'LOG_INFO': 'INFO', 172 'LOG_NOTICE': 'INFO', 173 'LOG_WARN': 'WARNING', 174 'LOG_WARNING': 'WARNING', 175 'LOG_ERR': 'ERROR', 176 'LOG_ERROR': 'ERROR', 177 'LOG_CRIT': 'CRITICAL', 178 } 179