Coverage for tests/test_logging.py: 10%

85 statements  

« prev     ^ index     » next       coverage.py v7.2.4, created at 2023-04-29 02:53 -0700

1# This file is part of utils. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12"""Simple unit test for Task logging. 

13""" 

14 

15import logging 

16import time 

17import unittest 

18 

19from lsst.utils.logging import PeriodicLogger, getLogger, trace_set_at 

20 

21 

22class TestLogging(unittest.TestCase): 

23 def testLogLevels(self): 

24 """Check that the new log levels look reasonable.""" 

25 

26 root = getLogger() 

27 

28 self.assertEqual(root.DEBUG, logging.DEBUG) 

29 self.assertGreater(root.VERBOSE, logging.DEBUG) 

30 self.assertLess(root.VERBOSE, logging.INFO) 

31 self.assertLess(root.TRACE, logging.DEBUG) 

32 

33 def testLogCommands(self): 

34 """Check that all the log commands work.""" 

35 

36 root = getLogger() 

37 

38 with self.assertLogs(level=root.TRACE) as cm: 

39 root.trace("Trace") 

40 root.debug("Debug") 

41 root.verbose("Verbose") 

42 root.verbose("Verbose with stacklevel", stacklevel=1) 

43 root.info("Info") 

44 root.warning("Warning") 

45 root.fatal("Fatal") 

46 root.critical("Critical") 

47 root.error("Error") 

48 

49 self.assertEqual(len(cm.records), 9) 

50 

51 # Check that each record has an explicit level name rather than 

52 # "Level N" and comes from this file (and not the logging.py). 

53 for record in cm.records: 

54 self.assertRegex(record.levelname, "^[A-Z]+$") 

55 self.assertEqual(record.filename, "test_logging.py") 

56 

57 with self.assertLogs(level=root.DEBUG) as cm: 

58 # Should only issue the INFO message. 

59 with root.temporary_log_level(root.INFO): 

60 root.info("Info") 

61 root.debug("Debug") 

62 self.assertEqual(len(cm.records), 1) 

63 

64 child = root.getChild("child") 

65 self.assertEqual(child.getEffectiveLevel(), root.getEffectiveLevel()) 

66 

67 # The root logger could be modified by the test environment. 

68 # We need to pick a level that is different. 

69 child.setLevel(root.getEffectiveLevel() - 5) 

70 self.assertNotEqual(child.getEffectiveLevel(), root.getEffectiveLevel()) 

71 

72 def testTraceSetAt(self): 

73 log_name = "lsst.afw" 

74 root_level = logging.getLogger().getEffectiveLevel() 

75 trace_set_at(log_name, 2) 

76 trace2_log = getLogger(f"TRACE2.{log_name}") 

77 trace3_log = getLogger(f"TRACE3.{log_name}") 

78 self.assertEqual(trace2_log.getEffectiveLevel(), logging.DEBUG) 

79 self.assertEqual(trace3_log.getEffectiveLevel(), logging.INFO) 

80 

81 # Check that child loggers are affected. 

82 log_name = "lsst.daf" 

83 child3_log = getLogger("TRACE3.lsst.daf") 

84 child2_log = getLogger("TRACE2.lsst.daf") 

85 self.assertEqual(child3_log.getEffectiveLevel(), root_level) 

86 self.assertEqual(child2_log.getEffectiveLevel(), root_level) 

87 trace_set_at("lsst", 2) 

88 self.assertEqual(child3_log.getEffectiveLevel(), logging.INFO) 

89 self.assertEqual(child2_log.getEffectiveLevel(), logging.DEBUG) 

90 

91 # Also check the root logger. 

92 trace_set_at("", 3) 

93 self.assertEqual(trace3_log.getEffectiveLevel(), logging.INFO) 

94 self.assertEqual(getLogger("TRACE3.test").getEffectiveLevel(), logging.DEBUG) 

95 

96 def test_periodic(self): 

97 logger = getLogger("test.periodicity") 

98 periodic = PeriodicLogger(logger) 

99 

100 # First message will not be issued. 

101 periodic.log("Message") 

102 self.assertEqual(periodic.num_issued, 0) 

103 

104 # Create a new periodic logger with no delay. 

105 # Every message should be issued. 

106 periodic = PeriodicLogger(logger, interval=0.0) 

107 with self.assertLogs(logger.name, level=logger.VERBOSE) as cm: 

108 periodic.log("Message") 

109 periodic.log("Message %d", 1) 

110 self.assertEqual(len(cm.output), 2) 

111 self.assertEqual(periodic.num_issued, 2) 

112 self.assertEqual(cm.output[0], f"VERBOSE:{logger.name}:Message") 

113 self.assertEqual(cm.output[1], f"VERBOSE:{logger.name}:Message 1") 

114 self.assertEqual(cm.records[0].filename, "test_logging.py", str(cm.records[0])) 

115 

116 # Create a new periodic logger with small delay. 

117 # One message should be issued. 

118 periodic = PeriodicLogger(logger, interval=0.2, level=logger.INFO) 

119 with self.assertLogs(logger.name, level=logger.INFO) as cm: 

120 periodic.log("Message") 

121 time.sleep(0.5) 

122 issued = periodic.log("Message %d", 1) 

123 self.assertTrue(issued) 

124 issued = periodic.log("Message %d", 2) 

125 self.assertFalse(issued) 

126 self.assertEqual(periodic.num_issued, 1) 

127 self.assertEqual(cm.output[0], f"INFO:{logger.name}:Message 1") 

128 

129 # Again with a standard python Logger. 

130 pylog = logging.getLogger("python.logger") 

131 periodic = PeriodicLogger(pylog, interval=0.0, level=logging.DEBUG) 

132 with self.assertLogs(pylog.name, level=logging.DEBUG) as cm: 

133 periodic.log("Message") 

134 self.assertEqual(cm.records[0].filename, "test_logging.py", str(cm.records[0])) 

135 

136 

137if __name__ == "__main__": 

138 unittest.main()