Package Products :: Package ZenUtils :: Module configlog |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenUtils.configlog

      1  ######################################################################
      2  #
      3  # Copyright 2011 Zenoss, Inc.  All Rights Reserved.
      4  #
      5  # Copyright 2001-2010 by Vinay Sajip. All Rights Reserved.
      6  #
      7  # Permission to use, copy, modify, and distribute this software and its
      8  # documentation for any purpose and without fee is hereby granted,
      9  # provided that the above copyright notice appear in all copies and that
     10  # both that copyright notice and this permission notice appear in
     11  # supporting documentation, and that the name of Vinay Sajip
     12  # not be used in advertising or publicity pertaining to distribution
     13  # of the software without specific, written prior permission.
     14  # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     15  # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
     16  # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     17  # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     18  # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     19  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     20  ######################################################################
     21
     22  """Creates new loggers from a python logging configuration file."""
     23
     24  import logging
     25  import logging.config
     26  from logging import FileHandler
     27  from logging.handlers import RotatingFileHandler
     28  from logging.handlers import TimedRotatingFileHandler
     29
     30  from .Utils import zenPath
     31
     32  log = logging.getLogger("zen.configlog")
     33
     34
     35 -def _relativeToLogPath(filename):
     36      """Returns the filename relative to ZENHOME/log/"""
     37      if filename.startswith('/'):
     38          return filename
     39      return zenPath('log', filename)
     40
     41
     42 -class ZenFileHandler(FileHandler):
     43      """Like python's FileHandler but relative to ZENHOME/log/"""
     44 -    def __init__(self, filename, mode='a', encoding=None, delay=0):
     45          filename = _relativeToLogPath(filename)
     46          FileHandler.__init__(self, filename, mode, encoding, delay)
     47
     48
     49 -class ZenRotatingFileHandler(RotatingFileHandler):
     50      """Like python's RotatingFileHandler but relative to ZENHOME/log/"""
     51 -    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0):
     52          filename = _relativeToLogPath(filename)
     53          RotatingFileHandler.__init__(self, filename, mode, maxBytes, backupCount, encoding, delay)
     54
     55
     56 -class ZenTimedRotatingFileHandler(TimedRotatingFileHandler):
     57      """Like python's TimedFileHandler but relative to ZENHOME/log/"""
     58 -    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
     59          filename = _relativeToLogPath(filename)
     60          TimedRotatingFileHandler.__init__(self, filename, when, interval, backupCount, encoding, delay, utc)
     61
     62
     63 -def addLogsFromConfigFile(fname, configDefaults=None):
     64      """Add new loggers, handlers, and fomatters from a file.
     65
     66      The file should be in the standard Python log config format described here:
     67      http://docs.python.org/library/logging.config.html#configuration-file-format
     68
     69      This code was copied from the Python 2.7 logging.config.fileConfig()
     70      method, then altered to not require root or wipe existing loggers.
     71      Unfortunately the standard option "disable_existing_loggers=False" would
     72      still wipe out their settings and replace root, undoing Zope's log config.
     73      """
     74      import ConfigParser
     75
     76      try:
     77          cp = ConfigParser.ConfigParser(configDefaults)
     78          if hasattr(fname, 'readline'):
     79              cp.readfp(fname)
     80          else:
     81              cp.read(fname)
     82
     83          formatters = logging.config._create_formatters(cp)
     84      except Exception:
     85          log.exception('Problem with log configuration file: %s', fname)
     86          return
     87
     88      # critical section
     89      logging._acquireLock()
     90      try:
     91          logging._handlers.clear()
     92          del logging._handlerList[:]
     93          # Handlers add themselves to logging._handlers
     94          handlers = logging.config._install_handlers(cp, formatters)
     95          _zen_install_loggers(cp, handlers)
     96      except Exception:
     97          log.exception('Problem with log configuration file: %s', fname)
     98      finally:
     99          logging._releaseLock()
    100
    101
    102 -def _zen_install_loggers(cp, handlers):
    103      """Create and install loggers, without wiping existing ones."""
    104
    105      llist = cp.get("loggers", "keys")
    106      llist = [log.strip() for log in llist.split(",")]
    107      if 'root' in llist:
    108          raise Exception('Zenoss logger config files should not have a root logger.')
    109
    110      #now set up the new ones...
    111      existing_logger_names = logging.root.manager.loggerDict.keys()
    112      for log in llist:
    113          sectname = "logger_%s" % log
    114          qn = cp.get(sectname, "qualname")
    115          opts = cp.options(sectname)
    116          if "propagate" in opts:
    117              propagate = cp.getint(sectname, "propagate")
    118          else:
    119              propagate = 1
    120          if qn in existing_logger_names:
    121              raise Exception("Logger already exists: %s" % qn)
    122          logger = logging.getLogger(qn)
    123          if "level" in opts:
    124              level = cp.get(sectname, "level")
    125              logger.setLevel(logging._levelNames[level])
    126          for h in logger.handlers[:]:
    127              logger.removeHandler(h)
    128          logger.propagate = propagate
    129          logger.disabled = 0
    130          hlist = cp.get(sectname, "handlers")
    131          if len(hlist):
    132              hlist = hlist.split(",")
    133              hlist = logging.config._strip_spaces(hlist)
    134              for hand in hlist:
    135                  logger.addHandler(handlers[hand])
    136