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()
186 def log(loggername, level, fmt, *args, **kwargs):
187 Log.getLogger(loggername)._log(level,
False, fmt, *args)
191 Log.getDefaultLogger()._log(TRACE,
False, fmt, *args)
195 Log.getDefaultLogger()._log(DEBUG,
False, fmt, *args)
199 Log.getDefaultLogger()._log(INFO,
False, fmt, *args)
203 Log.getDefaultLogger()._log(WARN,
False, fmt, *args)
211 Log.getDefaultLogger()._log(ERROR,
False, fmt, *args)
215 Log.getDefaultLogger()._log(FATAL,
False, fmt, *args)
218 def logf(loggername, level, fmt, *args, **kwargs):
219 Log.getLogger(loggername)._log(level,
True, fmt, *args, **kwargs)
223 Log.getDefaultLogger()._log(TRACE,
True, fmt, *args, **kwargs)
227 Log.getDefaultLogger()._log(DEBUG,
True, fmt, *args, **kwargs)
231 Log.getDefaultLogger()._log(INFO,
True, fmt, *args, **kwargs)
235 Log.getDefaultLogger()._log(WARN,
True, fmt, *args, **kwargs)
239 Log.getDefaultLogger()._log(ERROR,
True, fmt, *args, **kwargs)
243 Log.getDefaultLogger()._log(FATAL,
True, fmt, *args, **kwargs)
251 Log.usePythonLogging()
255 Log.doNotUsePythonLogging()
259 """Context manager to enable Python log forwarding temporarily.
266 Log.usePythonLogging()
268 def __exit__(self, exc_type, exc_value, traceback):
269 Log.UsePythonLogging = self.
current
273 """Helper class to translate levels between ``lsst.log`` and Python
278 """Translates from lsst.log/log4cxx levels to `logging` module levels.
283 Logging level number used by `lsst.log`, typically one of the
284 constants defined in this module (`DEBUG`, `INFO`, etc.)
289 Correspoding logging level number for Python `logging` module.
298 """Translates from standard python `logging` module levels to
299 lsst.log/log4cxx levels.
304 Logging level number used by Python `logging`, typically one of
305 the constants defined by `logging` module (`logging.DEBUG`,
306 `logging.INFO`, etc.)
311 Correspoding logging level number for `lsst.log` module.
317 """Handler for Python logging module that emits to LSST logging.
322 Level at which to set the this handler.
326 If this handler is enabled and `lsst.log` has been configured to use
327 Python `logging`, the handler will do nothing itself if any other
328 handler has been registered with the Python logger. If it does not
329 think that anything else is handling the message it will attempt to
330 send the message via a default `~logging.StreamHandler`. The safest
331 approach is to configure the logger with an additional handler
332 (possibly the ROOT logger) if `lsst.log` is to be configured to use
337 logging.Handler.__init__(self, level=level)
343 logger = Log.getLogger(record.name)
344 if logger.isEnabledFor(LevelTranslator.logging2lsstLog(record.levelno)):
345 logging.Handler.handle(self, record)
348 if Log.UsePythonLogging:
354 pylgr = logging.getLogger(record.name)
358 if any(
not isinstance(h, self.__class__)
for h
in pylgr.handlers):
364 if pylgr.parent
and pylgr.parent.hasHandlers()
and pylgr.propagate:
370 stream = logging.StreamHandler()
371 stream.setFormatter(logging.Formatter(fmt=
"%(name)s %(levelname)s (fallback): %(message)s"))
372 stream.handle(record)
375 logger = Log.getLogger(record.name)
379 logger.logMsg(LevelTranslator.logging2lsstLog(record.levelno),
380 record.filename, record.funcName,
381 record.lineno, message)