示例#1
0
    def testPythonLogging(self):
        """Test logging through the Python logging interface."""
        with TestLog.StdoutCapture(self.outputFilename):
            lgr = logging.getLogger()
            lgr.setLevel(logging.INFO)
            log.configure()
            with self.assertLogs(level="INFO") as cm:
                # Force the lsst.log handler to be applied as well as the
                # unittest log handler
                lgr.addHandler(log.LogHandler())
                lgr.info("This is INFO")
                lgr.debug("This is DEBUG")
                lgr.warning("This is %s", "WARNING")
                # message can be arbitrary Python object
                lgr.info(((1, 2), (3, 4)))
                lgr.info({1: 2})

            # Confirm that Python logging also worked
            self.assertEqual(len(cm.output), 4, f"Got output: {cm.output}")
            logging.shutdown()

        self.check("""
root INFO: This is INFO
root WARN: This is WARNING
root INFO: ((1, 2), (3, 4))
root INFO: {1: 2}
""")
示例#2
0
    def initLog(cls, longlog):
        """Initialize logging. This should only be called once per program
        execution. After the first call this will log a warning and return.

        If lsst.log is importable, will add its log handler to the python
        root logger's handlers.

        Parameters
        ----------
        longlog : `bool`
            If True, make log messages appear in long format, by default False.
        """
        if cls._initialized:
            # Unit tests that execute more than one command do end up
            # calling this function multiple times in one program execution,
            # so do log a debug but don't log an error or fail, just make the
            # re-initialization a no-op.
            log = logging.getLogger(__name__)
            log.debug(
                "Log is already initialized, returning without re-initializing."
            )
            return
        cls._initialized = True

        if lsstLog is not None:
            # Initialize global logging config. Skip if the env var
            # LSST_LOG_CONFIG exists. The file it points to would already
            # configure lsst.log.
            if not os.path.isfile(os.environ.get("LSST_LOG_CONFIG", "")):
                lsstLog.configure_prop(
                    _LOG_PROP.format(cls.lsstLog_longLogFmt
                                     if longlog else cls.lsstLog_normalLogFmt))
            cls._recordComponentSetting(None)
            pythonLogger = logging.getLogger()
            pythonLogger.setLevel(logging.INFO)
            cls._lsstLogHandler = lsstLog.LogHandler()
            # Forward all Python logging to lsstLog
            pythonLogger.addHandler(cls._lsstLogHandler)
        else:
            cls._recordComponentSetting(None)
            if longlog:
                logging.basicConfig(level=logging.INFO,
                                    format=cls.pylog_longLogFmt,
                                    datefmt=cls.pylog_longLogDateFmt)
            else:
                logging.basicConfig(level=logging.INFO,
                                    format=cls.pylog_normalFmt)

        # also capture warnings and send them to logging
        logging.captureWarnings(True)

        # remember this call
        cls.configState.append((cls.initLog, longlog))
示例#3
0
    def testPythonLogging(self):
        """Test logging through the Python logging interface."""
        with TestLog.StdoutCapture(self.outputFilename):
            import logging
            lgr = logging.getLogger()
            lgr.setLevel(logging.INFO)
            lgr.addHandler(log.LogHandler())
            log.configure()
            lgr.info("This is INFO")
            lgr.debug("This is DEBUG")
            logging.shutdown()

        self.check("""
root INFO: This is INFO
""")
示例#4
0
    def initLog(cls, longlog):
        """Initialize logging. This should only be called once per program
        execution. After the first call this will log a warning and return.

        If lsst.log is importable, will add its log handler to the python
        root logger's handlers.

        Parameters
        ----------
        longlog : `bool`
            If True, make log messages appear in long format, by default False.
        """
        if cls._initialized:
            # Unit tests that execute more than one command do end up
            # calling this fucntion multiple times in one program execution,
            # so do log a debug but don't log an error or fail, just make the
            # re-initalization a no-op.
            log = logging.getLogger(__name__.partition(".")[2])
            log.debug(
                "Log is already initialized, returning without re-initializing."
            )
            return
        cls._initialized = True

        if lsstLog is not None:
            # global logging config
            lsstLog.configure_prop(
                _LOG_PROP.format(
                    cls.longLogFmt if longlog else cls.normalLogFmt))
            cls._recordComponentSetting(None)
            pythonLogger = logging.getLogger()
            pythonLogger.setLevel(logging.INFO)
            cls._lsstLogHandler = lsstLog.LogHandler()
            # Forward all Python logging to lsstLog
            pythonLogger.addHandler(cls._lsstLogHandler)
        else:
            cls._recordComponentSetting(None)
            logging.basicConfig(level=logging.INFO)

        # also capture warnings and send them to logging
        logging.captureWarnings(True)
