Skip to content

Commit f53978c

Browse files
committed
enhancement: Track disk utilization in $HOME
Similar to memory usage tracking, polls the disk used/available in $HOME.
1 parent e6f707b commit f53978c

File tree

6 files changed

+90
-15
lines changed

6 files changed

+90
-15
lines changed

jupyter_resource_usage/api.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import os
23
from concurrent.futures import ThreadPoolExecutor
34
from inspect import isawaitable
45

@@ -61,6 +62,11 @@ async def get(self):
6162
if pss is not None:
6263
metrics["pss"] = pss
6364

65+
if config.track_disk_usage:
66+
disk_info = psutil.disk_usage(os.getenv("HOME"))
67+
metrics["disk_used"] = disk_info.used
68+
metrics["disk_total"] = disk_info.total
69+
6470
# Optionally get CPU information
6571
if config.track_cpu_percent:
6672
cpu_count = psutil.cpu_count()

jupyter_resource_usage/config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class ResourceUseDisplay(Configurable):
3737
Holds server-side configuration for jupyter-resource-usage
3838
"""
3939

40+
system_disk_metrics = List(
41+
trait=PSUtilMetric(),
42+
default_value=[{"name": "disk_usage", "attribute": "disk_used"}],
43+
)
44+
4045
process_memory_metrics = List(
4146
trait=PSUtilMetric(),
4247
default_value=[{"name": "memory_info", "attribute": "rss"}],
@@ -129,3 +134,10 @@ def _cpu_limit_default(self):
129134
Set to False in order to disable reporting of Prometheus style metrics.
130135
""",
131136
).tag(config=True)
137+
138+
track_disk_usage = Bool(
139+
default_value=False,
140+
help="""
141+
Set to True in order to enable reporting of disk usage statistics.
142+
""",
143+
).tag(config=True)

jupyter_resource_usage/metrics.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,6 @@ def cpu_metrics(self):
8080
return self.metrics(
8181
self.config.process_cpu_metrics, self.config.system_cpu_metrics
8282
)
83+
84+
def disk_metrics(self):
85+
return self.metrics(self.config.system_disk_metrics)

