    async def _measure_event_loop_interval(self):
        """Measure the event loop responsiveness

        A single long-running coroutine because PeriodicCallback is too expensive
        to measure small intervals.
        """
        tick = time.perf_counter

        last_tick = tick()
        resolution = self.event_loop_interval_resolution
        lower_bound = 2 * resolution
        # This loop runs _very_ often, so try to keep it efficient.
        # Even excess comparisons and assignments have a measurable effect on overall cpu usage.
        while True:
            await asyncio.sleep(resolution)
            now = tick()
            # measure the _difference_ between the sleep time and the measured time
            # the event loop blocked for somewhere in the range [delay, delay + resolution]
            tick_duration = now - last_tick
            last_tick = now
            if tick_duration < lower_bound:
                # don't report numbers less than measurement resolution,
                # we don't really have that information
                delay = resolution
            else:
                delay = tick_duration - resolution
                if delay >= self.event_loop_interval_log_threshold:
                    # warn about slow ticks
                    self.log.warning(
                        "Event loop was unresponsive for at least %.2fs!", delay
                    )

            EVENT_LOOP_INTERVAL_SECONDS.observe(delay)
Measure the event loop responsiveness

A single long-running coroutine because PeriodicCallback is too expensive
to measure small intervals.
jupyterhub/metrics.py