25 __all__ = [
"TRACE",
"DEBUG",
"INFO",
"WARN",
"ERROR",
"FATAL",
26 "Log",
"configure",
"configure_prop",
"getDefaultLogger",
"getLogger",
27 "MDC",
"MDCRemove",
"MDCRegisterInit",
"setLevel",
"getLevel",
"isEnabledFor",
28 "log",
"trace",
"debug",
"info",
"warn",
"warning",
"error",
"fatal",
"logf",
29 "tracef",
"debugf",
"infof",
"warnf",
"errorf",
"fatalf",
"lwpID",
30 "usePythonLogging",
"doNotUsePythonLogging",
"UsePythonLogging",
31 "LevelTranslator",
"LogHandler"]
51 UsePythonLogging =
False
52 """Forward Python `lsst.log` messages to Python `logging` package."""
56 """Forward log messages to Python `logging`
60 This is useful for unit testing when you want to ensure
61 that log messages are captured by the testing environment
62 as distinct from standard output.
64 This state only affects messages sent to the `lsst.log`
71 """Forward log messages to LSST logging system.
75 This is the default state.
80 self.
_log(Log.TRACE,
False, fmt, *args)
83 self.
_log(Log.DEBUG,
False, fmt, *args)
85 def info(self, fmt, *args):
86 self.
_log(Log.INFO,
False, fmt, *args)
88 def warn(self, fmt, *args):
89 self.
_log(Log.WARN,
False, fmt, *args)
95 self.
_log(Log.ERROR,
False, fmt, *args)
98 self.
_log(Log.FATAL,
False, fmt, *args)
101 self.
_log(Log.TRACE,
True, fmt, *args, **kwargs)
104 self.
_log(Log.DEBUG,
True, fmt, *args, **kwargs)
106 def infof(self, fmt, *args, **kwargs):
107 self.
_log(Log.INFO,
True, fmt, *args, **kwargs)
109 def warnf(self, fmt, *args, **kwargs):
110 self.
_log(Log.WARN,
True, fmt, *args, **kwargs)
113 self.
_log(Log.ERROR,
True, fmt, *args, **kwargs)
116 self.
_log(Log.FATAL,
True, fmt, *args, **kwargs)
118 def _log(self, level, use_format, fmt, *args, **kwargs):
119 if self.isEnabledFor(level):
120 frame = inspect.currentframe().f_back
122 filename = os.path.split(frame.f_code.co_filename)[1]
123 funcname = frame.f_code.co_name
125 msg = fmt.format(*args, **kwargs)
if args
or kwargs
else fmt
127 msg = fmt % args
if args
else fmt
129 pylog = logging.getLogger(self.getName())
130 record = logging.LogRecord(self.getName(), LevelTranslator.lsstLog2logging(level),
131 filename, frame.f_lineno, msg,
None,
False, func=funcname)
134 self.logMsg(level, filename, funcname, frame.f_lineno, msg)
137 """Implement pickle support.
139 args = (self.getName(), )
141 return (getLogger, args)
151 Log.configure_prop(properties)
155 return Log.getDefaultLogger()
159 return Log.getLogger(loggername)
163 Log.MDC(key, str(value))
171 Log.MDCRegisterInit(func)
175 Log.getLogger(loggername).
setLevel(level)
179 Log.getLogger(loggername).
getLevel()
189 def log(loggername, level, fmt, *args, **kwargs):
190 Log.getLogger(loggername)._log(level,
False, fmt, *args)
194 Log.getDefaultLogger()._log(TRACE,
False, fmt, *args)
198 Log.getDefaultLogger()._log(DEBUG,
False, fmt, *args)
202 Log.getDefaultLogger()._log(INFO,
False, fmt, *args)
206 Log.getDefaultLogger()._log(WARN,
False, fmt, *args)
214 Log.getDefaultLogger()._log(ERROR,
False, fmt, *args)
218 Log.getDefaultLogger()._log(FATAL,
False, fmt, *args)
221 def logf(loggername, level, fmt, *args, **kwargs):
222 Log.getLogger(loggername)._log(level,
True, fmt, *args, **kwargs)
226 Log.getDefaultLogger()._log(TRACE,
True, fmt, *args, **kwargs)
230 Log.getDefaultLogger()._log(DEBUG,
True, fmt, *args, **kwargs)
234 Log.getDefaultLogger()._log(INFO,
True, fmt, *args, **kwargs)
238 Log.getDefaultLogger()._log(WARN,
True, fmt, *args, **kwargs)
242 Log.getDefaultLogger()._log(ERROR,
True, fmt, *args, **kwargs)
246 Log.getDefaultLogger()._log(FATAL,
True, fmt, *args, **kwargs)
258 Log.usePythonLogging()
262 Log.doNotUsePythonLogging()
266 """Context manager to enable Python log forwarding temporarily.
273 Log.usePythonLogging()
275 def __exit__(self, exc_type, exc_value, traceback):
276 Log.UsePythonLogging = self.
current
280 """Helper class to translate levels between ``lsst.log`` and Python
285 """Translates from lsst.log/log4cxx levels to `logging` module levels.
290 Logging level number used by `lsst.log`, typically one of the
291 constants defined in this module (`DEBUG`, `INFO`, etc.)
296 Correspoding logging level number for Python `logging` module.
305 """Translates from standard python `logging` module levels to
306 lsst.log/log4cxx levels.
311 Logging level number used by Python `logging`, typically one of
312 the constants defined by `logging` module (`logging.DEBUG`,
313 `logging.INFO`, etc.)
318 Correspoding logging level number for `lsst.log` module.
324 """Handler for Python logging module that emits to LSST logging.
329 Level at which to set the this handler.
333 If this handler is enabled and `lsst.log` has been configured to use
334 Python `logging`, the handler will do nothing itself if any other
335 handler has been registered with the Python logger. If it does not
336 think that anything else is handling the message it will attempt to
337 send the message via a default `~logging.StreamHandler`. The safest
338 approach is to configure the logger with an additional handler
339 (possibly the ROOT logger) if `lsst.log` is to be configured to use
344 logging.Handler.__init__(self, level=level)
350 logger = Log.getLogger(record.name)
351 if logger.isEnabledFor(LevelTranslator.logging2lsstLog(record.levelno)):
352 logging.Handler.handle(self, record)
355 if Log.UsePythonLogging:
361 pylgr = logging.getLogger(record.name)
365 if any(
not isinstance(h, self.__class__)
for h
in pylgr.handlers):
371 if pylgr.parent
and pylgr.parent.hasHandlers()
and pylgr.propagate:
377 stream = logging.StreamHandler()
378 stream.setFormatter(logging.Formatter(fmt=
"%(name)s %(levelname)s (fallback): %(message)s"))
379 stream.handle(record)
382 logger = Log.getLogger(record.name)
386 logger.logMsg(LevelTranslator.logging2lsstLog(record.levelno),
387 record.filename, record.funcName,
388 record.lineno, message)