packages/labextension/src/memoryView.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ const MemoryViewComponent = ({
2020
const [values, setValues] = useState<number[]>([]);
2121

2222
const update = (): void => {
23-
const { memoryLimit, currentMemory, units } = model;
24-
const precision = ['B', 'KB', 'MB'].indexOf(units) > 0 ? 0 : 2;
23+
const { memoryLimit, currentMemory, memoryUnits } = model;
24+
const precision = ['B', 'KB', 'MB'].indexOf(memoryUnits) > 0 ? 0 : 2;
2525
const newText = `${currentMemory.toFixed(precision)} ${
2626
memoryLimit ? '/ ' + memoryLimit.toFixed(precision) : ''
27-
} ${units}`;
27+
} ${memoryUnits}`;
2828
const newValues = model.values.map((value) => value.memoryPercent);
2929
setText(newText);
3030
setValues(newValues);

packages/labextension/src/model.ts

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,22 @@ export namespace ResourceUsage {
5252
if (phase === 'rejected') {
5353
const oldMemoryAvailable = this._memoryAvailable;
5454
const oldCpuAvailable = this._cpuAvailable;
55+
const oldDiskAvailable = this._diskAvailable;
56+
5557
this._memoryAvailable = false;
5658
this._cpuAvailable = false;
59+
this._diskAvailable = false;
60+
5761
this._currentMemory = 0;
5862
this._memoryLimit = null;
5963
this._cpuLimit = null;
60-
this._units = 'B';
64+
this._memoryUnits = 'B';
6165

62-
if (oldMemoryAvailable || oldCpuAvailable) {
66+
this._diskUnits = 'B';
67+
this._diskUsed = 0;
68+
this._diskTotal = null;
69+
70+
if (oldMemoryAvailable || oldCpuAvailable || oldDiskAvailable) {
6371
this.stateChanged.emit();
6472
}
6573
return;
@@ -79,7 +87,7 @@ export namespace ResourceUsage {
7987
* Whether the metrics server extension is available.
8088
*/
8189
get metricsAvailable(): boolean {
82-
return this._memoryAvailable || this._cpuAvailable;
90+
return this._memoryAvailable || this._cpuAvailable || this._diskAvailable;
8391
}
8492

8593
/**
@@ -120,8 +128,8 @@ export namespace ResourceUsage {
120128
/**
121129
* The units for memory usages and limits.
122130
*/
123-
get units(): MemoryUnit {
124-
return this._units;
131+
get memoryUnits(): MemoryUnit {
132+
return this._memoryUnits;
125133
}
126134

127135
/**
@@ -131,6 +139,22 @@ export namespace ResourceUsage {
131139
return this._currentCpuPercent;
132140
}
133141

142+
get diskAvailable(): boolean {
143+
return this._diskAvailable;
144+
}
145+
146+
get diskUsed(): number {
147+
return this._diskUsed;
148+
}
149+
150+
get diskTotal(): number | null {
151+
return this._diskTotal;
152+
}
153+
154+
get diskUnits(): MemoryUnit {
155+
return this._diskUnits;
156+
}
157+
134158
/**
135159
* Get a list of the last metric values.
136160
*/
@@ -164,26 +188,30 @@ export namespace ResourceUsage {
164188
if (value === null) {
165189
this._memoryAvailable = false;
166190
this._cpuAvailable = false;
191+
this._diskAvailable = false;
167192
this._currentMemory = 0;
168193
this._memoryLimit = null;
169-
this._units = 'B';
194+
this._memoryUnits = 'B';
195+
this._diskUnits = 'B';
196+
this._diskUsed = 0;
197+
this._diskTotal = null;
170198
this._warn = false;
171199
return;
172200
}
173201

174202
const numBytes = value.pss ?? value.rss;
175203
const memoryLimits = value.limits.memory;
176204
const memoryLimit = memoryLimits?.pss ?? memoryLimits?.rss ?? null;
177-
const [currentMemory, units] = convertToLargestUnit(numBytes);
205+
const [currentMemory, memoryUnits] = convertToLargestUnit(numBytes);
178206
const usageWarning = value.limits.memory
179207
? value.limits.memory.warn
180208
: false;
181209

182210
this._memoryAvailable = numBytes !== undefined;
183211
this._currentMemory = currentMemory;
184-
this._units = units;
212+
this._memoryUnits = memoryUnits;
185213
this._memoryLimit = memoryLimit
186-
? memoryLimit / MEMORY_UNIT_LIMITS[units]
214+
? memoryLimit / MEMORY_UNIT_LIMITS[memoryUnits]
187215
: null;
188216
const memoryPercent = this.memoryLimit
189217
? Math.min(this._currentMemory / this.memoryLimit, 1)
@@ -195,19 +223,34 @@ export namespace ResourceUsage {
195223
this._currentCpuPercent =
196224
value.cpu_percent !== undefined ? value.cpu_percent / 100 : 0;
197225

226+
const diskUsedBytes = value.disk_used;
227+
const diskTotal = value.disk_total ?? null;
228+
const [diskUsed, diskUnits] = convertToLargestUnit(diskUsedBytes);
229+
230+
this._diskAvailable = diskTotal ?? false;
231+
this._diskUnits = diskUnits;
232+
this._diskUsed = diskUsed;
233+
this._diskTotal = diskTotal
234+
? diskTotal / MEMORY_UNIT_LIMITS[diskUnits]
235+
: null;
236+
198237
this._values.push({ memoryPercent, cpuPercent: this._currentCpuPercent });
199238
this._values.shift();
200239
this.stateChanged.emit(void 0);
201240
}
202241

203242
private _memoryAvailable = false;
204243
private _cpuAvailable = false;
244+
private _diskAvailable = false;
205245
private _currentMemory = 0;
206246
private _currentCpuPercent = 0;
207247
private _memoryLimit: number | null = null;
208248
private _cpuLimit: number | null = null;
249+
private _diskUsed = 0;
250+
private _diskTotal: number | null = null;
209251
private _poll: Poll<Private.IMetricRequestResult | null>;
210-
private _units: MemoryUnit = 'B';
252+
private _memoryUnits: MemoryUnit = 'B';
253+
private _diskUnits: MemoryUnit = 'B';
211254
private _warn = false;
212255
private _values: Model.IMetricValue[] = [];
213256
}
@@ -268,6 +311,8 @@ namespace Private {
268311
pss?: number;
269312
cpu_percent?: number;
270313
cpu_count?: number;
314+
disk_used?: number;
315+
disk_total?: number;
271316
limits: {
272317
memory?: {
273318
rss: number;

packages/labextension/src/resourceUsage.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,25 @@ export class ResourceUsageStatus extends VDomRenderer<ResourceUsage.Model> {
3737
text = this._trans.__(
3838
'Mem: %1 %2',
3939
this.model.currentMemory.toFixed(Private.DECIMAL_PLACES),
40-
this.model.units
40+
this.model.memoryUnits
4141
);
4242
} else {
4343
text = this._trans.__(
4444
'Mem: %1 / %2 %3',
4545
this.model.currentMemory.toFixed(Private.DECIMAL_PLACES),
4646
this.model.memoryLimit.toFixed(Private.DECIMAL_PLACES),
47-
this.model.units
47+
this.model.memoryUnits
4848
);
4949
}
50+
51+
if (this.model.diskAvailable && this.model.diskTotal !== null) {
52+
text = `${text} ${this._trans.__(
53+
'Disk: %1 / %2 %3',
54+
this.model.diskUsed.toFixed(Private.DECIMAL_PLACES),
55+
this.model.diskTotal.toFixed(Private.DECIMAL_PLACES),
56+
this.model.diskUnits
57+
)}`;
58+
}
5059
if (this.model.cpuAvailable) {
5160
text = `CPU: ${(this.model.currentCpuPercent * 100).toFixed(
5261
Private.DECIMAL_PLACES

0 commit comments

Comments
 (0)