diff options
Diffstat (limited to 'modules-available/statistics/hooks')
4 files changed, 194 insertions, 22 deletions
diff --git a/modules-available/statistics/hooks/config-tgz.inc.php b/modules-available/statistics/hooks/config-tgz.inc.php index 8dffbff6..b732fd7a 100644 --- a/modules-available/statistics/hooks/config-tgz.inc.php +++ b/modules-available/statistics/hooks/config-tgz.inc.php @@ -4,12 +4,12 @@ $res = Database::simpleQuery('SELECT h.hwname FROM statistic_hw h' . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)" . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array( 'projector' => 'projector', - 'screen' => DeviceType::SCREEN, + 'screen' => HardwareInfo::SCREEN, )); if ($res !== false) { // CHeck this in case we're running on old DB during update $content = ''; - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + foreach ($res as $row) { $content .= $row['hwname'] . "=beamer\n"; } diff --git a/modules-available/statistics/hooks/cron.inc.php b/modules-available/statistics/hooks/cron.inc.php index 0de233a8..4ba5e2f6 100644 --- a/modules-available/statistics/hooks/cron.inc.php +++ b/modules-available/statistics/hooks/cron.inc.php @@ -9,12 +9,42 @@ function logstats() $join = 'LEFT JOIN runmode r USING (machineuuid)'; $where = 'AND (r.isclient IS NULL OR r.isclient <> 0)'; } - $known = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.lastseen > $cutoff $where"); - $on = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.state IN ('IDLE', 'OCCUPIED') $where"); - $used = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.state = 'OCCUPIED' $where"); + // Get total/online/in-use + $known = Database::queryKeyValueList("SELECT locationid, Count(*) AS val FROM machine m + $join WHERE m.lastseen > $cutoff $where + GROUP BY locationid"); + $on = Database::queryKeyValueList("SELECT locationid, Count(*) AS val FROM machine m + $join WHERE m.state IN ('IDLE', 'OCCUPIED') $where + GROUP BY locationid"); + $used = Database::queryKeyValueList("SELECT locationid, Count(*) AS val FROM machine m + $join WHERE m.state = 'OCCUPIED' $where + GROUP BY locationid"); + // Get calendar data if available + if (Module::isAvailable('locationinfo')) { + // Refresh all calendars around 07:00 + $calendars = LocationInfo::getAllCalendars(date('G') != 7 || date('i') >= 10); + } + // Mash together + $data = ['usage' => []]; + foreach ($known as $lid => $val) { + $entry = ['t' => $val]; + if (isset($on[$lid])) { + $entry['o'] = $on[$lid]; + } + if (isset($used[$lid])) { + $entry['u'] = $used[$lid]; + } + if (isset($calendars[$lid])) { + $title = LocationInfo::extractCurrentEvent($calendars[$lid]); + if (!empty($title)) { + $entry['event'] = $title; + } + } + $data['usage'][$lid] = $entry; + } Database::exec("INSERT INTO statistic (dateline, typeid, clientip, username, data) VALUES (:now, '~stats', '', '', :vals)", array( 'now' => $NOW, - 'vals' => $known['val'] . '#' . $on['val'] . '#' . $used['val'], + 'vals' => json_encode($data), )); } @@ -26,18 +56,12 @@ function state_cleanup() // Query for logging $res = Database::simpleQuery("SELECT machineuuid, clientip, state, logintime, lastseen, live_memfree, live_swapfree, live_tmpfree FROM machine WHERE lastseen < If(state = 'STANDBY', $standby, $on) AND state <> 'OFFLINE'"); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - Database::exec('INSERT INTO clientlog (dateline, logtypeid, clientip, machineuuid, description, extra) - VALUES (UNIX_TIMESTAMP(), :type, :client, :uuid, :description, :longdesc)', array( - 'type' => 'machine-mismatch-cron', - 'client' => $row['clientip'], - 'description' => 'Client timed out, last known state is ' . $row['state'] - . '. Free RAM: ' . Util::readableFileSize($row['live_memfree'], -1, 2) - . ', free Swap: ' . Util::readableFileSize($row['live_swapfree'], -1, 2) - . ', free ID44: ' . Util::readableFileSize($row['live_tmpfree'], -1, 2), - 'longdesc' => '', - 'uuid' => $row['machineuuid'], - )); + foreach ($res as $row) { + ClientLog::write($row, 'machine-mismatch-cron', + 'Client timed out, last known state is ' . $row['state'] + . '. Free RAM: ' . Util::readableFileSize($row['live_memfree'], -1, 2) + . ', free Swap: ' . Util::readableFileSize($row['live_swapfree'], -1, 2) + . ', free ID44: ' . Util::readableFileSize($row['live_tmpfree'], -1, 2)); if ($row['state'] === 'OCCUPIED') { $length = $row['lastseen'] - $row['logintime']; if ($length > 0 && $length < 86400 * 7) { @@ -59,7 +83,7 @@ state_cleanup(); logstats(); if (mt_rand(1, 10) === 1) { - Database::exec("DELETE FROM statistic WHERE (UNIX_TIMESTAMP() - 86400 * 190) > dateline"); + Database::exec("DELETE FROM statistic WHERE (UNIX_TIMESTAMP() - 86400 * 365 * 2) > dateline"); if (mt_rand(1, 100) === 1) { Database::exec("OPTIMIZE TABLE statistic"); } diff --git a/modules-available/statistics/hooks/locations-column.inc.php b/modules-available/statistics/hooks/locations-column.inc.php new file mode 100644 index 00000000..51f280be --- /dev/null +++ b/modules-available/statistics/hooks/locations-column.inc.php @@ -0,0 +1,150 @@ +<?php + +if (!User::hasPermission('.statistics.view.list')) { + return null; +} + +class ClientCountLocationColumn extends AbstractLocationColumn +{ + + private $lookup; + + public function __construct() + { + $this->lookup = StatisticsColumnGetData([]); + } + + public function getColumnHtml(int $locationId): string + { + if (!isset($this->lookup[$locationId])) + return ''; + if ($this->lookup[$locationId]['hasChild'] ?? false) { + $child = <<<EOF + (<a href="?do=Statistics&show=list&filters=location~{$locationId}">↓{$this->lookup[$locationId]['clientCountSum']}</a>) +EOF; + } else { + $child = ''; + } + + return <<<EOF + <div class="pull-right"> + <a href="?do=Statistics&show=list&filters=location={$locationId}"> {$this->lookup[$locationId]['clientCount']} </a> + <span class="text-right" style="display:inline-block;width:6ex">$child</span> + </div> +EOF; + } + + public function getEditUrl(int $locationId): string + { + return ''; + } + + public function header(): string + { + return Dictionary::translateFileModule('statistics', 'module', 'location-column-header-count'); + } + + public function priority(): int + { + return 800; + } + +} + +class ClientLoadLocationColumn extends AbstractLocationColumn +{ + + private $lookup; + + public function __construct() + { + $this->lookup = StatisticsColumnGetData([]); + } + + public function getColumnHtml(int $locationId): string + { + if (!isset($this->lookup[$locationId]) || $this->lookup[$locationId]['clientCount'] === 0) + return ''; + $c =& $this->lookup[$locationId]; + return <<<EOF + <div class="load-col text-right" style="background:linear-gradient(to right, #f97, #f97 {$c['clientLoad']}%, + #6fa {$c['clientLoad']}%, #6fa {$c['clientIdle']}%, #eee {$c['clientIdle']}%)"> + {$c['clientLoad']} % + </div> +EOF; + + } + + public function getEditUrl(int $locationId): string + { + return ''; + } + + public function header(): string + { + return Dictionary::translateFileModule('statistics', 'module', 'location-column-header-load'); + } + + public function priority(): int + { + return 900; + } + +} + +function StatisticsColumnGetData(array $allowedLocationIds): array +{ + static $data = []; + if (!empty($data)) + return $data; + $extra = ''; + if (in_array(0, $allowedLocationIds)) { + $extra = ' OR locationid IS NULL'; + } + $locs = Location::getLocationsAssoc(); + $res = Database::simpleQuery("SELECT m.locationid, Count(*) AS cnt, + Sum(If(m.state = 'OCCUPIED', 1, 0)) AS used, Sum(If(m.state = 'IDLE', 1, 0)) AS idle + FROM machine m WHERE (locationid IN (:allowedLocationIds) $extra) GROUP BY locationid", compact('allowedLocationIds')); + foreach ($res as $row) { + $locId = (int)$row['locationid']; + $data[$locId] = [ + 'clientCount' => $row['cnt'], + 'clientLoad' => round(100 * $row['used'] / $row['cnt']), + 'clientIdle' => round(100 * ($row['used'] + $row['idle']) / $row['cnt']), + ]; + } + foreach ($allowedLocationIds as $locId) { + if (isset($data[$locId])) + continue; + $data[$locId] = [ + 'clientCount' => 0, + 'clientLoad' => 0, + 'clientIdle' => 0, + ]; + } + foreach ($data as $locId => &$loc) { + if (!in_array($locId, $allowedLocationIds)) + continue; + if (!isset($loc['clientCountSum'])) { + $loc['clientCountSum'] = 0; + } + $loc['clientCountSum'] += $loc['clientCount']; + if ($locId !== 0) { + foreach ($locs[$locId]['parents'] as $pid) { + if (!in_array($pid, $allowedLocationIds)) + continue; + $data[$pid]['hasChild'] = true; + if (!isset($data[$pid]['clientCountSum'])) { + $data[$pid]['clientCountSum'] = 0; + } + $data[$pid]['clientCountSum'] += $loc['clientCount']; + } + } + } + unset($loc); + return $data; +} + +StatisticsColumnGetData($allowedLocationIds); + +return [new ClientCountLocationColumn(), new ClientLoadLocationColumn()];
\ No newline at end of file diff --git a/modules-available/statistics/hooks/translation.inc.php b/modules-available/statistics/hooks/translation.inc.php index 4d09553a..f7a50b0d 100644 --- a/modules-available/statistics/hooks/translation.inc.php +++ b/modules-available/statistics/hooks/translation.inc.php @@ -16,10 +16,8 @@ $HANDLER['subsections'] = array( /** * Configuration categories. - * @param \Module $module - * @return array */ -$HANDLER['grep_filters'] = function($module) { +$HANDLER['grep_filters'] = function (Module $module): array { if (!$module->activate(1, false)) return array(); $want = StatisticsFilter::$columns; |