Coverage for tests/test_monitor.py: 14%

118 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-01 10:45 +0000

1# This file is part of dax_apdb. 

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# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22import unittest 

23from collections.abc import Mapping 

24from typing import Any 

25 

26from lsst.dax.apdb import monitor, timer 

27 

28 

29class _TestHandler(monitor.MonHandler): 

30 """Implementation of monitoring handler used in unit tests.""" 

31 

32 name: str 

33 tags: Mapping 

34 values: Mapping 

35 agent_name: str 

36 

37 def handle( 

38 self, name: str, timestamp: float, tags: monitor._TagsType, values: Mapping[str, Any], agent_name: str 

39 ) -> None: 

40 self.name = name 

41 self.tags = tags 

42 self.values = values 

43 self.agent_name = agent_name 

44 

45 

46class MonitorTestCase(unittest.TestCase): 

47 """Unit tests for monitoring classes.""" 

48 

49 def setUp(self) -> None: 

50 # MonService is a singleton wit global/shared test, need to reset it 

51 # for each new test. 

52 monsvc = monitor.MonService() 

53 monsvc._handlers = [] 

54 monsvc._context_tags = None 

55 monsvc._filters = [] 

56 

57 def test_simple(self) -> None: 

58 """Test few simple calls.""" 

59 handler = _TestHandler() 

60 monitor.MonService().add_handler(handler) 

61 

62 agent = monitor.MonAgent("007") 

63 agent.add_record("mon", values={"quantity": 1}) 

64 

65 self.assertEqual(handler.name, "mon") 

66 self.assertEqual(handler.tags, {}) 

67 self.assertEqual(handler.values, {"quantity": 1}) 

68 self.assertEqual(handler.agent_name, "007") 

69 

70 def test_two_handlers(self) -> None: 

71 """Test few simple calls with two handlers.""" 

72 handler1 = _TestHandler() 

73 monitor.MonService().add_handler(handler1) 

74 handler2 = _TestHandler() 

75 monitor.MonService().add_handler(handler2) 

76 

77 agent = monitor.MonAgent("007") 

78 agent.add_record("mon", values={"quantity": 1}, tags={"tag1": "atag"}) 

79 

80 self.assertEqual(handler1.name, "mon") 

81 self.assertEqual(handler1.tags, {"tag1": "atag"}) 

82 self.assertEqual(handler1.values, {"quantity": 1}) 

83 self.assertEqual(handler1.agent_name, "007") 

84 self.assertEqual(handler2.name, "mon") 

85 self.assertEqual(handler2.tags, {"tag1": "atag"}) 

86 self.assertEqual(handler2.values, {"quantity": 1}) 

87 self.assertEqual(handler2.agent_name, "007") 

88 

89 def test_tag_context(self) -> None: 

90 """Test tag context.""" 

91 handler = _TestHandler() 

92 monitor.MonService().add_handler(handler) 

93 

94 agent = monitor.MonAgent("007") 

95 

96 with agent.context_tags({"tag1": "atag"}): 

97 agent.add_record("mon", values={"quantity": 1}) 

98 

99 self.assertEqual(handler.name, "mon") 

100 self.assertEqual(handler.tags, {"tag1": "atag"}) 

101 self.assertEqual(handler.values, {"quantity": 1}) 

102 self.assertEqual(handler.agent_name, "007") 

103 

104 def test_logging_handler(self) -> None: 

105 """Test logging handler.""" 

106 handler = monitor.LoggingMonHandler("logger") 

107 monitor.MonService().add_handler(handler) 

108 

109 agent = monitor.MonAgent("007") 

110 

111 with self.assertLogs("logger", level="INFO") as cm: 

112 # Need to use fixed timestamps here to be able to compare strings. 

113 agent.add_record("mon", values={"quantity": 1}, tags={"tag1": "atag1"}, timestamp=100.0) 

114 agent.add_record("mon", values={"quantity": 2}, tags={"tag1": "atag2"}, timestamp=101.0) 

