Skip to content

Commit b6d5e17

Browse files
gsaibharjtpio
authored andcommitted
Adding support for jupyterlab statusbar-extension #36
1 parent 434df3f commit b6d5e17

File tree

3 files changed

+86
-44
lines changed

3 files changed

+86
-44
lines changed

nbresuse/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
from notebook.utils import url_path_join
12
from tornado import ioloop
23

4+
from nbresuse.api import ApiHandler
35
from nbresuse.config import ResourceUseDisplay
46
from nbresuse.metrics import PSUtilMetricsLoader
57
from nbresuse.prometheus import PrometheusHandler
@@ -32,7 +34,9 @@ def load_jupyter_server_extension(nbapp):
3234
"""
3335
resuseconfig = ResourceUseDisplay(parent=nbapp)
3436
nbapp.web_app.settings["nbresuse_display_config"] = resuseconfig
37+
route_pattern = url_path_join(nbapp.web_app.settings['base_url'], '/api/nbresuse/v1')
38+
nbapp.web_app.add_handlers('.*', [(route_pattern, ApiHandler)])
3539
callback = ioloop.PeriodicCallback(
3640
PrometheusHandler(PSUtilMetricsLoader(nbapp)), 1000
3741
)
38-
callback.start()
42+
callback.start()

nbresuse/api.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import json
2+
3+
from notebook.base.handlers import IPythonHandler
4+
from tornado import web
5+
6+
try:
7+
# since psutil is an optional dependency
8+
import psutil
9+
except ImportError:
10+
psutil = None
11+
12+
try:
13+
# Traitlets >= 4.3.3
14+
from traitlets import Callable
15+
except ImportError:
16+
from .utils import Callable
17+
18+
19+
class ApiHandler(IPythonHandler):
20+
21+
@web.authenticated
22+
async def get(self):
23+
"""
24+
Calculate and return current resource usage metrics
25+
"""
26+
config = self.settings['nbresuse_display_config']
27+
28+
if psutil:
29+
cur_process = psutil.Process()
30+
all_processes = [cur_process] + cur_process.children(recursive=True)
31+
32+
# Get memory information
33+
rss = sum([p.memory_info().rss for p in all_processes])
34+
35+
if callable(config.mem_limit):
36+
mem_limit = config.mem_limit(rss=rss)
37+
else: # mem_limit is an Int
38+
mem_limit = config.mem_limit
39+
40+
limits = {'memory': {
41+
'rss': mem_limit
42+
}}
43+
if config.mem_limit:
44+
limits['memory']['warn'] = (mem_limit - rss) < (
45+
mem_limit * config.mem_warning_threshold)
46+
47+
metrics = {
48+
'rss': rss,
49+
'limits': limits,
50+
}
51+
52+
self.write(json.dumps(metrics))

nbresuse/static/main.js

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ define([
55
function setupDOM() {
66
$('#maintoolbar-container').append(
77
$('<div>').attr('id', 'nbresuse-display')
8-
.addClass('btn-group')
9-
.addClass('pull-right')
10-
.append(
11-
$('<strong>').text('Memory: ')
12-
).append(
8+
.addClass('btn-group')
9+
.addClass('pull-right')
10+
.append(
11+
$('<strong>').text('Memory: ')
12+
).append(
1313
$('<span>').attr('id', 'nbresuse-mem')
14-
.attr('title', 'Actively used Memory (updates every 5s)')
14+
.attr('title', 'Actively used Memory (updates every 5s)')
1515
)
1616
);
1717
// FIXME: Do something cleaner to get styles in here?
@@ -24,49 +24,35 @@ define([
2424
}
2525

2626
function humanFileSize(size) {
27-
var i = Math.floor( Math.log(size) / Math.log(1024) );
28-
return ( size / Math.pow(1024, i) ).toFixed(1) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
27+
var i = Math.floor(Math.log(size) / Math.log(1024));
28+
return (size / Math.pow(1024, i)).toFixed(1) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
2929
}
3030

31-
32-
function metric(metric_name, text, multiple=false) {
33-
var regex = new RegExp("^" + metric_name + "\{?([^ \}]*)\}? (.*)$", "gm");
34-
var matches = [];
35-
var match;
36-
37-
do{
38-
match = regex.exec(text);
39-
if (match){
40-
matches.push(match)
41-
}
42-
}
43-
while (match);
44-
45-
if (!multiple) {
46-
if (matches.length > 0)
47-
return matches[0];
48-
return null;
49-
}else
50-
return matches;
51-
}
52-
53-
var displayMetrics = function() {
31+
var displayMetrics = function () {
5432
if (document.hidden) {
5533
// Don't poll when nobody is looking
5634
return;
5735
}
58-
$.ajax({
59-
url: utils.get_body_data('baseUrl') + 'metrics',
60-
success: function(data) {
61-
let totalMemoryUsage = metric("total_memory_usage", data);
62-
let maxMemoryUsage = metric("max_memory_usage", data);
36+
$.getJSON({
37+
url: utils.get_body_data('baseUrl') + 'api/nbresuse/v1',
38+
success: function (data) {
39+
totalMemoryUsage = humanFileSize(data['rss']);
40+
41+
var limits = data['limits'];
42+
var display = totalMemoryUsage;
6343

64-
if (maxMemoryUsage[2] <= 0)
65-
return;
66-
totalMemoryUsage = humanFileSize(parseFloat(totalMemoryUsage[2]));
67-
maxMemoryUsage = humanFileSize(parseFloat(maxMemoryUsage[2]));
44+
if (limits['memory']) {
45+
if (limits['memory']['rss']) {
46+
maxMemoryUsage = humanFileSize(limits['memory']['rss']);
47+
display += "/" + maxMemoryUsage
48+
}
49+
if (limits['memory']['warn']) {
50+
$('#nbresuse-display').addClass('nbresuse-warn');
51+
} else {
52+
$('#nbresuse-display').removeClass('nbresuse-warn');
53+
}
54+
}
6855

69-
var display = totalMemoryUsage + "/" + maxMemoryUsage;
7056
$('#nbresuse-mem').text(display);
7157
}
7258
});
@@ -78,7 +64,7 @@ define([
7864
// Update every five seconds, eh?
7965
setInterval(displayMetrics, 1000 * 5);
8066

81-
document.addEventListener("visibilitychange", function() {
67+
document.addEventListener("visibilitychange", function () {
8268
// Update instantly when user activates notebook tab
8369
// FIXME: Turn off update timer completely when tab not in focus
8470
if (!document.hidden) {
@@ -90,4 +76,4 @@ define([
9076
return {
9177
load_ipython_extension: load_ipython_extension,
9278
};
93-
});
79+
});

0 commit comments

Comments
 (0)