示例#5
0
    def testLogLoop(self):
        """Test that Python log forwarding works even if Python logging has
        been forwarded to lsst.log"""

        log.configure()

        # Note that assertLogs causes a specialists Python logging handler
        # to be added.

        # Set up some Python loggers
        loggername = "testLogLoop"
        lgr = logging.getLogger(loggername)
        lgr.setLevel(logging.INFO)
        rootlgr = logging.getLogger()
        rootlgr.setLevel(logging.INFO)

        # Declare that we are using the Python logger and that this will
        # not cause a log loop if we also are forwarding Python logging to
        # lsst.log
        log.usePythonLogging()

        # Ensure that we can log both in lsst.log and Python
        rootlgr.addHandler(log.LogHandler())

        # All three of these messages go through LogHandler
        # The first two because they have the handler added explicitly, the
        # the final one because the lsst.log logger is forwarded to the
        # ROOT Python logger which has the LogHandler registered.

        with open(self.outputFilename, "w") as fd:
            # Adding a StreamHandler will cause the LogHandler to no-op
            streamHandler = logging.StreamHandler(stream=fd)
            rootlgr.addHandler(streamHandler)

            # Do not use assertLogs since that messes with handlers
            lgr.info(
                "INFO message: Python child logger, lsst.log.LogHandler + PythonLogging"
            )
            rootlgr.info(
                "INFO message: Python root logger, lsst.log.logHandler + PythonLogging"
            )

            # This will use a ROOT python logger which has a LogHandler attached
            log.info("INFO message: lsst.log root logger, PythonLogging")

            rootlgr.removeHandler(streamHandler)

        self.check("""
INFO message: Python child logger, lsst.log.LogHandler + PythonLogging
INFO message: Python root logger, lsst.log.logHandler + PythonLogging
INFO message: lsst.log root logger, PythonLogging""")

        with open(self.outputFilename, "w") as fd:
            # Adding a StreamHandler will cause the LogHandler to no-op
            streamHandler = logging.StreamHandler(stream=fd)
            rootlgr.addHandler(streamHandler)

            # Do not use assertLogs since that messes with handlers
            lgr.info(
                "INFO message: Python child logger, lsst.log.LogHandler + PythonLogging"
            )
            rootlgr.info(
                "INFO message: Python root logger, lsst.log.logHandler + PythonLogging"
            )

            # This will use a ROOT python logger which has a LogHandler attached
            log.info("INFO message: lsst.log root logger, PythonLogging")

            rootlgr.removeHandler(streamHandler)

        self.check("""
INFO message: Python child logger, lsst.log.LogHandler + PythonLogging
INFO message: Python root logger, lsst.log.logHandler + PythonLogging
INFO message: lsst.log root logger, PythonLogging""")

        with self.assertLogs(level="INFO") as cm:
            rootlgr.info("Python log message forward to lsst.log")
            log.info("lsst.log message forwarded to Python")

        self.assertEqual(len(cm.output), 2, f"Got output: {cm.output}")

        logging.shutdown()