summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules-available/statistics/clientscript.js31
-rw-r--r--modules-available/statistics/pages/machine.inc.php65
-rw-r--r--modules-available/statistics/templates/machine-usage.html31
-rw-r--r--style/default.css18
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) . '%">&nbsp;</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) . '%">&nbsp;</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) . '%">&nbsp;</div>';
} elseif ($first) {
- // Not seen in last two weeks
+ // Not seen in last weeks
$spans['graph'] .= '<div style="background:#444;left:0;width:100%">&nbsp;</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) . '%">&nbsp;</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) . '%">&nbsp;</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) . '%">&nbsp;</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">&nbsp;{{{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;
+}