Skip to content

enhancement: Track disk utilization in $HOME #194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions jupyter_resource_usage/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import os
from concurrent.futures import ThreadPoolExecutor
from inspect import isawaitable

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

if config.track_disk_usage:
disk_info = psutil.disk_usage(os.getenv("HOME"))
metrics["disk_used"] = disk_info.used
metrics["disk_total"] = disk_info.total

# Optionally get CPU information
if config.track_cpu_percent:
cpu_count = psutil.cpu_count()
Expand Down
12 changes: 12 additions & 0 deletions jupyter_resource_usage/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class ResourceUseDisplay(Configurable):
Holds server-side configuration for jupyter-resource-usage
"""

system_disk_metrics = List(
trait=PSUtilMetric(),
default_value=[{"name": "disk_usage", "attribute": "disk_used"}],
)

process_memory_metrics = List(
trait=PSUtilMetric(),
default_value=[{"name": "memory_info", "attribute": "rss"}],
Expand Down Expand Up @@ -129,3 +134,10 @@ def _cpu_limit_default(self):
Set to False in order to disable reporting of Prometheus style metrics.
""",
).tag(config=True)

track_disk_usage = Bool(
default_value=False,
help="""
Set to True in order to enable reporting of disk usage statistics.
""",
).tag(config=True)
3 changes: 3 additions & 0 deletions jupyter_resource_usage/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,6 @@ 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.system_disk_metrics)
6 changes: 3 additions & 3 deletions packages/labextension/src/memoryView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const MemoryViewComponent = ({
const [values, setValues] = useState<number[]>([]);

const update = (): void => {
const { memoryLimit, currentMemory, units } = model;
const precision = ['B', 'KB', 'MB'].indexOf(units) > 0 ? 0 : 2;
const { memoryLimit, currentMemory, memoryUnits } = model;
const precision = ['B', 'KB', 'MB'].indexOf(memoryUnits) > 0 ? 0 : 2;
const newText = `${currentMemory.toFixed(precision)} ${
memoryLimit ? '/ ' + memoryLimit.toFixed(precision) : ''
} ${units}`;
} ${memoryUnits}`;
const newValues = model.values.map((value) => value.memoryPercent);
setText(newText);
setValues(newValues);
Expand Down
65 changes: 55 additions & 10 deletions packages/labextension/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,22 @@ export namespace ResourceUsage {
if (phase === 'rejected') {
const oldMemoryAvailable = this._memoryAvailable;
const oldCpuAvailable = this._cpuAvailable;
const oldDiskAvailable = this._diskAvailable;

this._memoryAvailable = false;
this._cpuAvailable = false;
this._diskAvailable = false;

this._currentMemory = 0;
this._memoryLimit = null;
this._cpuLimit = null;
this._units = 'B';
this._memoryUnits = 'B';

if (oldMemoryAvailable || oldCpuAvailable) {
this._diskUnits = 'B';
this._diskUsed = 0;
this._diskTotal = null;

if (oldMemoryAvailable || oldCpuAvailable || oldDiskAvailable) {
this.stateChanged.emit();
}
return;
Expand All @@ -79,7 +87,7 @@ export namespace ResourceUsage {
* Whether the metrics server extension is available.
*/
get metricsAvailable(): boolean {
return this._memoryAvailable || this._cpuAvailable;
return this._memoryAvailable || this._cpuAvailable || this._diskAvailable;
}

/**
Expand Down Expand Up @@ -120,8 +128,8 @@ export namespace ResourceUsage {
/**
* The units for memory usages and limits.
*/
get units(): MemoryUnit {
return this._units;
get memoryUnits(): MemoryUnit {
return this._memoryUnits;
}

/**
Expand All @@ -131,6 +139,22 @@ export namespace ResourceUsage {
return this._currentCpuPercent;
}

get diskAvailable(): boolean {
return this._diskAvailable;
}

get diskUsed(): number {
return this._diskUsed;
}

get diskTotal(): number | null {
return this._diskTotal;
}

get diskUnits(): MemoryUnit {
return this._diskUnits;
}

/**
* Get a list of the last metric values.
*/
Expand Down Expand Up @@ -164,26 +188,30 @@ export namespace ResourceUsage {
if (value === null) {
this._memoryAvailable = false;
this._cpuAvailable = false;
this._diskAvailable = false;
this._currentMemory = 0;
this._memoryLimit = null;
this._units = 'B';
this._memoryUnits = 'B';
this._diskUnits = 'B';
this._diskUsed = 0;
this._diskTotal = null;
this._warn = false;
return;
}

const numBytes = value.pss ?? value.rss;
const memoryLimits = value.limits.memory;
const memoryLimit = memoryLimits?.pss ?? memoryLimits?.rss ?? null;
const [currentMemory, units] = convertToLargestUnit(numBytes);
const [currentMemory, memoryUnits] = convertToLargestUnit(numBytes);
const usageWarning = value.limits.memory
? value.limits.memory.warn
: false;

this._memoryAvailable = numBytes !== undefined;
this._currentMemory = currentMemory;
this._units = units;
this._memoryUnits = memoryUnits;
this._memoryLimit = memoryLimit
? memoryLimit / MEMORY_UNIT_LIMITS[units]
? memoryLimit / MEMORY_UNIT_LIMITS[memoryUnits]
: null;
const memoryPercent = this.memoryLimit
? Math.min(this._currentMemory / this.memoryLimit, 1)
Expand All @@ -195,19 +223,34 @@ export namespace ResourceUsage {
this._currentCpuPercent =
value.cpu_percent !== undefined ? value.cpu_percent / 100 : 0;

const diskUsedBytes = value.disk_used;
const diskTotal = value.disk_total ?? null;
const [diskUsed, diskUnits] = convertToLargestUnit(diskUsedBytes);

this._diskAvailable = diskTotal ?? false;
this._diskUnits = diskUnits;
this._diskUsed = diskUsed;
this._diskTotal = diskTotal
? diskTotal / MEMORY_UNIT_LIMITS[diskUnits]
: null;

this._values.push({ memoryPercent, cpuPercent: this._currentCpuPercent });
this._values.shift();
this.stateChanged.emit(void 0);
}

private _memoryAvailable = false;
private _cpuAvailable = false;
private _diskAvailable = false;
private _currentMemory = 0;
private _currentCpuPercent = 0;
private _memoryLimit: number | null = null;
private _cpuLimit: number | null = null;
private _diskUsed = 0;
private _diskTotal: number | null = null;
private _poll: Poll<Private.IMetricRequestResult | null>;
private _units: MemoryUnit = 'B';
private _memoryUnits: MemoryUnit = 'B';
private _diskUnits: MemoryUnit = 'B';
private _warn = false;
private _values: Model.IMetricValue[] = [];
}
Expand Down Expand Up @@ -268,6 +311,8 @@ namespace Private {
pss?: number;
cpu_percent?: number;
cpu_count?: number;
disk_used?: number;
disk_total?: number;
limits: {
memory?: {
rss: number;
Expand Down
13 changes: 11 additions & 2 deletions packages/labextension/src/resourceUsage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,25 @@ export class ResourceUsageStatus extends VDomRenderer<ResourceUsage.Model> {
text = this._trans.__(
'Mem: %1 %2',
this.model.currentMemory.toFixed(Private.DECIMAL_PLACES),
this.model.units
this.model.memoryUnits
);
} else {
text = this._trans.__(
'Mem: %1 / %2 %3',
this.model.currentMemory.toFixed(Private.DECIMAL_PLACES),
this.model.memoryLimit.toFixed(Private.DECIMAL_PLACES),
this.model.units
this.model.memoryUnits
);
}

if (this.model.diskAvailable && this.model.diskTotal !== null) {
text = `${text} ${this._trans.__(
'Disk: %1 / %2 %3',
this.model.diskUsed.toFixed(Private.DECIMAL_PLACES),
this.model.diskTotal.toFixed(Private.DECIMAL_PLACES),
this.model.diskUnits
)}`;
}
if (this.model.cpuAvailable) {
text = `CPU: ${(this.model.currentCpuPercent * 100).toFixed(
Private.DECIMAL_PLACES
Expand Down