Skip to content

Commit 237b46e

Browse files
committed
Lots of new features + v0.2 bump!
- Configurable memory usage warnings - More configurability via traitlets - Document memory limit behavior - Add screenshot for memory usage warning - Change 'Mem' prefix in display to less cryptic 'Memory' - Fix primary screenshot to show memory limit too - Consolidate code into single file
1 parent 16689af commit 237b46e

File tree

7 files changed

+138
-47
lines changed

7 files changed

+138
-47
lines changed

README.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# nbresuse
22

3-
![Screenshot](screenshot.png)
3+
![Screenshot with memory limit](screenshot.png)
44

55
NB Resource Usage (nbresuse) is a small extension for Jupyter Notebooks that
66
displays an indication of how much resources your current notebook server and
@@ -9,21 +9,44 @@ main toolbar in the notebook itself, refreshing every 5s.
99

1010
## Installation
1111

12-
You can currently install this directly from git:
12+
You can currently install this package from PyPI.
1313

14+
```bash
15+
pip install nbresuse
1416
```
15-
pip install git+https://github.com/yuvipanda/nbresuse.git
16-
jupyter serverextension enable --py nbresuse
17-
jupyter nbextension install --py nbresuse
18-
```
19-
20-
To enable this extension for all notebooks:
2117

18+
Once installed, you need to enable it for use in your notebook
2219
```
23-
jupyter nbextension enable --py nbresuse
20+
jupyter serverextension enable --py nbresuse --sys-prefix
21+
jupyter nbextension install --py nbresuse --sys-prefix
22+
jupyter nbextension enable --py nbresuse --sys-prefix
2423
```
2524

25+
## Configuration
26+
27+
### Memory Limit
28+
29+
`nbresuse` can display a memory limit (but not enforce it). You can set this
30+
in serveral ways:
31+
32+
1. `MEM_LIMIT` environment variable. This is set by [JupyterHub](http://github.com/jupyterhub/jupyterhub/)
33+
if using a spawner that supports it.
34+
2. In the commandline when starting `jupyter notebook`, as `--ResourceUseDisplay.mem_limit`.
35+
3. In your jupyter notebook [traitlets](https://traitlets.readthedocs.io/en/stable/) config file
36+
37+
The limit needs to be set as an integer in Bytes.
38+
39+
### Memory usage warning threshold
40+
41+
![Screenshot with memory warning](warn-screenshot.png)
42+
43+
The background of the resource display can be changed to red when the user is near a memory limit.
44+
The threshold for this warning can be configured as a fraction of the memory limit.
45+
46+
If you want to flash the warning to the user when they are within 10% of the memory limit, you
47+
can set the parameter `--ResourceUseDisplay.mem_warning_threshold=0.1`.
48+
2649
## Resources displayed
2750

2851
Currently it only displays Memory usage (just RSS). Other metrics will be
29-
added in the future as needed.
52+
added in the future as needed.

nbresuse/__init__.py

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,97 @@
1-
from nbresuse.handlers import setup_handlers
2-
# Jupyter Extension points
1+
import os
2+
import json
3+
import psutil
4+
from traitlets import Float, Int, default
5+
from traitlets.config import Configurable
6+
from notebook.utils import url_path_join
7+
from notebook.base.handlers import IPythonHandler
8+
9+
10+
class MetricsHandler(IPythonHandler):
11+
def get(self):
12+
"""
13+
Calculate and return current resource usage metrics
14+
"""
15+
config = self.settings['nbresuse_display_config']
16+
cur_process = psutil.Process()
17+
all_processes = [cur_process] + cur_process.children(recursive=True)
18+
rss = sum([p.memory_info().rss for p in all_processes])
19+
20+
limits = {}
21+
22+
if config.mem_limit != 0:
23+
limits['memory'] = {
24+
'rss': config.mem_limit
25+
}
26+
if config.mem_warning_threshold != 0:
27+
limits['memory']['warn'] = (config.mem_limit - rss) < (config.mem_limit * config.mem_warning_threshold)
28+
metrics = {
29+
'rss': rss,
30+
'limits': limits,
31+
}
32+
self.write(json.dumps(metrics))
33+
34+
335
def _jupyter_server_extension_paths():
36+
"""
37+
Set up the server extension for collecting metrics
38+
"""
439
return [{
540
'module': 'nbresuse',
641
}]
742

843
def _jupyter_nbextension_paths():
44+
"""
45+
Set up the notebook extension for displaying metrics
46+
"""
947
return [{
1048
"section": "notebook",
1149
"dest": "nbresuse",
1250
"src": "static",
1351
"require": "nbresuse/main"
1452
}]
1553

54+
class ResourceUseDisplay(Configurable):
55+
"""
56+
Holds server-side configuration for nbresuse
57+
"""
58+
59+
mem_warning_threshold = Float(
60+
0.1,
61+
help="""
62+
Warn user with flashing lights when memory usage is within this fraction
63+
memory limit.
64+
65+
For example, if memory limit is 128MB, `mem_warning_threshold` is 0.1,
66+
we will start warning the user when they use (128 - (128 * 0.1)) MB.
67+
68+
Set to 0 to disable warning.
69+
""",
70+
config=True
71+
)
72+
73+
mem_limit = Int(
74+
0,
75+
config=True,
76+
help="""
77+
Memory limit to display to the user, in bytes.
78+
79+
Note that this does not actually limit the user's memory usage!
80+
81+
Defaults to reading from the `MEM_LIMIT` environment variable. If
82+
set to 0, no memory limit is displayed.
83+
"""
84+
)
85+
86+
@default('mem_limit')
87+
def _mem_limit_default(self):
88+
return int(os.environ.get('MEM_LIMIT', 0))
89+
1690
def load_jupyter_server_extension(nbapp):
17-
setup_handlers(nbapp.web_app)
91+
"""
92+
Called during notebook start
93+
"""
94+
resuseconfig = ResourceUseDisplay(parent=nbapp)
95+
nbapp.web_app.settings['nbresuse_display_config'] = resuseconfig
96+
route_pattern = url_path_join(nbapp.web_app.settings['base_url'], '/metrics')
97+
nbapp.web_app.add_handlers('.*', [(route_pattern, MetricsHandler)])

nbresuse/handlers.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

nbresuse/static/main.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
define(['jquery', 'base/js/utils'], function ($, utils) {
2-
function createDisplayDiv() {
2+
function setupDOM() {
33
$('#maintoolbar-container').append(
44
$('<div>').attr('id', 'nbresuse-display')
55
.addClass('btn-group')
66
.addClass('pull-right')
77
.append(
8-
$('<strong>').text('Mem: ')
8+
$('<strong>').text('Memory: ')
99
).append(
1010
$('<span>').attr('id', 'nbresuse-mem')
1111
.attr('title', 'Actively used Memory (updates every 5s)')
1212
)
1313
);
14+
// FIXME: Do something cleaner to get styles in here?
15+
$('head').append(
16+
$('<style>').html('.nbresuse-warn { background-color: #FFD2D2; color: #D8000C; }')
17+
);
18+
$('head').append(
19+
$('<style>').html('#nbresuse-display { padding: 2px 8px; }')
20+
);
1421
}
1522

1623
var displayMetrics = function() {
@@ -19,15 +26,25 @@ define(['jquery', 'base/js/utils'], function ($, utils) {
1926
// after the ., but GB should have 2.
2027
var display = Math.round(data['rss'] / (1024 * 1024));
2128

29+
var limits = data['limits'];
30+
if ('memory' in limits) {
31+
if ('rss' in limits['memory']) {
32+
display += " / " + (limits['memory']['rss'] / (1024 * 1024));
33+
}
34+
if (limits['memory']['warn']) {
35+
$('#nbresuse-display').addClass('nbresuse-warn');
36+
} else {
37+
$('#nbresuse-display').removeClass('nbresuse-warn');
38+
}
39+
}
2240
if (data['limits']['memory'] !== null) {
23-
display += " / " + (data['limits']['memory'] / (1024 * 1024));
2441
}
2542
$('#nbresuse-mem').text(display + ' MB');
2643
});
2744
}
2845

2946
var load_ipython_extension = function () {
30-
createDisplayDiv();
47+
setupDOM();
3148
displayMetrics();
3249
// Update every five seconds, eh?
3350
setInterval(displayMetrics, 1000 * 5);

screenshot.png

-2.78 KB
Loading

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setuptools.setup(
44
name="nbresuse",
5-
version='0.1.0',
5+
version='0.2.0',
66
url="https://github.com/yuvipanda/nbresuse",
77
author="Yuvi Panda",
88
description="Simple Jupyter extension to show how much resources (RAM) your notebook is using",

warn-screenshot.png

5.64 KB
Loading

0 commit comments

Comments
 (0)