From 259f3df3f0117628ce1455dd1b61a3f9e8f08920 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Thu, 31 Dec 2015 00:29:34 +0100
Subject: [statistics] Add visualization of usage
---
apis/clientlog.inc.php | 1 -
lang/de/templates/statistics/machine-usage.json | 4 +
lang/en/templates/statistics/machine-usage.json | 4 +
lang/pt/templates/statistics/machine-usage.json | 3 +
modules/statistics.inc.php | 103 +++++++++++++++++++-----
style/default.css | 17 +++-
templates/statistics/machine-main.html | 8 +-
templates/statistics/machine-usage.html | 51 ++++++++++++
8 files changed, 163 insertions(+), 28 deletions(-)
create mode 100644 lang/de/templates/statistics/machine-usage.json
create mode 100644 lang/en/templates/statistics/machine-usage.json
create mode 100644 lang/pt/templates/statistics/machine-usage.json
create mode 100644 templates/statistics/machine-usage.html
diff --git a/apis/clientlog.inc.php b/apis/clientlog.inc.php
index 61200875..c48fcdb0 100644
--- a/apis/clientlog.inc.php
+++ b/apis/clientlog.inc.php
@@ -134,7 +134,6 @@ if ($type{0} === '~') {
// Usage (occupied/free)
$sessionLength = 0;
$used = Request::post('used', 0, 'integer');
- error_log("uuid=$uuid old=$old used=$used");
if ($old === false) die("Unknown machine.\n");
// Figure out what's happening
if ($used === 0) {
diff --git a/lang/de/templates/statistics/machine-usage.json b/lang/de/templates/statistics/machine-usage.json
new file mode 100644
index 00000000..e2c9a979
--- /dev/null
+++ b/lang/de/templates/statistics/machine-usage.json
@@ -0,0 +1,4 @@
+{
+ "lang_timebarDesc": "Visuelle Darstellung der letzten Tage. Rote Abschnitte zeigen, wann der Rechner belegt war, gr\u00fcne, wann er nicht verwendet wurde, aber eingeschaltet war. Die leicht abgedunkelten Abschnitte markieren N\u00e4chte (22 bis 8 Uhr).",
+ "lang_usageDetails": "Nutzungsdetails"
+}
\ No newline at end of file
diff --git a/lang/en/templates/statistics/machine-usage.json b/lang/en/templates/statistics/machine-usage.json
new file mode 100644
index 00000000..398996f6
--- /dev/null
+++ b/lang/en/templates/statistics/machine-usage.json
@@ -0,0 +1,4 @@
+{
+ "lang_timebarDesc": "Visual representation of the last few days. Red parts mark periods where the client was occupied, green parts where the client was idle. Dimmed parts mark nights (10pm to 8am).",
+ "lang_usageDetails": "Detailed usage"
+}
\ No newline at end of file
diff --git a/lang/pt/templates/statistics/machine-usage.json b/lang/pt/templates/statistics/machine-usage.json
new file mode 100644
index 00000000..c44dc44f
--- /dev/null
+++ b/lang/pt/templates/statistics/machine-usage.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/modules/statistics.inc.php b/modules/statistics.inc.php
index dd04771f..3104496a 100644
--- a/modules/statistics.inc.php
+++ b/modules/statistics.inc.php
@@ -393,51 +393,110 @@ class Page_Statistics extends Page
private function showMachine($uuid)
{
- $row = Database::queryFirst("SELECT machineuuid, macaddr, clientip, firstseen, lastseen, logintime, lastboot,"
+ $client = Database::queryFirst("SELECT machineuuid, macaddr, clientip, firstseen, lastseen, logintime, lastboot,"
. " mbram, kvmstate, cpumodel, id44mb, data, hostname, notes FROM machine WHERE machineuuid = :uuid",
array('uuid' => $uuid));
// Mangle fields
$NOW = time();
- if ($NOW - $row['lastseen'] > 610) {
- $row['state_off'] = true;
- } elseif ($row['logintime'] == 0) {
- $row['state_idle'] = true;
+ if ($NOW - $client['lastseen'] > 610) {
+ $client['state_off'] = true;
+ } elseif ($client['logintime'] == 0) {
+ $client['state_idle'] = true;
} else {
- $row['state_occupied'] = true;
- $this->fillSessionInfo($row);
- }
- $row['firstseen'] = date('d.m.Y H:i', $row['firstseen']);
- $row['lastseen'] = date('d.m.Y H:i', $row['lastseen']);
- $row['lastboot'] = date('d.m.Y H:i', $row['lastboot']);
- $row['logintime'] = date('d.m.Y H:i', $row['logintime']);
- $row['gbram'] = round(round($row['mbram'] / 500) / 2, 1);
- $row['gbtmp'] = round($row['id44mb'] / 1024);
- $row['ramclass'] = $this->ramColorClass($row['mbram']);
- $row['kvmclass'] = $this->kvmColorClass($row['kvmstate']);
- $row['hddclass'] = $this->hddColorClass($row['gbtmp']);
+ $client['state_occupied'] = true;
+ $this->fillSessionInfo($client);
+ }
+ $client['firstseen_s'] = date('d.m.Y H:i', $client['firstseen']);
+ $client['lastseen_s'] = date('d.m.Y H:i', $client['lastseen']);
+ $client['lastboot_s'] = date('d.m.Y H:i', $client['lastboot']);
+ $client['logintime_s'] = date('d.m.Y H:i', $client['logintime']);
+ $client['gbram'] = round(round($client['mbram'] / 500) / 2, 1);
+ $client['gbtmp'] = round($client['id44mb'] / 1024);
+ $client['ramclass'] = $this->ramColorClass($client['mbram']);
+ $client['kvmclass'] = $this->kvmColorClass($client['kvmstate']);
+ $client['hddclass'] = $this->hddColorClass($client['gbtmp']);
// Parse the giant blob of data
$hdds = array();
- if (preg_match_all('/##### ([^#]+) #+$(.*?)^#####/ims', $row['data'] . '########', $out, PREG_SET_ORDER)) {
+ if (preg_match_all('/##### ([^#]+) #+$(.*?)^#####/ims', $client['data'] . '########', $out, PREG_SET_ORDER)) {
foreach ($out as $section) {
if ($section[1] === 'CPU') {
- $this->parseCpu($row, $section[2]);
+ $this->parseCpu($client, $section[2]);
}
if ($section[1] === 'dmidecode') {
- $this->parseDmiDecode($row, $section[2]);
+ $this->parseDmiDecode($client, $section[2]);
}
if ($section[1] === 'Partition tables') {
$this->parseHdd($hdds, $section[2]);
}
}
}
+ unset($client['data']);
// Throw output at user
- Render::addTemplate('statistics/machine-main', $row);
+ Render::addTemplate('statistics/machine-main', $client);
+ // Sessions
+ $NOW = time();
+ $cutoff = $NOW - 86400 * 7;
+ if ($cutoff < $row['firstseen']) $cutoff = $row['firstseen'];
+ $scale = 100 / ($NOW - $cutoff);
+ $res = Database::simpleQuery("SELECT dateline, typeid, data FROM statistic"
+ . " WHERE dateline > :cutoff AND typeid IN ('~session-length', '~offline-length') AND machineuuid = :uuid ORDER BY dateline ASC", array(
+ 'cutoff' => $cutoff - 86400,
+ 'uuid' => $uuid
+ ));
+ $spans['rows'] = array();
+ $last = false;
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['dateline'] + $row['data'] < $cutoff || $row['data'] > 864000) continue;
+ if ($last !== false && abs($last['dateline'] - $row['dateline']) < 30
+ && abs($last['data'] - $row['data']) < 30) continue;
+ if ($last !== false && $last['dateline'] + $last['data'] > $row['dateline']) {
+ $point = $last['dateline'] + $last['data'];
+ $row['data'] -= ($point - $row['dateline']);
+ $row['dateline'] = $point;
+ }
+ if ($row['dateline'] < $cutoff) {
+ $row['data'] -= ($cutoff - $row['dateline']);
+ $row['dateline'] = $cutoff;
+ }
+ $row['from'] = date('d.m. H:i', $row['dateline']);
+ $row['duration'] = floor($row['data'] / 86400) . 'd ' . gmdate('H:i', $row['data']);
+ if ($row['typeid'] === '~offline-length') {
+ $row['glyph'] = 'off';
+ $color = '#444';
+ } else {
+ $row['glyph'] = 'user';
+ $color = '#e77';
+ }
+ $spans['graph'] .= '
';
+ $spans['rows'][] = $row;
+ $last = $row;
+ }
+ if (isset($client['state_occupied'])) {
+ $spans['graph'] .= '
';
+ } elseif (isset($client['state_off'])) {
+ $spans['graph'] .= '
';
+ }
+ $t = explode('-', date('Y-n-j-G', $cutoff));
+ if ($t[3] >= 8 && $t[3] <= 22) {
+ $start = mktime(22, 0, 0, $t[1], $t[2], $t[0]);
+ } else {
+ $start = mktime(22, 0, 0, $t[1], $t[2] - 1, $t[0]);
+ }
+ for ($i = $start; $i < $NOW; $i += 86400) {
+ $spans['graph'] .= '
';
+ }
+ if (count($spans['rows']) > 10) {
+ $spans['hasrows2'] = true;
+ $spans['rows2'] = array_slice($spans['rows'], ceil(count($spans['rows']) / 2));
+ $spans['rows'] = array_slice($spans['rows'], 0, ceil(count($spans['rows']) / 2));
+ }
+ Render::addTemplate('statistics/machine-usage', $spans);
// Any hdds?
if (!empty($hdds['hdds'])) {
Render::addScriptBottom('chart.min');
Render::addTemplate('statistics/machine-hdds', $hdds);
}
- Render::addTemplate('statistics/machine-notes', $row);
+ Render::addTemplate('statistics/machine-notes', $client);
}
private function parseCpu(&$row, $data)
diff --git a/style/default.css b/style/default.css
index 9c0c367a..73e4effa 100644
--- a/style/default.css
+++ b/style/default.css
@@ -216,4 +216,19 @@ body {
input[readonly] {
background-color: white !important;
cursor: text !important;
-}
\ No newline at end of file
+}
+
+.timebar {
+ position: relative;
+ background: #afc;
+ border: 1px solid #0a2;
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+.timebar div {
+ position: absolute;
+ top: 0px;
+ overflow: hidden;
+}
+
diff --git a/templates/statistics/machine-main.html b/templates/statistics/machine-main.html
index f9ca1c5d..8071416a 100644
--- a/templates/statistics/machine-main.html
+++ b/templates/statistics/machine-main.html
@@ -31,15 +31,15 @@
{{/hostname}}
{{lang_firstSeen}} |
- {{firstseen}} |
+ {{firstseen_s}} |
{{lang_lastBoot}} |
- {{lastboot}} |
+ {{lastboot_s}} |
{{lang_lastSeen}} |
- {{lastseen}} |
+ {{lastseen_s}} |
{{lang_usageState}} |
@@ -57,7 +57,7 @@
{{^username}}
{{lang_machineOccupied}}
{{/username}}
- {{logintime}}
+ {{logintime_s}}
{{/state_occupied}}
{{#session}}
{{session}}
diff --git a/templates/statistics/machine-usage.html b/templates/statistics/machine-usage.html
new file mode 100644
index 00000000..ffaa747b
--- /dev/null
+++ b/templates/statistics/machine-usage.html
@@ -0,0 +1,51 @@
+
+
+
+
+ {{lang_usageDetails}}
+
+
+
+
+
+
+ Type |
+ When |
+ Length |
+
+ {{#rows}}
+
+ |
+ {{from}} |
+ {{duration}} |
+
+ {{/rows}}
+
+
+
+
+ {{#hasrows2}}
+
+ Type |
+ When |
+ Length |
+
+ {{/hasrows2}}
+ {{#rows2}}
+
+ |
+ {{from}} |
+ {{duration}} |
+
+ {{/rows2}}
+
+
+
+
{{{graph}}}
+
+ {{lang_timebarDesc}}
+
+
+
+
+
--
cgit v1.2.3-55-g7522