def test_run_with_real_frame(self): # Start a thread and sample a frame from it. from slowlog.compat import Queue from slowlog.compat import get_ident import threading start_queue = Queue() end_queue = Queue() def run(): start_queue.put(get_ident()) end_queue.get() th = threading.Thread(target=run) th.start() try: ident = start_queue.get() # Wait for the thread to start. obj = self._make() obj.queue = self._make_nosleep_queue() reporter = self._make_reporter(report_at=1234.0, ident=ident) obj.reporters.add(reporter) obj.run(time=lambda: 1234.1) finally: end_queue.put(None) # Let the thread end. th.join() self.assertEqual(len(self.reported), 1) report_time, frame = self.reported[0] self.assertEqual(report_time, 1234.1) self.assertIsNotNone(frame) self.assertIsNotNone(frame.f_code.co_filename) self.assertIsNotNone(frame.f_code.co_name) self.assertEqual(len(self.queue_gets), 1) t = self.queue_gets[0][1] self.assertEqual(t, 10.0)
def __init__(self): super(Monitor, self).__init__(name='slowlog_monitor') self.setDaemon(True) self.queue = Queue() # Thread communication: [(reporter, add) or None] self.reporters = set() # set([Reporter])
class Monitor(Thread): """A thread that reports info about activities longer than some threshold. """ min_interval = 0.01 def __init__(self): super(Monitor, self).__init__(name='slowlog_monitor') self.setDaemon(True) self.queue = Queue() # Thread communication: [(reporter, add) or None] self.reporters = set() # set([Reporter]) def add(self, reporter): """Add a Reporter.""" self.queue.put((reporter, True)) def remove(self, reporter): """Remove a Reporter.""" self.queue.put((reporter, False)) def run(self, time=time.time): try: queue = self.queue while True: if not queue.empty(): block = False timeout = None elif self.reporters: report_time = time() timeout_at = report_time + 3600.0 frames = None for reporter in self.reporters: if report_time >= reporter.report_at: if frames is None: frames = sys._current_frames() frame = frames.get(reporter.ident) try: reporter.report_at = (report_time + reporter.interval) reporter(report_time, frame) except Exception: log.exception("Error in reporter %s", reporter) timeout_at = min(timeout_at, reporter.report_at) frames = None # Free memory block = True timeout = max(self.min_interval, timeout_at - report_time) else: # Wait for a reporter. block = True timeout = None try: item = queue.get(block, timeout) except Empty: pass else: if item is None: # Stop looping. break reporter, add = item if add: self.reporters.add(reporter) else: self.reporters.discard(reporter) finally: global _monitor if _monitor_lock is not None: _monitor_lock.acquire() try: if _monitor is self: _monitor = None finally: _monitor_lock.release() else: pass # pragma no cover def stop(self): global _monitor _monitor = None self.queue.put(None)