-
Notifications
You must be signed in to change notification settings - Fork 1
/
python_logger.py.bak
288 lines (250 loc) · 10.6 KB
/
python_logger.py.bak
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
#
# This library 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.
#
# This library 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 this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
#=============================================================================
# Author : Guillaume Boulant (CSSI)
# Rewritten by Renaud Barate (EDF R&D)
# Project : SALOME
# Copyright : EDF 2001-2009
# $Header$
#=============================================================================
## \defgroup logger logger
# \{
# \details
# This module defines a class which provides logging facility in Salome.
# \}
"""
This module defines a class which provides logging facility in Salome:
"""
import sys, os
import logging
import termcolor
## This class formats and displays log messages in Salome environment. It
# inherits \b logging.Logger class defined in \b logging module from Python
# library, so all methods from \b logging.Logger can be used here.
# The format of the traces is:
# LEVEL[keyword] : Message
#
# ,where \em LEVEL is the level of the message (\em DEBUG, \em INFO, etc.),
# \em keyword is the name of the logger, and \em Message is the message to log.
#
# When creating a new Logger object, the parameter \em keyword defines the
# name of the logger, \em level defines the logging level (default is
# \b logging.DEBUG if KERNEL module is configured with --enable-debug option
# or \b logging.WARNING otherwise), and \em color defines the color
# of the log messages for this logger (log messages will appear in color
# only when displayed on color - capable ASCII terminals). See module
# \ref termcolor "salome.kernel.termcolor" for the color constants.
#
# By default, log messages will be displayed only on standard output. They
# can also be recorded in a file (see method setLogFile()). For now,
# the CORBA-based logging facility can not be used through this class.
#
# A source filename \em sourceFileName can be defined. If this argument is
# specified, then the \em keyword is modified to the basename of the
# \em sourceFileName
#
# Basic usage::
# \code
# from salome.kernel.logger import Logger
# log = Logger("Test")
# log.debug("Debug message")
# log.info("Information message")
# log.warning("Warning message")
# log.error("Error message")
# log.critical("Fatal error message")
# \endcode
# \ingroup logger
class Logger(logging.Logger):
"""
This class formats and displays log messages in Salome environment. It
inherits :class:`Logger<logging.Logger>` class defined in :mod:`logging`
module from Python library, so all methods from :class:`logging.Logger`
can be used here. The format of the traces is:
LEVEL [keyword] : Message
where `LEVEL` is the level of the message (`DEBUG`, `INFO`, etc.),
`keyword` is the name of the logger, and `Message` is the message to log.
When creating a new Logger object, the parameter `keyword` defines the
name of the logger, `level` defines the logging level (default is
:const:`logging.DEBUG` if KERNEL module is configured with --enable-debug
option or :const:`logging.WARNING` otherwise), and `color` defines the color
of the log messages for this logger (log messages will appear in color
only when displayed on color-capable ASCII terminals). See module
:mod:`salome.kernel.termcolor` for the color constants.
By default, log messages will be displayed only on standard output. They
can also be recorded in a file (see method :meth:`setLogFile`). For now,
the CORBA-based logging facility can not be used through this class.
A source filename `sourceFileName` can be defined. If this argument is
specified, then the `keyword` is modified to the basename of the `sourceFileName`
Basic usage::
from salome.kernel.logger import Logger
log = Logger("Test")
log.debug("Debug message")
log.info("Information message")
log.warning("Warning message")
log.error("Error message")
log.critical("Fatal error message")
"""
def __init__(self, keyword = "KEY", level = logging.DEBUG,
color = None, sourceFileName=None):
if sourceFileName is not None:
keyword = os.path.basename(sourceFileName).split('.')[0]
logging.Logger.__init__(self, keyword, level)
self._baseFormatString = "%(levelname)-8s [%(name)s] : %(message)s"
self._baseFormatter = logging.Formatter(self._baseFormatString)
if hasattr(sys.stdout, "flush"):
self._stdoutStream = sys.stdout
else:
self._stdoutStream = _UnFlushableLogStream(sys.stdout)
self._stdoutHandler = logging.StreamHandler(self._stdoutStream)
self._stdoutHandler.setLevel(level)
self.setColor(color)
self.addHandler(self._stdoutHandler)
self._fileHandler = None
## Log all messages, including DEBUG level messages (equivalent to
# setLevel(logging.DEBUG)).
def showDebug(self):
"""
Log all messages, including DEBUG level messages (equivalent to
``setLevel(logging.DEBUG)``).
"""
self.setLevel(logging.DEBUG)
## Define a log file to record the log messages (in addition to the
# standard output).
def setLogFile(self, logFilename):
"""
Define a log file to record the log messages (in addition to the
standard output).
"""
self.closeLogFile()
self._fileHandler = logging.FileHandler(logFilename, 'w')
self._fileHandler.setLevel(logging.WARNING)
self._fileHandler.setFormatter(self._baseFormatter)
self.addHandler(self._fileHandler)
## Set the color of log messages on color-capable terminals. If \em color
# is \b None, the default color will be used.
def setColor(self, color):
"""
Set the color of log messages on color-capable terminals. If `color`
is :const:`None`, the default color will be used.
"""
if color is None or not termcolor.canDisplayColor(self._stdoutStream):
stdoutFormatter = self._baseFormatter
else:
format = ("%s%s%s" %
(termcolor.getControlSequence(color),
self._baseFormatString,
termcolor.getControlSequence(termcolor.DEFAULT)))
stdoutFormatter = logging.Formatter(format)
self._stdoutHandler.setFormatter(stdoutFormatter)
## Close the log file.
def closeLogFile(self):
"""Close the log file."""
if self._fileHandler is not None:
self.removeHandler(self._fileHandler)
self._fileHandler.close()
self._fileHandler = None
## Hide DEBUG level messages (equivalent to setLevel(logging.INFO)).
def hideDebug(self):
"""
Hide DEBUG level messages (equivalent to ``setLevel(logging.INFO)``).
"""
self.setLevel(logging.INFO)
## Log a message with CRITICAL level. This method only exists for
# backward compatibility and is equivalent to \b critical(message).
def fatal(self, message):
"""
Log a message with CRITICAL level. This method only exists for
backward compatibility and is equivalent to ``critical(message)``.
"""
self.critical(message)
## This utility class allows to log messages to a stream with no \b flush
# method. This is useful to send log messages to \b PyOut objects.
# \ingroup logger
class _UnFlushableLogStream:
"""
This utility class allows to log messages to a stream with no `flush`
method. This is useful to send log messages to `PyOut` objects.
"""
def __init__(self, stream):
self._stream = stream
def write(self, msg):
self._stream.write(msg)
def flush(self):
pass
## This class extends Logger class and adds exception information
# when DEBUG messages are recorded. It exists mainly for backward
# compatibility, as the same thing can be done by calling
# <em> Logger.debug(message, exc_info = True) </em>.
# \ingroup logger
class ExtLogger(Logger):
"""
This class extends :class:`Logger` class and adds exception information
when DEBUG messages are recorded. It exists mainly for backward
compatibility, as the same thing can be done by calling
``Logger.debug(message, exc_info = True)``.
"""
def __init__(self, keyword = "KEY",
level = logging.DEBUG,
color = None, sourceFileName=None):
Logger.__init__(self, keyword, level, color, sourceFileName)
## Log a DEBUG message with exception information (equivalent to
# <em> Logger.debug(message, exc_info = True) </em>).
def debug( self, message ):
"""
Log a DEBUG message with exception information (equivalent to
``Logger.debug(message, exc_info = True)``).
"""
Logger.debug(self, message, exc_info = True)
## Test function for logger module
# \ingroup logger
def TEST_Logger():
"""Test function for logger module"""
log1 = Logger("log1")
log1.setLevel(logging.WARNING)
# Base methods
log1.info("Information message")
log1.debug("Debug message")
log1.fatal("Fatal error message")
log1.warning("WARNING message")
# Message building
data = 12
log1.info("This message displays data = " + str(data))
data = {}
data["KERNEL"] = "V1"
data["GEOM"] = "V2"
log1.info("This message displays data = " + str(data))
# Test with a non-string parameter
log1.info(data)
# Test with a default instance
log2 = Logger("log2")
log2.info("Default logger")
# Test showDebug method
log2.setLogFile("test.log")
log2.debug("Debug trace")
log2.hideDebug()
log2.debug("This trace should NOT be displayed")
log2.showDebug()
log2.debug("This trace should be displayed")
log2.closeLogFile()
log2.info("After closing the log file")
# Main function only used to test the module
if __name__ == "__main__":
TEST_Logger()