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

# Source Code for Module Products.ZenUtils.configlog

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