Index: third_party/logilab/common/logging_ext.py |
diff --git a/third_party/logilab/common/logging_ext.py b/third_party/logilab/common/logging_ext.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1b7a1e60950ba178ede6c3c65b2985e44220b9b3 |
--- /dev/null |
+++ b/third_party/logilab/common/logging_ext.py |
@@ -0,0 +1,178 @@ |
+# -*- coding: utf-8 -*- |
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
+# |
+# This file is part of logilab-common. |
+# |
+# logilab-common is free software: you can redistribute it and/or modify it under |
+# the terms of the GNU Lesser General Public License as published by the Free |
+# Software Foundation, either version 2.1 of the License, or (at your option) any |
+# later version. |
+# |
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT |
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
+# details. |
+# |
+# You should have received a copy of the GNU Lesser General Public License along |
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>. |
+"""Extends the logging module from the standard library.""" |
+ |
+__docformat__ = "restructuredtext en" |
+ |
+import os |
+import sys |
+import logging |
+ |
+from logilab.common.textutils import colorize_ansi |
+ |
+ |
+def set_log_methods(cls, logger): |
+ """bind standard logger's methods as methods on the class""" |
+ cls.__logger = logger |
+ for attr in ('debug', 'info', 'warning', 'error', 'critical', 'exception'): |
+ setattr(cls, attr, getattr(logger, attr)) |
+ |
+ |
+def xxx_cyan(record): |
+ if 'XXX' in record.message: |
+ return 'cyan' |
+ |
+class ColorFormatter(logging.Formatter): |
+ """ |
+ A color Formatter for the logging standard module. |
+ |
+ By default, colorize CRITICAL and ERROR in red, WARNING in orange, INFO in |
+ green and DEBUG in yellow. |
+ |
+ self.colors is customizable via the 'color' constructor argument (dictionary). |
+ |
+ self.colorfilters is a list of functions that get the LogRecord |
+ and return a color name or None. |
+ """ |
+ |
+ def __init__(self, fmt=None, datefmt=None, colors=None): |
+ logging.Formatter.__init__(self, fmt, datefmt) |
+ self.colorfilters = [] |
+ self.colors = {'CRITICAL': 'red', |
+ 'ERROR': 'red', |
+ 'WARNING': 'magenta', |
+ 'INFO': 'green', |
+ 'DEBUG': 'yellow', |
+ } |
+ if colors is not None: |
+ assert isinstance(colors, dict) |
+ self.colors.update(colors) |
+ |
+ def format(self, record): |
+ msg = logging.Formatter.format(self, record) |
+ if record.levelname in self.colors: |
+ color = self.colors[record.levelname] |
+ return colorize_ansi(msg, color) |
+ else: |
+ for cf in self.colorfilters: |
+ color = cf(record) |
+ if color: |
+ return colorize_ansi(msg, color) |
+ return msg |
+ |
+def set_color_formatter(logger=None, **kw): |
+ """ |
+ Install a color formatter on the 'logger'. If not given, it will |
+ defaults to the default logger. |
+ |
+ Any additional keyword will be passed as-is to the ColorFormatter |
+ constructor. |
+ """ |
+ if logger is None: |
+ logger = logging.getLogger() |
+ if not logger.handlers: |
+ logging.basicConfig() |
+ format_msg = logger.handlers[0].formatter._fmt |
+ fmt = ColorFormatter(format_msg, **kw) |
+ fmt.colorfilters.append(xxx_cyan) |
+ logger.handlers[0].setFormatter(fmt) |
+ |
+ |
+LOG_FORMAT = '%(asctime)s - (%(name)s) %(levelname)s: %(message)s' |
+LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S' |
+ |
+def get_handler(debug=False, syslog=False, logfile=None, rotation_parameters=None): |
+ """get an apropriate handler according to given parameters""" |
+ if os.environ.get('APYCOT_ROOT'): |
+ handler = logging.StreamHandler(sys.stdout) |
+ if debug: |
+ handler = logging.StreamHandler() |
+ elif logfile is None: |
+ if syslog: |
+ from logging import handlers |
+ handler = handlers.SysLogHandler() |
+ else: |
+ handler = logging.StreamHandler() |
+ else: |
+ try: |
+ if rotation_parameters is None: |
+ handler = logging.FileHandler(logfile) |
+ else: |
+ from logging.handlers import TimedRotatingFileHandler |
+ handler = TimedRotatingFileHandler( |
+ logfile, **rotation_parameters) |
+ except IOError: |
+ handler = logging.StreamHandler() |
+ return handler |
+ |
+def get_threshold(debug=False, logthreshold=None): |
+ if logthreshold is None: |
+ if debug: |
+ logthreshold = logging.DEBUG |
+ else: |
+ logthreshold = logging.ERROR |
+ elif isinstance(logthreshold, basestring): |
+ logthreshold = getattr(logging, THRESHOLD_MAP.get(logthreshold, |
+ logthreshold)) |
+ return logthreshold |
+ |
+def get_formatter(logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT): |
+ isatty = hasattr(sys.__stdout__, 'isatty') and sys.__stdout__.isatty() |
+ if isatty and sys.platform != 'win32': |
+ fmt = ColorFormatter(logformat, logdateformat) |
+ def col_fact(record): |
+ if 'XXX' in record.message: |
+ return 'cyan' |
+ if 'kick' in record.message: |
+ return 'red' |
+ fmt.colorfilters.append(col_fact) |
+ else: |
+ fmt = logging.Formatter(logformat, logdateformat) |
+ return fmt |
+ |
+def init_log(debug=False, syslog=False, logthreshold=None, logfile=None, |
+ logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT, fmt=None, |
+ rotation_parameters=None, handler=None): |
+ """init the log service""" |
+ logger = logging.getLogger() |
+ if handler is None: |
+ handler = get_handler(debug, syslog, logfile, rotation_parameters) |
+ # only addHandler and removeHandler method while I would like a setHandler |
+ # method, so do it this way :$ |
+ logger.handlers = [handler] |
+ logthreshold = get_threshold(debug, logthreshold) |
+ logger.setLevel(logthreshold) |
+ if fmt is None: |
+ if debug: |
+ fmt = get_formatter(logformat=logformat, logdateformat=logdateformat) |
+ else: |
+ fmt = logging.Formatter(logformat, logdateformat) |
+ handler.setFormatter(fmt) |
+ return handler |
+ |
+# map logilab.common.logger thresholds to logging thresholds |
+THRESHOLD_MAP = {'LOG_DEBUG': 'DEBUG', |
+ 'LOG_INFO': 'INFO', |
+ 'LOG_NOTICE': 'INFO', |
+ 'LOG_WARN': 'WARNING', |
+ 'LOG_WARNING': 'WARNING', |
+ 'LOG_ERR': 'ERROR', |
+ 'LOG_ERROR': 'ERROR', |
+ 'LOG_CRIT': 'CRITICAL', |
+ } |