Skip to content

Commit

Permalink
refactor lowe usage percentage
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Neagu committed Mar 19, 2024
1 parent d4050c0 commit 6a8d74e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ ENV JP_LSP_VIRTUAL_DIR="/home/${NB_USER}/.virtual_documents"
COPY --chown=$NB_UID:$NB_GID docker /docker

RUN chmod +x /docker/activity.py \
&& chmod +x /docker/kernel_checker.py
&& chmod +x /docker/activity_monitor.py

RUN echo 'export PATH="/home/${NB_USER}/.venv/bin:$PATH"' >> "/home/${NB_USER}/.bashrc"

Expand Down
39 changes: 36 additions & 3 deletions docker/activity_monitor.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import psutil
import requests
import tornado
import subprocess

from concurrent.futures import ThreadPoolExecutor, as_completed
from contextlib import suppress
Expand All @@ -22,7 +23,7 @@

CHECK_INTERVAL_S: Final[float] = 5
CPU_USAGE_MONITORING_INTERVAL_S: Final[float] = 1
THRESHOLD_CPU_USAGE: Final[float] = 20 # percent in range [0, 100]
THRESHOLD_CPU_USAGE: Final[float] = 5 # percent in range [0, 100]


class JupyterKernelMonitor:
Expand Down Expand Up @@ -51,6 +52,7 @@ def are_kernels_busy(self) -> bool:
class CPUUsageMonitor:
def __init__(self, threshold: float):
self.threshold = threshold

def _get_children_processes(self, pid) -> list[psutil.Process]:
try:
return psutil.Process(pid).children(recursive=True)
Expand All @@ -62,7 +64,7 @@ def _get_brother_processes(self) -> list[psutil.Process]:
# ASSUMPTIONS:
# - `CURRENT_PROC` is a child of root process
# - `CURRENT_PROC` does not create any child processes
#
#
# It looks for its brothers (and their children) p1 to pN in order
# to compute real CPU usage.
# - CURRENT_PROC
Expand All @@ -74,6 +76,15 @@ def _get_brother_processes(self) -> list[psutil.Process]:
children = self._get_children_processes(parent_pid)
return [c for c in children if c.pid != current_process.pid]

def _get_cpu_usage(self, pid: int) -> float:
cmd = f"ps -p {pid} -o %cpu --no-headers"
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
try:
return float(output)
except ValueError:
print(f"Could not parse {pid} cpu usage: {output}")
return float(0)

def _get_total_cpu_usage(self) -> float:
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [
Expand Down Expand Up @@ -122,6 +133,23 @@ async def run(self):
activity_manager = ActivityManager(CHECK_INTERVAL_S)


class DebugHandler(tornado.web.RequestHandler):
def get(self):
self.write(
json.dumps(
{
"cpu_usage": {
"current": activity_manager.cpu_usage_monitor._get_total_cpu_usage(),
"busy": activity_manager.cpu_usage_monitor.are_children_busy(),
},
"kernal_monitor": {
"busy": activity_manager.jupyter_kernel_monitor.are_kernels_busy()
},
}
)
)


class MainHandler(tornado.web.RequestHandler):
def get(self):
idle_seconds = activity_manager.get_idle_seconds()
Expand All @@ -131,7 +159,12 @@ def get(self):


def make_app() -> tornado.web.Application:
return tornado.web.Application([(r"/", MainHandler)])
return tornado.web.Application(
[
(r"/", MainHandler),
(r"/debug", DebugHandler),
]
)


async def main():
Expand Down

0 comments on commit 6a8d74e

Please sign in to comment.