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

Source Code for Module 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 if os.name == 'posix' and sys.version_info >= (2, 6): 116 from logging.handlers import WatchedFileHandler 117 handler = WatchedFileHandler(logfile) 118 else: 119 handler = logging.FileHandler(logfile) 120 else: 121 from logging.handlers import TimedRotatingFileHandler 122 handler = TimedRotatingFileHandler( 123 logfile, **rotation_parameters) 124 except IOError: 125 handler = logging.StreamHandler() 126 return handler
127
128 -def get_threshold(debug=False, logthreshold=None):
129 if logthreshold is None: 130 if debug: 131 logthreshold = logging.DEBUG 132 else: 133 logthreshold = logging.ERROR 134 elif isinstance(logthreshold, str): 135 logthreshold = getattr(logging, THRESHOLD_MAP.get(logthreshold, 136 logthreshold)) 137 return logthreshold
138
139 -def _colorable_terminal():
140 isatty = hasattr(sys.__stdout__, 'isatty') and sys.__stdout__.isatty() 141 if not isatty: 142 return False 143 if os.name == 'nt': 144 try: 145 from colorama import init as init_win32_colors 146 except ImportError: 147 return False 148 init_win32_colors() 149 return True
150
151 -def get_formatter(logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT):
152 if _colorable_terminal(): 153 fmt = ColorFormatter(logformat, logdateformat) 154 def col_fact(record): 155 if 'XXX' in record.message: 156 return 'cyan' 157 if 'kick' in record.message: 158 return 'red'
159 fmt.colorfilters.append(col_fact) 160 else: 161 fmt = logging.Formatter(logformat, logdateformat) 162 return fmt 163
164 -def init_log(debug=False, syslog=False, logthreshold=None, logfile=None, 165 logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT, fmt=None, 166 rotation_parameters=None, handler=None):
167 """init the log service""" 168 logger = logging.getLogger() 169 if handler is None: 170 handler = get_handler(debug, syslog, logfile, rotation_parameters) 171 # only addHandler and removeHandler method while I would like a setHandler 172 # method, so do it this way :$ 173 logger.handlers = [handler] 174 logthreshold = get_threshold(debug, logthreshold) 175 logger.setLevel(logthreshold) 176 if fmt is None: 177 if debug: 178 fmt = get_formatter(logformat=logformat, logdateformat=logdateformat) 179 else: 180 fmt = logging.Formatter(logformat, logdateformat) 181 handler.setFormatter(fmt) 182 return handler
183 184 # map logilab.common.logger thresholds to logging thresholds 185 THRESHOLD_MAP = {'LOG_DEBUG': 'DEBUG', 186 'LOG_INFO': 'INFO', 187 'LOG_NOTICE': 'INFO', 188 'LOG_WARN': 'WARNING', 189 'LOG_WARNING': 'WARNING', 190 'LOG_ERR': 'ERROR', 191 'LOG_ERROR': 'ERROR', 192 'LOG_CRIT': 'CRITICAL', 193 } 194