-
Notifications
You must be signed in to change notification settings - Fork 102
/
metrics.py
93 lines (77 loc) · 3.23 KB
/
metrics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
try:
import psutil
except ImportError:
psutil = None
from jupyter_server.serverapp import ServerApp
class PSUtilMetricsLoader:
def __init__(self, server_app: ServerApp):
self.config = server_app.web_app.settings[
"jupyter_resource_usage_display_config"
]
self.server_app = server_app
def get_process_metric_value(self, process, name, args, kwargs, attribute=None):
try:
# psutil.Process methods will either return...
metric_value = getattr(process, name)(*args, **kwargs)
if attribute is not None: # ... a named tuple
return getattr(metric_value, attribute)
else: # ... or a number
return metric_value
# Avoid littering logs with stack traces
# complaining about dead processes
except BaseException:
return 0
def process_metric(self, name, args=[], kwargs={}, attribute=None):
if psutil is None:
return None
else:
current_process = psutil.Process()
all_processes = [current_process] + current_process.children(recursive=True)
process_metric_value = lambda process: self.get_process_metric_value(
process, name, args, kwargs, attribute
)
return sum([process_metric_value(process) for process in all_processes])
def system_metric(self, name, args=[], kwargs={}, attribute=None):
if psutil is None:
return None
else:
# psutil functions will either raise an error, or return...
try:
metric_value = getattr(psutil, name)(*args, **kwargs)
except:
return None
if attribute is not None: # ... a named tuple
return getattr(metric_value, attribute)
else: # ... or a number
return metric_value
def get_metric_values(self, metrics, metric_type):
metric_types = {"process": self.process_metric, "system": self.system_metric}
metric_value = metric_types[metric_type] # Switch statement
metric_values = {}
for metric in metrics:
name = metric["name"]
if metric.get("attribute", False):
name += "_" + metric.get("attribute")
metric_values.update({name: metric_value(**metric)})
return metric_values
def metrics(self, process_metrics, system_metrics):
metric_values = {}
if process_metrics:
metric_values.update(self.get_metric_values(process_metrics, "process"))
if system_metrics:
metric_values.update(self.get_metric_values(system_metrics, "system"))
if any(value is None for value in metric_values.values()):
return None
return metric_values
def memory_metrics(self):
return self.metrics(
self.config.process_memory_metrics, self.config.system_memory_metrics
)
def cpu_metrics(self):
return self.metrics(
self.config.process_cpu_metrics, self.config.system_cpu_metrics
)
def disk_metrics(self):
return self.metrics(
self.config.process_disk_metrics, self.config.system_disk_metrics
)