def check(self, obj: FinishedSignagePointMessage) -> Optional[Event]: if self._last_signage_point is None: self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return None event = None valid, skipped = calculate_skipped_signage_points( self._last_signage_point_timestamp, self._last_signage_point, obj.timestamp, obj.signage_point) if not valid: return None # To reduce notification spam, only send notifications for skips larger than 1 if skipped == 1: logging.info( f"Detected {skipped} skipped signage point." "This is expected to happen occasionally and not a reason for concern." ) elif skipped >= 2: message = f"Experiencing networking issues? Skipped {skipped} signage points!" logging.warning(message) event = Event( type=EventType.USER, priority=EventPriority.NORMAL, service=EventService.FULL_NODE, message=message, ) self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return event
def testNoSkips(self): for i in range(1, self.number): skipped = calculate_skipped_signage_points( prev_ts=self.timestamps[i - 1], prev_id=self.ids[i - 1], curr_ts=self.timestamps[i], curr_id=self.ids[i]) self.assertEqual(skipped, 0)
def check(self, obj: FinishedSignagePointMessage) -> Optional[Event]: if self._last_signage_point is None: self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return None event = None valid, skipped = calculate_skipped_signage_points( self._last_signage_point_timestamp, self._last_signage_point, obj.timestamp, obj.signage_point) if not valid: # Reset state when we receive non-valid order of signage points # this ensures that we aren't sending any wrongly calculated skips self._last_signage_point_timestamp = None self._last_signage_point = None return None # To reduce notification spam, only send notifications for skips larger than 1 # or for multiple individual skips within 1 hour if skipped == 1: logging.info(f"Detected {skipped} skipped signage point.") if self._last_skip_timestamp: minutes_since_last_skip = ( datetime.now() - self._last_skip_timestamp).seconds // 60 if minutes_since_last_skip > 60: logging.info( "No other skips in the last 60 minutes. Can be safely ignored." ) else: message = "Experiencing networking issues? Skipped 2+ signage points in the last hour." logging.warning(message) event = Event( type=EventType.USER, priority=EventPriority.NORMAL, service=EventService.FULL_NODE, message=message, ) if skipped >= 2: message = f"Experiencing networking issues? Skipped {skipped} signage points!" logging.warning(message) event = Event( type=EventType.USER, priority=EventPriority.NORMAL, service=EventService.FULL_NODE, message=message, ) if skipped != 0: self._last_skip_timestamp = datetime.now() self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return event
def consume(self, obj: FinishedSignagePointMessage): if self._last_signage_point is None: self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return skips = calculate_skipped_signage_points( self._last_signage_point_timestamp, self._last_signage_point, obj.timestamp, obj.signage_point ) self._skips_total += skips self._total += 1 self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point
def testMultiRolloverSkip(self): skip_indices = range(42, 420) skip_tss = [] skip_ids = [] for i in range(len(self.timestamps)): if i not in skip_indices: skip_tss.append(self.timestamps[i]) skip_ids.append(self.ids[i]) total_skipped = 0 for i in range(1, len(skip_ids)): total_skipped += calculate_skipped_signage_points( prev_ts=skip_tss[i - 1], prev_id=skip_ids[i - 1], curr_ts=skip_tss[i], curr_id=skip_ids[i]) self.assertEqual(len(skip_indices), total_skipped)
def testSingleSkips(self): skip_indices = [42, 63, 124, 234, 333, 335, 338, 420] skip_tss = [] skip_ids = [] for i in range(len(self.timestamps)): if i not in skip_indices: skip_tss.append(self.timestamps[i]) skip_ids.append(self.ids[i]) total_skipped = 0 for i in range(1, len(skip_ids)): total_skipped += calculate_skipped_signage_points( prev_ts=skip_tss[i - 1], prev_id=skip_ids[i - 1], curr_ts=skip_tss[i], curr_id=skip_ids[i]) self.assertEqual(len(skip_indices), total_skipped)
def consume(self, obj: FinishedSignagePointMessage): if self._last_signage_point is None: self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point return valid, skips = calculate_skipped_signage_points( self._last_signage_point_timestamp, self._last_signage_point, obj.timestamp, obj.signage_point) if not valid: # Reset state when we receive non-valid order of signage points # this ensures that we aren't sending any wrongly calculated skips self._last_signage_point_timestamp = None self._last_signage_point = None return self._skips_total += skips self._total += 1 self._last_signage_point_timestamp = obj.timestamp self._last_signage_point = obj.signage_point
def testMultipleSkipsInRow(self): skip_indices = range(42, 69) skip_tss = [] skip_ids = [] for i in range(len(self.timestamps)): if i not in skip_indices: skip_tss.append(self.timestamps[i]) skip_ids.append(self.ids[i]) total_skipped = 0 all_valid = True for i in range(1, len(skip_ids)): valid, skips = calculate_skipped_signage_points( prev_ts=skip_tss[i - 1], prev_id=skip_ids[i - 1], curr_ts=skip_tss[i], curr_id=skip_ids[i]) all_valid = all_valid and valid total_skipped += skips self.assertTrue(all_valid) self.assertEqual(len(skip_indices), total_skipped)