115 self.assertEqual( 

116 cm.output, 

117 [ 

118 'INFO:logger:{"name": "mon", "timestamp": 100.0, ' 

119 '"tags": {"tag1": "atag1"}, "values": {"quantity": 1}, "source": "007"}', 

120 'INFO:logger:{"name": "mon", "timestamp": 101.0, ' 

121 '"tags": {"tag1": "atag2"}, "values": {"quantity": 2}, "source": "007"}', 

122 ], 

123 ) 

124 

125 def test_timer(self) -> None: 

126 """Test monitoring output via Timer.""" 

127 handler = _TestHandler() 

128 monitor.MonService().add_handler(handler) 

129 

130 agent = monitor.MonAgent("007") 

131 with agent.context_tags({"tag1": "atag"}): 

132 with timer.Timer("timer", agent): 

133 pass 

134 self.assertEqual(handler.name, "timer") 

135 self.assertEqual(handler.tags, {"tag1": "atag"}) 

136 self.assertEqual(set(handler.values), {"real", "user", "sys"}) 

137 self.assertEqual(handler.agent_name, "007") 

138 

139 def test_filters(self) -> None: 

140 """Test agent filtering.""" 

141 handler = _TestHandler() 

142 monitor.MonService().add_handler(handler) 

143 

144 # Note that unlike in the `logging` there is no parent/child relation 

145 # between agent, disabling "lsst" will not disable two others. 

146 agent1 = monitor.MonAgent("lsst.agent1") 

147 agent2 = monitor.MonAgent("lsst.agent2") 

148 agent3 = monitor.MonAgent("lsst") 

149 

150 # By default nothing is filtered 

151 agent1.add_record("mon1", values={"quantity": 1}) 

152 self.assertEqual(handler.name, "mon1") 

153 self.assertEqual(handler.values["quantity"], 1) 

154 agent2.add_record("mon2", values={"quantity": 2}) 

155 self.assertEqual(handler.name, "mon2") 

156 self.assertEqual(handler.values["quantity"], 2) 

157 agent3.add_record("mon3", values={"quantity": 3}) 

158 self.assertEqual(handler.name, "mon3") 

159 self.assertEqual(handler.values["quantity"], 3) 

160 

161 # Disable one of them. 

162 monitor.MonService().set_filters(["-lsst"]) 

163 agent1.add_record("mon1", values={"quantity": 1}) 

164 self.assertEqual(handler.name, "mon1") 

165 self.assertEqual(handler.values["quantity"], 1) 

166 agent2.add_record("mon2", values={"quantity": 2}) 

167 self.assertEqual(handler.name, "mon2") 

168 self.assertEqual(handler.values["quantity"], 2) 

169 agent3.add_record("mon3", values={"quantity": 3}) 

170 self.assertEqual(handler.name, "mon2") 

171 self.assertEqual(handler.values["quantity"], 2) 

172 

173 # Disable all except one. 

174 monitor.MonService().set_filters(["+lsst.agent1", "-any"]) 

175 agent1.add_record("mon1", values={"quantity": 1}) 

176 self.assertEqual(handler.name, "mon1") 

177 self.assertEqual(handler.values["quantity"], 1) 

178 agent2.add_record("mon2", values={"quantity": 2}) 

179 self.assertEqual(handler.name, "mon1") 

180 self.assertEqual(handler.values["quantity"], 1) 

181 agent3.add_record("mon3", values={"quantity": 3}) 

182 self.assertEqual(handler.name, "mon1") 

183 self.assertEqual(handler.values["quantity"], 1) 

184 

185 # Plus sign is optional in the rule. 

186 monitor.MonService().set_filters(["+lsst.agent1", "lsst.agent2", "-lsst"]) 

187 agent1.add_record("mon1", values={"quantity": 1}) 

188 self.assertEqual(handler.name, "mon1") 

189 self.assertEqual(handler.values["quantity"], 1) 

190 agent2.add_record("mon2", values={"quantity": 2}) 

191 self.assertEqual(handler.name, "mon2") 

192 self.assertEqual(handler.values["quantity"], 2) 

193 agent3.add_record("mon3", values={"quantity": 3}) 

194 self.assertEqual(handler.name, "mon2") 

195 self.assertEqual(handler.values["quantity"], 2) 

196 

197 

198if __name__ == "__main__": 

199 unittest.main()