Browse Source

[2781] implement skipping collecting and polling statistics to stats

The stats module logs STATS_SKIP_POLLING when it catches an InitSessionTimeout
exception while initially receiving modules information from the init
module. Also, the stats module logs STATS_SKIP_COLLECTING including the name of
the module unable to collect when it catches a SessionTimeout exception while
collecting statistics from that module.
Naoki Kambe 11 years ago
parent
commit
c185e03598
2 changed files with 42 additions and 6 deletions
  1. 17 6
      src/bin/stats/stats.py.in
  2. 25 0
      src/bin/stats/tests/stats_test.py

+ 17 - 6
src/bin/stats/stats.py.in

@@ -186,6 +186,11 @@ class StatsError(Exception):
     """Exception class for Stats class"""
     pass
 
+class InitSessionTimeout(isc.cc.session.SessionTimeout):
+    """SessionTimeout Exception in the session between the stats module and the
+    init module"""
+    pass
+
 class Stats:
     """
     Main class of stats module
@@ -271,6 +276,8 @@ class Stats:
             # TODO: Is it OK to just pass? As part of refactoring, preserving
             # the original behaviour.
             value = None
+        except isc.cc.session.SessionTimeout as e:
+            raise InitSessionTimeout(e)
         modules = []
         if type(value) is list:
             # NOTE: For example, the "show_processes" command
@@ -338,6 +345,7 @@ class Stats:
         _statistics_data = []
         _sequences = sequences[:]
         while len(_sequences) > 0:
+            (module_name, seq) = (None, None)
             try:
                 (module_name, seq) = _sequences.pop(0)
                 answer, env = self.cc_session.group_recvmsg(False, seq)
@@ -348,7 +356,7 @@ class Stats:
                             (module_name, env['from'], args))
             # skip this module if SessionTimeout raised
             except isc.cc.session.SessionTimeout:
-                pass
+                logger.warn(STATS_SKIP_COLLECTING, module_name)
         return _statistics_data
 
     def _refresh_statistics(self, statistics_data):
@@ -371,11 +379,14 @@ class Stats:
            search multiple instances of same module. Second requests
            each module to invoke 'getstats'. Finally updates internal
            statistics data every time it gets from each instance."""
-        modules = self._get_multi_module_list()
-        sequences = self._query_statistics(modules)
-        _statistics_data = self._collect_statistics(sequences)
-        self._refresh_statistics(_statistics_data)
-        # if successfully done, set the last time of polling
+        try:
+            modules = self._get_multi_module_list()
+            sequences = self._query_statistics(modules)
+            _statistics_data = self._collect_statistics(sequences)
+            self._refresh_statistics(_statistics_data)
+        except InitSessionTimeout:
+            logger.warn(STATS_SKIP_POLLING)
+        # if successfully done or skipped, set the last time of polling
         self._lasttime_poll = get_timestamp()
 
     def _check_command(self, nonblock=False):

+ 25 - 0
src/bin/stats/tests/stats_test.py

@@ -1383,6 +1383,16 @@ class TestStats(unittest.TestCase):
         stat.mccs.rpc_call = lambda x,y: __raise(99, 'Error')
         self.assertListEqual([], stat._get_multi_module_list())
 
+    def test_get_multi_module_list_initsessiontimeout(self):
+        """Test _get_multi_module_list() returns an empty list if rcp_call()
+        raise a InitSeeionTimeout exception"""
+        # InitSeeionTimeout case
+        stat = MyStats()
+        ex = stats.InitSessionTimeout
+        def __raise(*x): raise ex(*x)
+        stat.mccs.rpc_call = lambda x,y: __raise()
+        self.assertRaises(ex, stat._get_multi_module_list)
+
     def test_query_statistics(self):
         """Test _query_statistics returns a list of pairs of module and
         sequences from group_sendmsg()"""
@@ -1613,6 +1623,21 @@ class TestStats(unittest.TestCase):
         self.assertEqual(self.const_timestamp, stat._lasttime_poll)
         stats.get_timestamp = orig_get_timestamp
 
+    def test_polling_initsessiontimeout(self):
+        """Test _lasttime_poll is updated after do_polling() in case that it catches
+        InitSesionTimeout at _get_multi_module_list()
+        """
+        orig_get_timestamp = stats.get_timestamp
+        stats.get_timestamp = lambda : self.const_timestamp
+        ex = stats.InitSessionTimeout
+        def __raise(*x): raise ex(*x)
+        stat = MyStats()
+        self.assertEqual(0.0, stat._lasttime_poll)
+        stat._get_multi_module_list = lambda: __raise()
+        stat.do_polling()
+        self.assertEqual(self.const_timestamp, stat._lasttime_poll)
+        stats.get_timestamp = orig_get_timestamp
+
 class Z_TestOSEnv(unittest.TestCase):
     # Running this test would break logging setting.  To prevent it from
     # affecting other tests we use the same workaround as Z_TestOSEnv in