1
1
import json
2
+ from concurrent .futures import ThreadPoolExecutor
2
3
3
4
import psutil
4
5
from notebook .base .handlers import IPythonHandler
5
6
from tornado import web
7
+ from tornado .concurrent import run_on_executor
6
8
7
9
try :
8
10
# Traitlets >= 4.3.3
12
14
13
15
14
16
class ApiHandler (IPythonHandler ):
17
+
18
+ executor = ThreadPoolExecutor (max_workers = 5 )
19
+
15
20
@web .authenticated
16
21
async def get (self ):
17
22
"""
@@ -38,4 +43,30 @@ async def get(self):
38
43
39
44
metrics = {"rss" : rss , "limits" : limits }
40
45
46
+ # Optionally get CPU information
47
+ if config .track_cpu_percent :
48
+ cpu_count = psutil .cpu_count ()
49
+ cpu_percent = await self ._get_cpu_percent (all_processes )
50
+
51
+ if config .cpu_limit != 0 :
52
+ limits ["cpu" ] = {"cpu" : config .cpu_limit }
53
+ if config .cpu_warning_threshold != 0 :
54
+ limits ["cpu" ]["warn" ] = (config .cpu_limit - self .cpu_percent ) < (
55
+ config .cpu_limit * config .cpu_warning_threshold
56
+ )
57
+
58
+ metrics .update (cpu_percent = cpu_percent , cpu_count = cpu_count )
59
+
41
60
self .write (json .dumps (metrics ))
61
+
62
+ @run_on_executor
63
+ def _get_cpu_percent (self , all_processes ):
64
+ def get_cpu_percent (p ):
65
+ try :
66
+ return p .cpu_percent (interval = 0.05 )
67
+ # Avoid littering logs with stack traces complaining
68
+ # about dead processes having no CPU usage
69
+ except :
70
+ return 0
71
+
72
+ return sum ([get_cpu_percent (p ) for p in all_processes ])
0 commit comments