Browse Source

refactor logging throttling mechanism; enhance ThrottlingFilter with dynamic intervals and reset logic;

Silas Gruen 10 months ago
parent
commit
56ab0d88af
2 changed files with 46 additions and 19 deletions
  1. 45 18
      robot-control/src/utils/logging.py
  2. 1 1
      robot-control/src/vision/datamatrix.py

+ 45 - 18
robot-control/src/utils/logging.py

@@ -30,42 +30,69 @@ class LoggerSingleton:
             backupCount=log_config['backup_count']
         )
         file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-        file_handler.addFilter(ThrottlingFilter(throttle_interval=1.0))
+        file_handler.addFilter(ThrottlingFilter())
         file_handler.setFormatter(file_formatter)
         logger.addHandler(file_handler)
 
         if log_config['console_output']:
             console_handler = logging.StreamHandler()
-            console_handler.addFilter(ThrottlingFilter(throttle_interval=1.0))
+            console_handler.addFilter(ThrottlingFilter())
             console_formatter = logging.Formatter('%(levelname)s: %(message)s')
             console_handler.setFormatter(console_formatter)
             logger.addHandler(console_handler)
 
         return logger
-    
-    import logging
-import time
+
 
 class ThrottlingFilter(logging.Filter):
-    def __init__(self, name='', throttle_interval=10.0):
+    def __init__(self, name='', initial_throttle_interval=1.0, max_throttle_interval=120.0, 
+                 throttle_multiplier=2.0, reset_after=120.0):
         """
         :param name: Filter name (can be left empty)
-        :param throttle_interval: Time interval (in seconds) that must pass before a duplicate message is logged.
+        :param initial_throttle_interval: Initial time interval (in seconds) before allowing duplicate messages
+        :param max_throttle_interval: Maximum throttle interval (in seconds)
+        :param throttle_multiplier: Factor by which to increase the interval for repeated messages
+        :param reset_after: Time in seconds after which to reset throttle interval if message wasn't seen
         """
         super().__init__(name)
-        self.throttle_interval = throttle_interval
-        # A dictionary to store the last logged time for each unique message
-        self.last_logged = {}
+        self.initial_throttle_interval = initial_throttle_interval
+        self.max_throttle_interval = max_throttle_interval
+        self.throttle_multiplier = throttle_multiplier
+        self.reset_after = reset_after
+        self.message_states = {}
 
     def filter(self, record):
         current_time = time.time()
-        # Use the log message as a key. For more complex scenarios, you could combine
-        # other record attributes like record.levelno, record.name, etc.
         message_key = record.getMessage()
-        last_time = self.last_logged.get(message_key, 0)
         
-        if current_time - last_time >= self.throttle_interval:
-            self.last_logged[message_key] = current_time
-            return True  # Allow the record to be logged
-        else:
-            return False  # Skip logging this record
+        if message_key not in self.message_states:
+            self.message_states[message_key] = {
+                'last_time': current_time,
+                'current_interval': self.initial_throttle_interval
+            }
+            return True
+        
+        state = self.message_states[message_key]
+        time_since_last = current_time - state['last_time']
+        
+        # Reset throttle interval if message hasn't been seen for reset_after seconds
+        if time_since_last >= self.reset_after:
+            self.message_states[message_key] = {
+                'last_time': current_time,
+                'current_interval': self.initial_throttle_interval
+            }
+            return True
+            
+        if time_since_last >= state['current_interval']:
+            # Message allowed - increase throttle interval for next occurrence
+            next_interval = min(
+                state['current_interval'] * self.throttle_multiplier,
+                self.max_throttle_interval
+            )
+            self.message_states[message_key] = {
+                'last_time': current_time,
+                'current_interval': next_interval
+            }
+            return True
+        
+        return False

+ 1 - 1
robot-control/src/vision/datamatrix.py

@@ -59,7 +59,7 @@ class DataMatrixReader:
         
         decoded = decode(frame)
         if not decoded:
-            logger.error("No datamatrix found")
+            logger.warning("No datamatrix found")
             return None
             
         return decoded[0].data.decode('utf-8')