Skip to content
This repository was archived by the owner on Jul 28, 2023. It is now read-only.

Commit 0f8cb2c

Browse files
authored
Merge pull request #20 from jtpio/cpu
Add CPU indicator to the top bar
2 parents 158a7dd + 3a7f107 commit 0f8cb2c

File tree

12 files changed

+7580
-229
lines changed

12 files changed

+7580
-229
lines changed

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ This extension was originally developed as part of the [jupyterlab-topbar](https
1313

1414
## TODO
1515

16-
- Add CPU usage
1716
- Add Network I/O
1817
- Expose more settings
1918

@@ -40,7 +39,7 @@ conda install -c conda-forge nbresuse
4039

4140
### Graphic Display
4241

43-
You can set the memory limit (but not enforce it) to display the indicator in the top bar.
42+
You can set the memory and cpu limits (but not enforce it) to display the indicator in the top bar.
4443

4544
For more info, check the [memory limit](https://github.com/yuvipanda/nbresuse#memory-limit) in the [nbresuse](https://github.com/yuvipanda/nbresuse) repository.
4645

@@ -49,14 +48,28 @@ Edit `~/.jupyter/jupyter_notebook_config.py`:
4948
```python
5049
c = get_config()
5150

52-
c.NotebookApp.ResourceUseDisplay.mem_limit = Size_of_GB *1024*1024*1024
51+
# memory
52+
c.NotebookApp.ResourceUseDisplay.mem_limit = <size_in_GB> *1024*1024*1024
53+
54+
# cpu
55+
c.NotebookApp.ResourceUseDisplay.track_cpu_percent = True
56+
c.NotebookApp.ResourceUseDisplay.cpu_limit = <number_of_cpus>
57+
```
58+
59+
For example:
60+
61+
```python
62+
c.NotebookApp.ResourceUseDisplay.mem_limit = 4294967296
63+
c.NotebookApp.ResourceUseDisplay.track_cpu_percent = True
64+
c.NotebookApp.ResourceUseDisplay.cpu_limit = 2
5365
```
5466

5567
Or use the command line option:
5668

5769
```bash
5870
# POSIX shell
59-
jupyter lab --NotebookApp.ResourceUseDisplay.mem_limit=$(( Size_of_GB *1024*1024*1024))
71+
jupyter lab --NotebookApp.ResourceUseDisplay.mem_limit=$(( size_in_GB *1024*1024*1024)) \
72+
--NotebookApp.ResourceUseDisplay.cpu_limit=$(( number_of_cpus ))
6073
```
6174

6275
### Advanced Settings

doc/screencast.gif

75.2 KB
Loading
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { ReactWidget } from '@jupyterlab/apputils';
2+
3+
import React, { useEffect, useState, ReactElement } from 'react';
4+
5+
import { IndicatorComponent } from './indicator';
6+
7+
import { ResourceUsage } from './model';
8+
9+
/**
10+
* A CpuView component to display CPU usage.
11+
*/
12+
const CpuViewComponent = ({
13+
model,
14+
label,
15+
}: {
16+
model: ResourceUsage.Model;
17+
label: string;
18+
}): ReactElement => {
19+
const [text, setText] = useState('');
20+
const [values, setValues] = useState([]);
21+
22+
const update = (): void => {
23+
const { currentCpuPercent } = model;
24+
const newValues = model.values.map((value) => value.cpuPercent);
25+
const newText = `${(currentCpuPercent * 100).toFixed(0)}%`;
26+
setText(newText);
27+
setValues(newValues);
28+
};
29+
30+
useEffect(() => {
31+
model.changed.connect(update);
32+
return (): void => {
33+
model.changed.disconnect(update);
34+
};
35+
}, [model]);
36+
37+
return (
38+
<IndicatorComponent
39+
enabled={model.cpuAvailable}
40+
values={values}
41+
label={label}
42+
color={'#0072B3'}
43+
text={text}
44+
/>
45+
);
46+
};
47+
48+
/**
49+
* A namespace for CpuView statics.
50+
*/
51+
export namespace CpuView {
52+
/**
53+
* Create a new CpuView React Widget.
54+
*
55+
* @param model The resource usage model.
56+
* @param label The label next to the component.
57+
*/
58+
export const createCpuView = (
59+
model: ResourceUsage.Model,
60+
label: string
61+
): ReactWidget => {
62+
return ReactWidget.create(<CpuViewComponent model={model} label={label} />);
63+
};
64+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
export * from './cpuView';
12
export * from './memoryView';
3+
export * from './model';
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import React, { useState, ReactElement } from 'react';
2+
3+
import { Sparklines, SparklinesLine, SparklinesSpots } from 'react-sparklines';
4+
5+
/**
6+
* A indicator fill component.
7+
*/
8+
const IndicatorFiller = ({
9+
percentage,
10+
color,
11+
}: {
12+
percentage: number;
13+
color: string;
14+
}): ReactElement => {
15+
return (
16+
<div
17+
className="jp-IndicatorFiller"
18+
style={{
19+
width: `${percentage * 100}%`,
20+
background: `${color}`,
21+
}}
22+
/>
23+
);
24+
};
25+
26+
/**
27+
* An indicator bar component.
28+
*/
29+
const IndicatorBar = ({
30+
values,
31+
percentage,
32+
baseColor,
33+
}: {
34+
values: number[];
35+
percentage: number;
36+
baseColor: string;
37+
}): ReactElement => {
38+
const [isSparklines, setIsSparklines] = useState(false);
39+
40+
const toggleSparklines = (): void => {
41+
setIsSparklines(!isSparklines);
42+
};
43+
44+
const color =
45+
percentage > 0.5 ? (percentage > 0.8 ? 'red' : 'orange') : baseColor;
46+
47+
return (
48+
<div className="jp-IndicatorBar" onClick={(): void => toggleSparklines()}>
49+
{isSparklines && (
50+
<Sparklines
51+
data={values}
52+
min={0.0}
53+
max={1.0}
54+
limit={values.length}
55+
margin={0}
56+
>
57+
<SparklinesLine
58+
style={{
59+
stroke: color,
60+
strokeWidth: 4,
61+
fill: color,
62+
fillOpacity: 1,
63+
}}
64+
/>
65+
<SparklinesSpots />
66+
</Sparklines>
67+
)}
68+
{!isSparklines && (
69+
<IndicatorFiller percentage={percentage} color={color} />
70+
)}
71+
</div>
72+
);
73+
};
74+
75+
/**
76+
* An incicator component for displaying resource usage.
77+
*
78+
*/
79+
export const IndicatorComponent = ({
80+
enabled,
81+
values,
82+
label,
83+
color,
84+
text,
85+
}: {
86+
enabled: boolean;
87+
values: number[];
88+
label: string;
89+
color: string;
90+
text: string;
91+
}): ReactElement => {
92+
const percentage = values[values.length - 1];
93+
return (
94+
enabled && (
95+
<div className="jp-IndicatorContainer">
96+
<div className="jp-IndicatorText">{label}</div>
97+
{percentage !== null && (
98+
<div className="jp-IndicatorWrapper">
99+
<IndicatorBar
100+
values={values}
101+
percentage={percentage}
102+
baseColor={color}
103+
/>
104+
</div>
105+
)}
106+
<div className="jp-IndicatorText">{text}</div>
107+
</div>
108+
)
109+
);
110+
};

0 commit comments

Comments
 (0)