Back to index

salome-kernel  6.5.0
logger.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 #
00003 # Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00004 #
00005 # This library is free software; you can redistribute it and/or
00006 # modify it under the terms of the GNU Lesser General Public
00007 # License as published by the Free Software Foundation; either
00008 # version 2.1 of the License.
00009 #
00010 # This library is distributed in the hope that it will be useful,
00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 # Lesser General Public License for more details.
00014 #
00015 # You should have received a copy of the GNU Lesser General Public
00016 # License along with this library; if not, write to the Free Software
00017 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 #
00019 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00020 #
00021 
00022 #=============================================================================
00023 #  Author    : Guillaume Boulant (CSSI)
00024 #  Rewritten by Renaud Barate (EDF R&D)
00025 #  Project   : SALOME
00026 #  Copyright : EDF 2001-2009
00027 #  $Header: /home/server/cvs/KERNEL/KERNEL_SRC/src/KERNEL_PY/kernel/Attic/logger.py,v 1.1.8.3.12.1 2012-04-12 14:05:14 vsr Exp $
00028 #=============================================================================
00029 """
00030 This module defines a class which provides logging facility in Salome:
00031 """
00032 
00033 import sys, os
00034 import logging
00035 
00036 from salome.kernel.deprecation import deprecated
00037 from salome.kernel import termcolor
00038 import salome.kernel.logconfig
00039 
00040 class Logger(logging.Logger):
00041     """
00042     This class formats and displays log messages in Salome environment. It
00043     inherits :class:`Logger<logging.Logger>` class defined in :mod:`logging`
00044     module from Python library, so all methods from :class:`logging.Logger`
00045     can be used here. The format of the traces is:
00046     
00047     LEVEL    [keyword] : Message
00048     
00049     where `LEVEL` is the level of the message (`DEBUG`, `INFO`, etc.),
00050     `keyword` is the name of the logger, and `Message` is the message to log.
00051     
00052     When creating a new Logger object, the parameter `keyword` defines the
00053     name of the logger, `level` defines the logging level (default is
00054     :const:`logging.DEBUG` if KERNEL module is configured with --enable-debug
00055     option or :const:`logging.WARNING` otherwise), and `color` defines the color
00056     of the log messages for this logger (log messages will appear in color
00057     only when displayed on color-capable ASCII terminals). See module
00058     :mod:`salome.kernel.termcolor` for the color constants.
00059     
00060     By default, log messages will be displayed only on standard output. They
00061     can also be recorded in a file (see method :meth:`setLogFile`). For now,
00062     the CORBA-based logging facility can not be used through this class.
00063 
00064     A source filename `sourceFileName` can be defined. If this argument is
00065     specified, then the `keyword` is modified to the basename of the `sourceFileName`
00066     
00067     Basic usage::
00068     
00069         from salome.kernel.logger import Logger
00070         log = Logger("Test")
00071         log.debug("Debug message")
00072         log.info("Information message")
00073         log.warning("Warning message")
00074         log.error("Error message")
00075         log.critical("Fatal error message")
00076 
00077     """
00078 
00079     def __init__(self, keyword = "KEY", level = salome.kernel.logconfig.loggingLevel,
00080                  color = None, sourceFileName=None):
00081 
00082         if sourceFileName is not None:
00083             keyword = os.path.basename(sourceFileName).split('.')[0]
00084         logging.Logger.__init__(self, keyword, level)
00085         self._baseFormatString = "%(levelname)-8s [%(name)s] : %(message)s"
00086         self._baseFormatter = logging.Formatter(self._baseFormatString)
00087         if hasattr(sys.stdout, "flush"):
00088             self._stdoutStream = sys.stdout
00089         else:
00090             self._stdoutStream = _UnFlushableLogStream(sys.stdout)
00091         self._stdoutHandler = logging.StreamHandler(self._stdoutStream)
00092         self._stdoutHandler.setLevel(logging.DEBUG)
00093         self.setColor(color)
00094         self.addHandler(self._stdoutHandler)
00095         self._fileHandler = None
00096 
00097     def showDebug(self):
00098         """
00099         Log all messages, including DEBUG level messages (equivalent to
00100         ``setLevel(logging.DEBUG)``).
00101         """
00102         self.setLevel(logging.DEBUG)
00103 
00104     def setLogFile(self, logFilename):
00105         """
00106         Define a log file to record the log messages (in addition to the
00107         standard output).
00108         """
00109         self.closeLogFile()
00110         self._fileHandler = logging.FileHandler(logFilename, 'w')
00111         self._fileHandler.setLevel(logging.DEBUG)
00112         self._fileHandler.setFormatter(self._baseFormatter)
00113         self.addHandler(self._fileHandler)
00114 
00115     def setColor(self, color):
00116         """
00117         Set the color of log messages on color-capable terminals. If `color`
00118         is :const:`None`, the default color will be used.
00119         """
00120         if color is None or not termcolor.canDisplayColor(self._stdoutStream):
00121             stdoutFormatter = self._baseFormatter
00122         else:
00123             format = ("%s%s%s" %
00124                       (termcolor.getControlSequence(color),
00125                        self._baseFormatString,
00126                        termcolor.getControlSequence(termcolor.DEFAULT)))
00127             stdoutFormatter = logging.Formatter(format)
00128         self._stdoutHandler.setFormatter(stdoutFormatter)
00129 
00130     def closeLogFile(self):
00131         """Close the log file."""
00132         if self._fileHandler is not None:
00133             self.removeHandler(self._fileHandler)
00134             self._fileHandler.close()
00135             self._fileHandler = None
00136 
00137     def hideDebug(self):
00138         """
00139         Hide DEBUG level messages (equivalent to ``setLevel(logging.INFO)``).
00140         """
00141         self.setLevel(logging.INFO)
00142 
00143     @deprecated("Deprecated since version 5.1.5. Please replace with "
00144                 "Logger.critical(message)")
00145     def fatal(self, message):
00146         """
00147         Log a message with CRITICAL level. This method only exists for
00148         backward compatibility and is equivalent to ``critical(message)``.
00149         """
00150         self.critical(message)
00151 
00152 
00153 class _UnFlushableLogStream:
00154     """
00155     This utility class allows to log messages to a stream with no `flush`
00156     method. This is useful to send log messages to `PyOut` objects.
00157     """
00158 
00159     def __init__(self, stream):
00160         self._stream = stream
00161 
00162     def write(self, msg):
00163         self._stream.write(msg)
00164 
00165     def flush(self):
00166         pass
00167 
00168 
00169 class ExtLogger(Logger):
00170     """
00171     This class extends :class:`Logger` class and adds exception information
00172     when DEBUG messages are recorded. It exists mainly for backward
00173     compatibility, as the same thing can be done by calling
00174     ``Logger.debug(message, exc_info = True)``.
00175     """
00176     
00177     @deprecated("Class ExtLogger is deprecated since version 5.1.5. See "
00178                 "documentation for replacement.")
00179     def __init__(self, keyword = "KEY",
00180                  level = salome.kernel.logconfig.loggingLevel,
00181                  color = None, sourceFileName=None):
00182         Logger.__init__(self, keyword, level, color, sourceFileName)
00183 
00184     def debug( self, message ):
00185         """
00186         Log a DEBUG message with exception information (equivalent to
00187         ``Logger.debug(message, exc_info = True)``).
00188         """
00189         Logger.debug(self, message, exc_info = True)
00190 
00191 
00192 def TEST_Logger():
00193     """Test function for logger module"""
00194     log = Logger("TST")
00195 
00196     # Base methods
00197     log.info("Information message")
00198     log.debug("Debug message")
00199     log.fatal("Fatal error message")
00200 
00201     # Message building
00202     data = 12
00203     log.info("This message displays data = " + str(data))
00204 
00205     data = {}
00206     data["KERNEL"] = "V1"
00207     data["GEOM"] = "V2"
00208     log.info("This message displays data = " + str(data))
00209 
00210     # Test with a non-string parameter
00211     log.info(data)
00212 
00213     # Test with a default instance
00214     log = Logger()
00215     log.info("Default logger")
00216 
00217     # Test showDebug method
00218     log.setLogFile("test.log")
00219     log.debug("Debug trace")
00220     log.hideDebug()
00221     log.debug("This trace should NOT be displayed")
00222     log.showDebug()
00223     log.debug("This trace should be displayed")
00224     log.closeLogFile()
00225     log.info("After closing the log file")
00226 
00227 
00228 # Main function only used to test the module
00229 if __name__ == "__main__":
00230     TEST_Logger()