1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #=============================================================================
23 # Author : Guillaume Boulant (CSSI)
24 # Rewritten by Renaud Barate (EDF R&D)
25 #=============================================================================
27 ## \defgroup logger logger
30 # This module defines a class which provides logging facility in Salome.
34 This module defines a class which provides logging facility in Salome:
40 from salome.kernel.deprecation import deprecated
41 from salome.kernel import termcolor
42 import salome.kernel.logconfig
44 ## This class formats and displays log messages in Salome environment. It
45 # inherits \b logging.Logger class defined in \b logging module from Python
46 # library, so all methods from \b logging.Logger can be used here.
47 # The format of the traces is:
48 # LEVEL[keyword] : Message
50 # ,where \em LEVEL is the level of the message (\em DEBUG, \em INFO, etc.),
51 # \em keyword is the name of the logger, and \em Message is the message to log.
53 # When creating a new Logger object, the parameter \em keyword defines the
54 # name of the logger, \em level defines the logging level (default is
55 # \b logging.DEBUG if KERNEL module is configured with --enable-debug option
56 # or \b logging.WARNING otherwise), and \em color defines the color
57 # of the log messages for this logger (log messages will appear in color
58 # only when displayed on color - capable ASCII terminals). See module
59 # \ref termcolor "salome.kernel.termcolor" for the color constants.
61 # By default, log messages will be displayed only on standard output. They
62 # can also be recorded in a file (see method setLogFile()). For now,
63 # the CORBA-based logging facility can not be used through this class.
65 # A source filename \em sourceFileName can be defined. If this argument is
66 # specified, then the \em keyword is modified to the basename of the
71 # from salome.kernel.logger import Logger
72 # log = Logger("Test")
73 # log.debug("Debug message")
74 # log.info("Information message")
75 # log.warning("Warning message")
76 # log.error("Error message")
77 # log.critical("Fatal error message")
80 class Logger(logging.Logger):
82 This class formats and displays log messages in Salome environment. It
83 inherits :class:`Logger<logging.Logger>` class defined in :mod:`logging`
84 module from Python library, so all methods from :class:`logging.Logger`
85 can be used here. The format of the traces is:
87 LEVEL [keyword] : Message
89 where `LEVEL` is the level of the message (`DEBUG`, `INFO`, etc.),
90 `keyword` is the name of the logger, and `Message` is the message to log.
92 When creating a new Logger object, the parameter `keyword` defines the
93 name of the logger, `level` defines the logging level (default is
94 :const:`logging.DEBUG` if KERNEL module is configured with --enable-debug
95 option or :const:`logging.WARNING` otherwise), and `color` defines the color
96 of the log messages for this logger (log messages will appear in color
97 only when displayed on color-capable ASCII terminals). See module
98 :mod:`salome.kernel.termcolor` for the color constants.
100 By default, log messages will be displayed only on standard output. They
101 can also be recorded in a file (see method :meth:`setLogFile`). For now,
102 the CORBA-based logging facility can not be used through this class.
104 A source filename `sourceFileName` can be defined. If this argument is
105 specified, then the `keyword` is modified to the basename of the `sourceFileName`
109 from salome.kernel.logger import Logger
111 log.debug("Debug message")
112 log.info("Information message")
113 log.warning("Warning message")
114 log.error("Error message")
115 log.critical("Fatal error message")
119 def __init__(self, keyword = "KEY", level = salome.kernel.logconfig.loggingLevel,
120 color = None, sourceFileName=None):
122 if sourceFileName is not None:
123 keyword = os.path.basename(sourceFileName).split('.')[0]
124 logging.Logger.__init__(self, keyword, level)
125 self._baseFormatString = "%(levelname)-8s [%(name)s] : %(message)s"
126 self._baseFormatter = logging.Formatter(self._baseFormatString)
127 if hasattr(sys.stdout, "flush"):
128 self._stdoutStream = sys.stdout
130 self._stdoutStream = _UnFlushableLogStream(sys.stdout)
131 self._stdoutHandler = logging.StreamHandler(self._stdoutStream)
132 self._stdoutHandler.setLevel(logging.DEBUG)
134 self.addHandler(self._stdoutHandler)
135 self._fileHandler = None
137 ## Log all messages, including DEBUG level messages (equivalent to
138 # setLevel(logging.DEBUG)).
141 Log all messages, including DEBUG level messages (equivalent to
142 ``setLevel(logging.DEBUG)``).
144 self.setLevel(logging.DEBUG)
146 ## Define a log file to record the log messages (in addition to the
148 def setLogFile(self, logFilename):
150 Define a log file to record the log messages (in addition to the
154 self._fileHandler = logging.FileHandler(logFilename, 'w')
155 self._fileHandler.setLevel(logging.DEBUG)
156 self._fileHandler.setFormatter(self._baseFormatter)
157 self.addHandler(self._fileHandler)
159 ## Set the color of log messages on color-capable terminals. If \em color
160 # is \b None, the default color will be used.
161 def setColor(self, color):
163 Set the color of log messages on color-capable terminals. If `color`
164 is :const:`None`, the default color will be used.
166 if color is None or not termcolor.canDisplayColor(self._stdoutStream):
167 stdoutFormatter = self._baseFormatter
170 (termcolor.getControlSequence(color),
171 self._baseFormatString,
172 termcolor.getControlSequence(termcolor.DEFAULT)))
173 stdoutFormatter = logging.Formatter(format)
174 self._stdoutHandler.setFormatter(stdoutFormatter)
176 ## Close the log file.
177 def closeLogFile(self):
178 """Close the log file."""
179 if self._fileHandler is not None:
180 self.removeHandler(self._fileHandler)
181 self._fileHandler.close()
182 self._fileHandler = None
184 ## Hide DEBUG level messages (equivalent to setLevel(logging.INFO)).
187 Hide DEBUG level messages (equivalent to ``setLevel(logging.INFO)``).
189 self.setLevel(logging.INFO)
191 @deprecated("Deprecated since version 5.1.5. Please replace with "
192 "Logger.critical(message)")
194 ## Log a message with CRITICAL level. This method only exists for
195 # backward compatibility and is equivalent to \b critical(message).
196 def fatal(self, message):
198 Log a message with CRITICAL level. This method only exists for
199 backward compatibility and is equivalent to ``critical(message)``.
201 self.critical(message)
203 ## This utility class allows to log messages to a stream with no \b flush
204 # method. This is useful to send log messages to \b PyOut objects.
206 class _UnFlushableLogStream:
208 This utility class allows to log messages to a stream with no `flush`
209 method. This is useful to send log messages to `PyOut` objects.
212 def __init__(self, stream):
213 self._stream = stream
215 def write(self, msg):
216 self._stream.write(msg)
221 ## This class extends Logger class and adds exception information
222 # when DEBUG messages are recorded. It exists mainly for backward
223 # compatibility, as the same thing can be done by calling
224 # <em> Logger.debug(message, exc_info = True) </em>.
226 class ExtLogger(Logger):
228 This class extends :class:`Logger` class and adds exception information
229 when DEBUG messages are recorded. It exists mainly for backward
230 compatibility, as the same thing can be done by calling
231 ``Logger.debug(message, exc_info = True)``.
234 @deprecated("Class ExtLogger is deprecated since version 5.1.5. See "
235 "documentation for replacement.")
236 def __init__(self, keyword = "KEY",
237 level = salome.kernel.logconfig.loggingLevel,
238 color = None, sourceFileName=None):
239 Logger.__init__(self, keyword, level, color, sourceFileName)
241 ## Log a DEBUG message with exception information (equivalent to
242 # <em> Logger.debug(message, exc_info = True) </em>).
243 def debug( self, message ):
245 Log a DEBUG message with exception information (equivalent to
246 ``Logger.debug(message, exc_info = True)``).
248 Logger.debug(self, message, exc_info = True)
250 ## Test function for logger module
253 """Test function for logger module"""
257 log.info("Information message")
258 log.debug("Debug message")
259 log.fatal("Fatal error message")
263 log.info("This message displays data = " + str(data))
266 data["KERNEL"] = "V1"
268 log.info("This message displays data = " + str(data))
270 # Test with a non-string parameter
273 # Test with a default instance
275 log.info("Default logger")
277 # Test showDebug method
278 log.setLogFile("test.log")
279 log.debug("Debug trace")
281 log.debug("This trace should NOT be displayed")
283 log.debug("This trace should be displayed")
285 log.info("After closing the log file")
288 # Main function only used to test the module
289 if __name__ == "__main__":