Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
improved chart visuals and added tooltip with additional information
Changes in detail:
- show load in percent
- pined chart y max to 100%
- added units to chart y-Axis
- added small (by default) blue box to CPU load legend (like the one that was in the RAM legend)
- added hover text to the "Load average: XX.X % (X.XX) last minute" that displays the load averages for 1, 5 and 15 minutes
- added tooltip to both charts that display the cpu load / ram usage at the time where the cursor hovers.

Signed-off-by: Malex14 <[email protected]>
  • Loading branch information
Malex14 authored and kesselb committed Dec 12, 2024
commit 2c6f3e5de310e1918b3e913869920f8ae13e9add
21 changes: 18 additions & 3 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
margin-top: 0;
}

.rambox {
.rambox, .cpubox {
height: 10px;
width: 10px;
background-color: #555;
background-color: var(--color-primary-element);
}

.swapbox {
height: 10px;
width: 10px;
background-color: #222;
background-color: var(--color-background-darker);
}

.info {
Expand Down Expand Up @@ -291,3 +291,18 @@
.active-users-box .info {
font-size: 2rem;
}

.smoothie-chart-tooltip {
display: flex;
flex-wrap: nowrap;
align-items: center;
padding: 16px;
margin: 0 0.25rem;
background-color: var(--color-main-background);
border: 2px solid var(--color-border);
border-radius: var(--border-radius-large);
}

.cpu-wrapper {
width: 100%;
}
107 changes: 68 additions & 39 deletions js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
memoryUsageLine,
swapUsageLine,
cpuLoadChart,
cpuLoadLine,
activeUsersChart,
sharesChart;

$(document).ready(function () {
var rambox = document.getElementById('rambox');
rambox.style.backgroundColor = OCA.Theming ? OCA.Theming.color : 'rgb(54, 129, 195)';

var swapbox = document.getElementById('swapbox');
swapbox.style.backgroundColor = 'rgba(100, 100, 100, 0.8)';
cpuLoadLine

const chartOptions = {
millisPerPixel: 100,
minValue: 0,
grid: {fillStyle: 'rgba(0,0,0,0)', strokeStyle: 'transparent'},
labels: {fillStyle: getThemedPassiveColor(), fontSize: 12, precision: 1},
responsive: true,
tooltip: true,
tooltipLine: {
strokeStyle: getThemedPassiveColor()
}
};

$(function () {
initDiskCharts();

setHumanReadableSizeToElement("databaseSize");
Expand All @@ -37,7 +41,7 @@

$.get(url)
.done(function (response) {
updateCPUStatistics(response.system.cpuload)
updateCPUStatistics(response.system.cpuload, response.system.cpunum)
updateMemoryStatistics(response.system.mem_total, response.system.mem_free, response.system.swap_total, response.system.swap_free)
})
.always(function () {
Expand All @@ -63,10 +67,10 @@
* Reset all canvas widths on window resize so canvas is responsive
*/
function resizeSystemCharts() {
var cpuCanvas = $("#cpuloadcanvas"),
cpuCanvasWidth = cpuCanvas.parents('.infobox').width() - 30,
let cpuCanvas = $("#cpuloadcanvas"),
cpuCanvasWidth = cpuCanvas.parents('.infobox').width(),
memCanvas = $("#memorycanvas"),
memCanvasWidth = memCanvas.parents('.infobox').width() - 30;
memCanvasWidth = memCanvas.parents('.infobox').width();


// We have to set css width AND attribute width
Expand All @@ -76,9 +80,14 @@
memCanvas.attr('width', memCanvasWidth);
}

function updateCPUStatistics(cpuload) {
var $cpuFooterInfo = $('#cpuFooterInfo');
var $cpuLoadCanvas = $('#cpuloadcanvas');
function updateCPUStatistics(cpuload, numCpus) {
let $cpuFooterInfo = $('#cpuFooterInfo');
let $cpuLoadCanvas = $('#cpuloadcanvas');

// We need to stop touch events here, since they cause the tooltip to open, but never close again
$cpuLoadCanvas[0].addEventListener('touchstart', (e) => {
e.preventDefault();
})

if (cpuload === 'N/A') {
$cpuFooterInfo.text(t('serverinfo', 'CPU info not available'));
Expand All @@ -89,30 +98,43 @@
$cpuLoadCanvas.removeClass('hidden');
}

var cpu1 = cpuload[0],
cpu2 = cpuload[1],
cpu3 = cpuload[2];
let cpuloadFixed = cpuload.map((load) => load.toFixed(2));
let cpuloadPercentageFixed = cpuload.map((load) => ((load / numCpus) * 100).toFixed(1));

if (typeof cpuLoadChart === 'undefined') {
cpuLoadChart = new SmoothieChart(
{
millisPerPixel: 100,
minValue: 0,
grid: {fillStyle: 'rgba(0,0,0,0)', strokeStyle: 'transparent'},
labels: {fillStyle: 'rgba(0,0,0,0.4)', fontSize: 12},
responsive: true
});
const percentageFormatter = (val, precision) => val.toFixed(precision) + " %";

cpuLoadChart = new SmoothieChart({
...chartOptions,
yMinFormatter: percentageFormatter,
yMaxFormatter: percentageFormatter,
maxValue: 100
});
cpuLoadChart.streamTo(document.getElementById("cpuloadcanvas"), 1000/*delay*/);
cpuLoadLine = new TimeSeries();
cpuLoadChart.addTimeSeries(cpuLoadLine, {
lineWidth: 1,
strokeStyle: getThemedPassiveColor(),
fillStyle: getThemedPrimaryColor()
fillStyle: getThemedPrimaryColor(),
tooltipLabel: t('serverinfo', 'CPU Usage:')
});
}

$cpuFooterInfo.text(t('serverinfo', 'Load average: {cpu} (last minute)', { cpu: cpu1.toFixed(2) }));
cpuLoadLine.append(new Date().getTime(), cpu1);
$cpuFooterInfo.text(t('serverinfo', 'Load average: {percentage} % ({cpu}) last minute', { percentage: cpuloadPercentageFixed[0], cpu: cpuloadFixed[0] }));
$cpuFooterInfo[0].title = t(
'serverinfo',
'{lastMinutePercentage} % ({lastMinute}) last Minute\n{last5MinutesPercentage} % ({last5Minutes}) last 5 Minutes\n{last15MinutesPercentage} % ({last15Minutes}) last 15 Minutes',
{
lastMinute: cpuloadFixed[0],
lastMinutePercentage: cpuloadPercentageFixed[0],
last5Minutes: cpuloadFixed[1],
last5MinutesPercentage: cpuloadPercentageFixed[1],
last15Minutes: cpuloadFixed[2],
last15MinutesPercentage: cpuloadPercentageFixed[2]
}
);

cpuLoadLine.append(new Date().getTime(), cpuload[0]);
}

function isMemoryStat(memTotal, memFree) {
Expand All @@ -136,6 +158,11 @@
var $swapFooterInfo = $('#swapFooterInfo');
var $memoryCanvas = $('#memorycanvas');

// We need to stop touch events here, since they cause the tooltip to open, but never close again
$memoryCanvas[0].addEventListener('touchstart', (e) => {
e.preventDefault();
})

var memTotalBytes = memTotal * 1024,
memUsageBytes = (memTotal - memFree) * 1024,
memTotalGB = memTotal / (1024 * 1024),
Expand All @@ -152,27 +179,29 @@
}

if (typeof memoryUsageChart === 'undefined') {
const gbFormatter = (val, precision) => val.toFixed(precision) + " GB";

memoryUsageChart = new SmoothieChart(
{
millisPerPixel: 100,
...chartOptions,
maxValue: maxValueOfChart,
minValue: 0,
grid: {fillStyle: 'rgba(0,0,0,0)', strokeStyle: 'transparent'},
labels: {fillStyle: 'rgba(0,0,0,0.4)', fontSize: 12},
responsive: true
yMinFormatter: gbFormatter,
yMaxFormatter: gbFormatter
});
memoryUsageChart.streamTo(document.getElementById("memorycanvas"), 1000/*delay*/);
memoryUsageLine = new TimeSeries();
memoryUsageChart.addTimeSeries(memoryUsageLine, {
lineWidth: 1,
strokeStyle: getThemedPassiveColor(),
fillStyle: getThemedPrimaryColor()
fillStyle: getThemedPrimaryColor(),
tooltipLabel: t('serverinfo', 'RAM Usage:')
});
swapUsageLine = new TimeSeries();
memoryUsageChart.addTimeSeries(swapUsageLine, {
lineWidth: 1,
strokeStyle: 'rgb(100, 100, 100)',
fillStyle: 'rgba(100, 100, 100, 0.2)'
strokeStyle: getThemedPassiveColor(),
fillStyle: 'rgba(100, 100, 100, 0.2)',
tooltipLabel: t('serverinfo', 'SWAP Usage:')
});
}

Expand Down
2 changes: 1 addition & 1 deletion js/smoothie.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@
}
var el = this.getTooltipEl();
el.style.top = Math.round(this.mousePageY) + 'px';
el.style.left = Math.round(this.mousePageX) + 'px';
el.style.right = `calc(100vw - ${Math.round(this.mousePageX)}px)`;
this.updateTooltip();
};

Expand Down
11 changes: 11 additions & 0 deletions lib/OperatingSystems/FreeBSD.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ public function getCpuName(): string {
return $data;
}

public function getCpuCount(): int {
$numCpu = 1; // this should be a save default

try {
$numCpu = intval($this->executeCommand('sysctl -n hw.ncpu')); //TODO: this should be tested if it actually works on FreeBSD
} catch (RuntimeException) {}

return $numCpu;
}

public function getTime(): string {
try {
return $this->executeCommand('date');
Expand Down Expand Up @@ -247,4 +257,5 @@ protected function getNetInterfaces(): array {
}
return $data;
}

}
7 changes: 7 additions & 0 deletions lib/OperatingSystems/IOperatingSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ public function supported(): bool;
*/
public function getCpuName(): string;

/**
* Get number of processors (threads).
*
* @return int
*/
public function getCpuCount(): int;

/**
* Get disk info returns a list of Disk objects. Used and Available in bytes.
*
Expand Down
11 changes: 11 additions & 0 deletions lib/OperatingSystems/Linux.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ public function getCpuName(): string {
return $data;
}

public function getCpuCount(): int
{
$numCpu = 1; // this should be a save default

try {
$numCpu = intval($this->executeCommand('nproc --all'));
} catch (RuntimeException) {}

return $numCpu;
}

public function getTime(): string {
try {
return $this->executeCommand('date');
Expand Down
4 changes: 4 additions & 0 deletions lib/Os.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public function getCpuName(): string {
return $this->backend->getCpuName();
}

public function getCpuCount(): int {
return $this->backend->getCpuCount();
}

public function getTime(): string {
return $this->backend->getTime();
}
Expand Down
2 changes: 2 additions & 0 deletions lib/SystemStatistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function __construct(IConfig $config, IAppManager $appManager, Installer
public function getSystemStatistics(bool $skipApps = false, bool $skipUpdate = true): array {
$processorUsage = $this->getProcessorUsage();
$memoryUsage = $this->os->getMemory();
$numCPU = $this->os->getCpuCount();

$data = [
'version' => $this->config->getSystemValue('version'),
Expand All @@ -52,6 +53,7 @@ public function getSystemStatistics(bool $skipApps = false, bool $skipUpdate = t
'debug' => $this->config->getSystemValue('debug', false) ? 'yes' : 'no',
'freespace' => $this->getFreeSpace(),
'cpuload' => $processorUsage['loadavg'],
'cpunum' => $numCPU,
'mem_total' => $memoryUsage->getMemTotal() * 1024,
'mem_free' => $memoryUsage->getMemAvailable() * 1024,
'swap_total' => $memoryUsage->getSwapTotal() * 1024,
Expand Down
2 changes: 1 addition & 1 deletion templates/settings-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function FormatMegabytes(int $byte): string {
<canvas id="cpuloadcanvas" style="width:100%; height:200px" width="600" height="200"></canvas>
</div>
</div>
<p><em id="cpuFooterInfo"></em></p>
<p><span class="cpubox" id="cpubox">&nbsp;&nbsp;</span>&nbsp;&nbsp;<em id="cpuFooterInfo"></em></p>
</div>

<div class="col col-6 col-l-12">
Expand Down