diff options
author | Simon Rettberg | 2024-09-12 11:27:34 +0200 |
---|---|---|
committer | Simon Rettberg | 2024-09-12 11:27:34 +0200 |
commit | 8c960784b8c3524a23a3c0a5a33926a3aa887b70 (patch) | |
tree | 7202d67efd1047c051821eab969c220c1083801b | |
parent | [rebootcontrol] Only run the Taskmanager check if we got work to do (diff) | |
download | slx-admin-8c960784b8c3524a23a3c0a5a33926a3aa887b70.tar.gz slx-admin-8c960784b8c3524a23a3c0a5a33926a3aa887b70.tar.xz slx-admin-8c960784b8c3524a23a3c0a5a33926a3aa887b70.zip |
[statistics] Extend usage history to 10 days, add pie chart
-rw-r--r-- | modules-available/statistics/clientscript.js | 31 | ||||
-rw-r--r-- | modules-available/statistics/pages/machine.inc.php | 65 | ||||
-rw-r--r-- | modules-available/statistics/templates/machine-usage.html | 31 | ||||
-rw-r--r-- | style/default.css | 18 |
4 files changed, 110 insertions, 35 deletions
diff --git a/modules-available/statistics/clientscript.js b/modules-available/statistics/clientscript.js index 3c166f64..8ed2129c 100644 --- a/modules-available/statistics/clientscript.js +++ b/modules-available/statistics/clientscript.js @@ -73,4 +73,35 @@ function addFilter(field, op, argument) { function refresh() { $('#query-form').submit(); +} + +function makeUsagePie($parent) { + var data = $parent.data('chart'); + var chartData = { + datasets: [{ + data: data.map(function(x) { return x.value; }), + backgroundColor: data.map(function(x) { return x.color; }), + tooltip: data.map(function(x) { return x.tooltip; }), + }] + }; + var $canv = $('<canvas style="width:250px;height:250px" width="250" height="250">'); + $parent.append($canv); + (function() { + new Chart($canv[0].getContext('2d'), { + type: 'pie', data: chartData, options: { + animation: false, + plugins: { + tooltip: { + enabled: true, + callbacks: { + label: function(context) { + return context.dataset.tooltip[context.dataIndex]; + } + } + }, + legend: {display: false} + } + } + }); + })(); }
\ No newline at end of file diff --git a/modules-available/statistics/pages/machine.inc.php b/modules-available/statistics/pages/machine.inc.php index 1d46b523..34ed63da 100644 --- a/modules-available/statistics/pages/machine.inc.php +++ b/modules-available/statistics/pages/machine.inc.php @@ -310,29 +310,36 @@ class SubPage } // Sessions $NOW = time(); - $cutoff = $NOW - 86400 * 7; + $cutoff = $NOW - 86400 * 10; //if ($cutoff < $client['firstseen']) $cutoff = $client['firstseen']; $scale = 100 / ($NOW - $cutoff); - $res = Database::simpleQuery('SELECT dateline, typeid, data FROM statistic' - . " WHERE dateline > :cutoff AND typeid IN (:sessionLength, :offlineLength) AND machineuuid = :uuid ORDER BY dateline ASC", array( - 'cutoff' => $cutoff - 86400 * 14, + $res = Database::simpleQuery('SELECT dateline, typeid, data FROM statistic + WHERE dateline > :cutoff + AND typeid IN (:sessionLength, :offlineLength, :suspendLength) + AND machineuuid = :uuid ORDER BY dateline ASC', [ + 'cutoff' => $cutoff - 86400 * 30, 'uuid' => $uuid, 'sessionLength' => Statistics::SESSION_LENGTH, 'offlineLength' => Statistics::OFFLINE_LENGTH, - )); - $spans['rows'] = array(); - $spans['graph'] = ''; + 'suspendLength' => Statistics::SUSPEND_LENGTH, + ]); + $spans = [ + 'rows' => array(), + 'graph' => '', + ]; + $timeOffline = $timeStandby = $timeIdle = $timeUse = 0; $last = false; $first = true; foreach ($res as $row) { if (!$client['isclient'] && $row['typeid'] === Statistics::SESSION_LENGTH) continue; // Don't differentiate between session and idle for non-clients if ($first && $row['dateline'] > $cutoff && $client['lastboot'] > $cutoff) { - // Special case: offline before + // Special case: offline before query start (longer than 30 days) + $timeOffline += min($row['dateline'], $client['lastboot']) - $cutoff; $spans['graph'] .= '<div style="background:#444;left:0;width:' . round((min($row['dateline'], $client['lastboot']) - $cutoff) * $scale, 2) . '%"> </div>'; } $first = false; - if ($row['dateline'] + $row['data'] < $cutoff || $row['data'] > 864000) { + if ($row['dateline'] + $row['data'] < $cutoff || $row['dateline'] + $row['data'] > $NOW) { continue; } if ($last !== false && abs($last['dateline'] - $row['dateline']) < 30 @@ -354,24 +361,43 @@ class SubPage if ($row['typeid'] === Statistics::OFFLINE_LENGTH) { $row['glyph'] = 'off'; $color = '#444'; + $timeOffline += $row['data']; } elseif ($row['typeid'] === Statistics::SUSPEND_LENGTH) { $row['glyph'] = 'pause'; $color = '#686'; + $timeStandby += $row['data']; } else { $row['glyph'] = 'user'; $color = '#e77'; + $timeUse += $row['data']; } $spans['graph'] .= '<div style="background:' . $color . ';left:' . round(($row['dateline'] - $cutoff) * $scale, 2) . '%;width:' . round(($row['data']) * $scale, 2) . '%"> </div>'; + // Reconstructed entry for table: idle - not logged in DB directly + if ($last !== false) { + $lastEnd = $last['dateline'] + $last['data']; + $duration = $row['dateline'] - $lastEnd; + if ($client['isclient'] && $duration > 90) { + $spans['rows'][] = [ + 'glyph' => 'ok-circle', + 'from' => Util::prettyTime($lastEnd), + 'duration' => floor($duration / 86400) . 'd ' . gmdate('H:i', $duration), + ]; + } + if ($duration > 0) { + $timeIdle += $duration; + } + } + // Normal entry for table if ($client['isclient']) { $spans['rows'][] = $row; } $last = $row; } if ($first && $client['lastboot'] > $cutoff) { - // Special case: offline before + // Special case: offline before and no activity besides bootup $spans['graph'] .= '<div style="background:#444;left:0;width:' . round(($client['lastboot'] - $cutoff) * $scale, 2) . '%"> </div>'; } elseif ($first) { - // Not seen in last two weeks + // Not seen in last weeks $spans['graph'] .= '<div style="background:#444;left:0;width:100%"> </div>'; } if ($client['state'] === 'OCCUPIED') { @@ -381,6 +407,7 @@ class SubPage 'duration' => '-', 'glyph' => 'user', ]; + $timeUse += $NOW - $client['logintime']; } elseif ($client['state'] === 'OFFLINE') { $spans['graph'] .= '<div style="background:#444;left:' . round(($client['lastseen'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['lastseen'] + 900) * $scale, 2) . '%"> </div>'; $spans['rows'][] = [ @@ -388,6 +415,7 @@ class SubPage 'duration' => '-', 'glyph' => 'off', ]; + $timeOffline += $NOW - $client['lastseen']; } elseif ($client['state'] === 'STANDBY') { $spans['graph'] .= '<div style="background:#686;left:' . round(($client['lastseen'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['lastseen'] + 900) * $scale, 2) . '%"> </div>'; $spans['rows'][] = [ @@ -395,6 +423,10 @@ class SubPage 'duration' => '-', 'glyph' => 'pause', ]; + $timeStandby += $NOW - $client['lastseen']; + } elseif ($last !== false && $client['state'] === 'IDLE') { + $lastEnd = $last['dateline'] + $last['data']; + $timeIdle += $NOW - $lastEnd; } $t = explode('-', date('Y-n-j-G', $cutoff)); if ($t[3] >= 8 && $t[3] <= 22) { @@ -405,12 +437,13 @@ class SubPage for ($i = $start; $i < $NOW; $i += 86400) { $spans['graph'] .= '<div style="background:rgba(0,0,90,.2);left:' . round(($i - $cutoff) * $scale, 2) . '%;width:' . round((10 * 3600) * $scale, 2) . '%"> </div>'; } - if (count($spans['rows']) > 10) { - $spans['hasrows2'] = true; - $spans['rows2'] = array_slice($spans['rows'], (int)ceil(count($spans['rows']) / 2)); - $spans['rows'] = array_slice($spans['rows'], 0, (int)ceil(count($spans['rows']) / 2)); - } $spans['isclient'] = $client['isclient']; + $spans['chart'] = json_encode([ + ['value' => $timeOffline, 'color' => '#444', 'tooltip' => 'OFFLINE: ' . Util::formatDuration($timeOffline)], + ['value' => $timeStandby, 'color' => '#686', 'tooltip' => 'STANDBY: ' . Util::formatDuration($timeStandby)], + ['value' => $timeIdle, 'color' => '#afc', 'tooltip' => 'IDLE: ' . Util::formatDuration($timeIdle)], + ['value' => $timeUse, 'color' => '#e99', 'tooltip' => 'OCCUPIED: ' . Util::formatDuration($timeUse)], + ]); Render::addTemplate('machine-usage', $spans); // Any hdds? if (!empty($hdds['hdds'])) { diff --git a/modules-available/statistics/templates/machine-usage.html b/modules-available/statistics/templates/machine-usage.html index be435ee5..ba6ae5b1 100644 --- a/modules-available/statistics/templates/machine-usage.html +++ b/modules-available/statistics/templates/machine-usage.html @@ -7,13 +7,15 @@ <div class="panel-body"> {{#isclient}} <div class="row"> - <div class="col-sm-6"> + <div class="col-md-6 sticky-table" style="max-height:400px" id="usage-list"> <table class="table table-condensed"> + <thead> <tr> <th>{{lang_eventType}}</th> <th>{{lang_when}}</th> <th>{{lang_duration}}</th> </tr> + </thead> {{#rows}} <tr> <td><span class="glyphicon glyphicon-{{glyph}}"></span></td> @@ -23,24 +25,17 @@ {{/rows}} </table> </div> - <div class="col-sm-6"> - <table class="table table-condensed"> - {{#hasrows2}} - <tr> - <th>{{lang_eventType}}</th> - <th>{{lang_when}}</th> - <th>{{lang_duration}}</th> - </tr> - {{/hasrows2}} - {{#rows2}} - <tr> - <td><span class="glyphicon glyphicon-{{glyph}}"></span></td> - <td>{{from}}</td> - <td>{{duration}}</td> - </tr> - {{/rows2}} - </table> + <div class="col-md-6 hidden-sm"> + <div class="pull-right" style="max-width: 290px" id="usage-pie" data-chart="{{chart}}"></div> + <div class="clearfix"></div> </div> + <script> + document.addEventListener('DOMContentLoaded', function () { + var element = document.getElementById("usage-list"); + element.scrollTop = element.scrollHeight; + makeUsagePie($('#usage-pie')); + }); + </script> </div> {{/isclient}} <div class="timebar"> {{{graph}}}</div> diff --git a/style/default.css b/style/default.css index 19e1ba08..9e5de615 100644 --- a/style/default.css +++ b/style/default.css @@ -630,4 +630,20 @@ label.disabled { cursor: not-allowed !important; background-color: #eee !important; opacity: 1 !important; -}
\ No newline at end of file +} + +div.sticky-table { + overflow: scroll; + position: relative; +} + +div.sticky-table table { + position: relative; +} + +div.sticky-table table thead { + background: #f8f8f8; + position: sticky; + top: 0; + z-index: 10; +} |