serverstats-0.8.2/0000755000175000017500000000000010725006401011665 5ustar memeserverstats-0.8.2/includes/0000755000175000017500000000000010725006400013472 5ustar memeserverstats-0.8.2/includes/logger_file.class.php0000644000175000017500000000361610725006400017573 0ustar memefile = $file; } public function __destruct() { if (isset($this->fh)) { fclose($this->fh); } } private function getFileHandler() { if (!isset($this->fh)) { if (!$this->fh = fopen($this->file, 'a+')) { throw new Exception('Could not open file (' . $this->file . ') for errorlogging'); } } return $this->fh; } private function writeToFile($loglevel, $string) { $date = date('r'); fwrite($this->getFileHandler(), $date . ' (' . logger::levelToString($loglevel) . '): ' . $string . "\n"); } public function logString($loglevel, $string) { if (!logger::needsLogging($loglevel)) return; $this->writeToFile($loglevel, $string); } public function logException($loglevel, Exception $exception) { if (!logger::needsLogging($loglevel)) return; $this->writeToFile($loglevel, $exception->__toString()); } } ?> serverstats-0.8.2/includes/functions.php0000644000175000017500000001504010725006400016213 0ustar meme =': return ($value1 >= $value2); case '>': return ($value1 > $value2); case '<=': return ($value1 <= $value2); case '<': return ($value1 < $value2); case '=': case '==': return ($value1 == $value2); case '!=': return ($value1 != $value2); default: throw new Exception('Invalid operator'); } } function extractFilter($filterString = '') { $filter = array(); $filterString = trim($filterString); if (strtolower($filterString) == 'none') { return array('none'); } $filterParts = preg_split('/\s*,\s*/', $filterString); foreach ($filterParts as $filterPart) { if (preg_match('/^([a-zA-Z0-9]+):(.+)$/', $filterPart, $matches)) { $filter[$matches[1]] = $matches[2]; } } return $filter; } function extractFilterFromTree($tree) { $last = array_pop($tree); return extractFilter($last['filter']); } function extractTree($treeString = '') { global $config; $tree = array(); $treeString = trim($treeString); if ($treeString === "") $treeParts = array(); else $treeParts = preg_split('/\s*,\s*/', $treeString); $path = ''; $tree[] = array( 'title' => $config['graph']['tree']['title'], 'filter' => $config['graph']['tree']['filter'], 'path' => $path ); $subTree = $config['graph']['tree']['sub']; foreach ($treeParts as $part) { if (isset($subTree[$part])) { $path .= $path === "" ? $part : (',' . $part); $tree[] = array( 'title' => $subTree[$part]['title'], 'filter' => $subTree[$part]['filter'], 'path' => $path ); if (isset($subTree[$part]['sub'])) $subTree = $subTree[$part]['sub']; else break; } else break; } return $tree; } function isFiltered($graph, $filter) { foreach ($filter as $category => $condition) { if ($condition == 'none') { return true; } if ($condition{0} == "!") { $condition = substr($condition, 1); $negate = true; } else { $negate = false; } if (!isset($graph['categories']) || !isset($graph['categories'][$category])) return !$negate; if (is_array($graph['categories'][$category]) || $graph['categories'][$category] instanceof Traversable) { $filtered = true; foreach ($graph['categories'][$category] as $value) { if ((!$negate && $condition == $value) || ($negate && $condition != $value)) { $filtered = false; break; } } if ($filtered) return true; } else { if ($negate) { if ($condition == $graph['categories'][$category]) return true; } else { if ($condition != $graph['categories'][$category]) return true; } } } } function printBreadcrumps($tree) { $needSep = false; foreach ($tree as $crump) { ?> $condition) { $filterParts[] = $category . ':' . $condition; } return implode(',', $filterParts); } ?> serverstats-0.8.2/includes/simpleconfig.class.php0000644000175000017500000007266210725006400020003 0ustar meme $modconf) { if (!$modconf['used']) { continue; } switch ($module) { case 'apache': foreach ($modconf['hosts'] as $host) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'requests': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $host), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $host), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'requestsps', 'cf' => 'AVERAGE', 'legend' => 'Requests/s', 'color' => '7FD180' ) ) ); break; } } } break; case 'cpu': foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'usage': $config['list'][] = array( 'title' => $graphconf['title'], 'upperLimit' => 100, 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_system', 'cf' => 'AVERAGE', 'legend' => 'System', 'color' => 'FF0000' ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_user', 'cf' => 'AVERAGE', 'legend' => 'User', 'color' => '00FF00', 'stacked' => true ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_nice', 'cf' => 'AVERAGE', 'legend' => 'Nice', 'color' => '0000FF', 'stacked' => true ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_idle', 'cf' => 'AVERAGE', 'legend' => 'Idle', 'color' => 'FFFF00', 'stacked' => true ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_iowait', 'cf' => 'AVERAGE', 'legend' => 'IOwait', 'color' => 'FFAA00', 'stacked' => true ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_irq', 'cf' => 'AVERAGE', 'legend' => 'IRQ', 'color' => 'FF6600', 'stacked' => true ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'cpu_softirq', 'cf' => 'AVERAGE', 'legend' => 'SoftIRQ', 'color' => 'AAFF00', 'stacked' => true ) ) ); break; } } break; case 'disk': foreach ($modconf['disks'] as $disk) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'iorate': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $disk), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'verticalLabel' => 'byte/s', 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($disk), 'ds' => 'readps', 'cf' => 'AVERAGE', 'legend' => 'read', 'color' => 'FF0000' ), array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($disk), 'ds' => 'writeps', 'cf' => 'AVERAGE', 'legend' => 'write', 'color' => 'EEEE00' ) ) ); break; } } } break; case 'load': foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'load': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'COMMENT', 'text' => 'average number of tasks in the queue\:\n' ), array( 'type' => 'LINE', 'source' => $module, 'ds' => '1min', 'cf' => 'AVERAGE', 'legend' => '1 minute', 'width' => 1, 'color' => 'FFDD00' ), array( 'type' => 'GPRINT', 'name' => 'load_1min', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_1min', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_1min', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_1min', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf\n' ), array( 'type' => 'LINE', 'source' => $module, 'ds' => '5min', 'cf' => 'AVERAGE', 'legend' => '5 minutes', 'width' => 1, 'color' => 'FF8800' ), array( 'type' => 'GPRINT', 'name' => 'load_5min', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_5min', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_5min', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_5min', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf\n' ), array( 'type' => 'LINE', 'source' => $module, 'ds' => '15min', 'cf' => 'AVERAGE', 'legend' => '15 minutes', 'width' => 1, 'color' => 'FF0000' ), array( 'type' => 'GPRINT', 'name' => 'load_15min', 'cf' => 'LAST', 'format' => 'cur\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_15min', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_15min', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf' ), array( 'type' => 'GPRINT', 'name' => 'load_15min', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf\n' ) ) ); break; case 'processes': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'AREA', 'source' => $module, 'ds' => 'tasks', 'cf' => 'AVERAGE', 'legend' => 'number of processes', 'color' => 'FFDD00' ), array( 'type' => 'AREA', 'source' => $module, 'ds' => 'running', 'cf' => 'AVERAGE', 'legend' => 'running processes', 'color' => 'FF0000' ) ) ); break; } } break; case 'memory': foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'memory': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'DEF', 'source' => $module, 'ds' => 'MemTotal', 'cf' => 'AVERAGE', 'name' => 'total' ), array( 'type' => 'CDEF', 'expression' => 'total,1024,/,1024,/', 'name' => 'total_mb' ), array( 'type' => 'DEF', 'source' => $module, 'ds' => 'MemFree', 'cf' => 'AVERAGE', 'name' => 'free' ), array( 'type' => 'CDEF', 'expression' => 'free,1024,/,1024,/', 'name' => 'free_mb' ), array( 'type' => 'DEF', 'source' => $module, 'ds' => 'Cached', 'cf' => 'AVERAGE', 'name' => 'cached' ), array( 'type' => 'CDEF', 'expression' => 'cached,1024,/,1024,/', 'name' => 'cached_mb' ), array( 'type' => 'AREA', 'name' => 'total', 'legend' => 'total', 'color' => 'FFFFCC' ), array( 'type' => 'GPRINT', 'name' => 'total_mb', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf MB\n' ), array( 'type' => 'AREA', 'name' => 'free', 'legend' => 'free', 'color' => 'FF0000' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf MB\n' ), array( 'type' => 'STACK', 'name' => 'cached', 'legend' => 'cached', 'color' => 'EEDD22' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'LAST', 'format' => 'cur\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf MB' ), array( 'type' => 'LINE', 'width' => 1, 'name' => 'total', 'color' => '000000' ) ) ); break; case 'swap': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'DEF', 'source' => $module, 'ds' => 'SwapTotal', 'cf' => 'AVERAGE', 'name' => 'total' ), array( 'type' => 'CDEF', 'expression' => 'total,1024,/,1024,/', 'name' => 'total_mb' ), array( 'type' => 'DEF', 'source' => $module, 'ds' => 'SwapFree', 'cf' => 'AVERAGE', 'name' => 'free' ), array( 'type' => 'CDEF', 'expression' => 'free,1024,/,1024,/', 'name' => 'free_mb' ), array( 'type' => 'DEF', 'source' => $module, 'ds' => 'SwapCached', 'cf' => 'AVERAGE', 'name' => 'cached' ), array( 'type' => 'CDEF', 'expression' => 'cached,1024,/,1024,/', 'name' => 'cached_mb' ), array( 'type' => 'AREA', 'name' => 'total', 'legend' => 'total', 'color' => 'FFFFCC' ), array( 'type' => 'GPRINT', 'name' => 'total_mb', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf MB\n' ), array( 'type' => 'AREA', 'name' => 'free', 'legend' => 'free', 'color' => 'FF0000' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'LAST', 'format' => ' cur\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'free_mb', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf MB\n' ), array( 'type' => 'STACK', 'name' => 'cached', 'legend' => 'cached', 'color' => 'EEDD22' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'LAST', 'format' => 'cur\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'MINIMUM', 'format' => 'min\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'MAXIMUM', 'format' => 'max\: %01.2lf MB' ), array( 'type' => 'GPRINT', 'name' => 'cached_mb', 'cf' => 'AVERAGE', 'format' => 'avg\: %01.2lf MB' ), array( 'type' => 'LINE', 'width' => 1, 'name' => 'total', 'color' => '000000' ) ) ); break; } } break; case 'mysql': foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'questions': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $modconf['host']), 'content' => array( array( 'type' => 'LINE', 'source' => $module, 'ds' => 'questionsps', 'cf' => 'AVERAGE', 'legend' => 'questions/s', 'width' => 1, 'color' => '00A302' ) ) ); break; case 'processes': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $modconf['host']), 'content' => array( array( 'type' => 'AREA', 'source' => $module, 'ds' => 'processcount', 'cf' => 'AVERAGE', 'legend' => 'number of queries', 'color' => '7FD180' ) ) ); break; } } break; case 'ping': foreach ($modconf['hosts'] as $host) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'single': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $host), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $host), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'time', 'cf' => 'AVERAGE', 'legend' => $host, 'color' => '7FD180' ) ) ); break; } } } foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'combined': $content = array(); srand(0); foreach ($modconf['hosts'] as $host) { $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'time', 'cf' => 'AVERAGE', 'legend' => $host . '\n', 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); } $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $modconf['hosts']), 'content' => $content ); break; } } break; case 'ping_http': foreach ($modconf['hosts'] as $host) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'single': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $host), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $host), 'content' => array( array( 'type' => 'AREA', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'open', 'cf' => 'AVERAGE', 'legend' => 'open connection\n', 'color' => 'DEE100' ), array( 'type' => 'AREA', 'stacked' => true, 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'send', 'cf' => 'AVERAGE', 'legend' => 'send request\n', 'color' => '665B00' ), array( 'type' => 'AREA', 'stacked' => true, 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'receive', 'cf' => 'AVERAGE', 'legend' => 'receive response\n', 'color' => '534BEF' ), array( 'type' => 'AREA', 'stacked' => true, 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'close', 'cf' => 'AVERAGE', 'legend' => 'close connection\n', 'color' => '060085' ), array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'time', 'cf' => 'AVERAGE', 'legend' => 'total', 'color' => 'CD0000' ) ) ); break; } } } foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'combined': $content = array(); srand(0); foreach ($modconf['hosts'] as $host) { $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($host), 'ds' => 'time', 'cf' => 'AVERAGE', 'legend' => $host . '\n', 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); } $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => $modconf['hosts']), 'content' => $content ); break; } } break; case 'traffic': foreach ($modconf['chains'] as $chain) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'single_bps': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $chain), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($chain), 'ds' => 'bps', 'cf' => 'AVERAGE', 'legend' => $chain, 'color' => '7FD180' ) ) ); break; case 'single_count': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $chain), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($chain), 'ds' => 'traffic', 'cf' => 'AVERAGE', 'legend' => $chain, 'color' => '7FD180' ) ) ); break; } } } foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'combined_bps': $content = array(); srand(0); foreach ($modconf['chains'] as $chain) { $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($chain), 'ds' => 'bps', 'cf' => 'AVERAGE', 'legend' => $chain, 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); } $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => $content ); break; case 'combined_count': $content = array(); srand(0); foreach ($modconf['chains'] as $chain) { $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($chain), 'ds' => 'traffic', 'cf' => 'AVERAGE', 'legend' => $chain, 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); } $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => $content ); break; } } break; case 'traffic_proc': foreach ($modconf['interfaces'] as $interface) { foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'single_bps': $config['list'][] = array( 'title' => sprintf($graphconf['title'], $interface), 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($interface), 'ds' => $interface . '_rbytes', 'cf' => 'AVERAGE', 'legend' => 'Download Bytes/s', 'color' => '0002A3' ), array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($interface), 'ds' => $interface . '_tbytes', 'cf' => 'AVERAGE', 'legend' => 'Upload Bytes/s', 'color' => '00A302' ) ) ); break; } } } foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'combined_bps': $content = array(); srand(0); foreach ($modconf['interfaces'] as $interface) { $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($interface), 'ds' => $interface . '_rbytes', 'cf' => 'AVERAGE', 'legend' => 'Download Bytes/s (' . $interface . ')', 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); $content[] = array( 'type' => 'LINE', 'source' => $module . '_' . rrd::escapeDsName($interface), 'ds' => $interface . '_tbytes', 'cf' => 'AVERAGE', 'legend' => 'Upload Bytes/s (' . $interface . ')\n', 'color' => sprintf('%02X%02X%02X', rand(0, 255), rand(0, 255), rand(0, 255)) ); } $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => $content ); break; } } break; case 'users': foreach ($modconf['graphs'] as $graph => $graphconf) { if (!$graphconf['used']) { continue; } switch ($graph) { case 'logged_in': $config['list'][] = array( 'title' => $graphconf['title'], 'lowerLimit' => 0, 'altAutoscaleMax' => true, 'categories' => array('host' => 'localhost'), 'content' => array( array( 'type' => 'AREA', 'source' => $module, 'ds' => 'users', 'cf' => 'AVERAGE', 'legend' => 'Users logged in', 'color' => '4444DD' ) ) ); break; } } break; } } } public static function sources(&$config, $simpleconfig) { if (!$simpleconfig['used']) { return; } foreach ($simpleconfig['modules'] as $module => $modconf) { if (!$modconf['used']) { continue; } switch ($module) { case 'apache': foreach ($modconf['hosts'] as $host) { $config[$module . '_' . rrd::escapeDsName($host)]['module'] = new apache('http://' . $host . '/server-status?auto'); } break; case 'cpu': $config[$module]['module'] = new cpu(); break; case 'disk': foreach ($modconf['disks'] as $disk) { $config[$module . '_' . rrd::escapeDsName($disk)]['module'] = new disk($disk); } break; case 'load': $config[$module]['module'] = new load(); break; case 'memory': $config[$module]['module'] = new memory(); break; case 'mysql': $config[$module]['module'] = new mysql($modconf['user'], $modconf['password'], $modconf['host']); break; case 'ping': foreach ($modconf['hosts'] as $host) { $config[$module . '_' . rrd::escapeDsName($host)]['module'] = new ping($host); } break; case 'ping_http': foreach ($modconf['hosts'] as $host) { $config[$module . '_' . rrd::escapeDsName($host)]['module'] = new ping_http($host); } break; case 'traffic': foreach ($modconf['chains'] as $chain) { $config[$module . '_' . rrd::escapeDsName($chain)]['module'] = new traffic($chain); } break; case 'traffic_proc': foreach ($modconf['interfaces'] as $interface) { $config[$module . '_' . rrd::escapeDsName($interface)]['module'] = new traffic_proc($interface); } break; case 'users': $config[$module]['module'] = new users(); break; } } } } ?> serverstats-0.8.2/includes/rrd.class.php0000644000175000017500000003132710725006400016104 0ustar memerrdtoolbin = $rrdtoolbin; $this->rrdfile = $rrdfile; if (file_exists($this->rrdfile)) { $this->restoreOptions(); } } private function restoreOptions() { $output = array(); $return = 0; $params = ' info ' . escapeshellarg($this->rrdfile); $command = escapeshellcmd($this->rrdtoolbin) . $params; exec($command . ' 2>&1', $output, $return); if ($return != 0) { throw new Exception('rrdtool ("' . $command . '") finished with exitcode ' . $return . "\n" . implode("\n", $output)); } $matches = array(); foreach ($output as $line) { if (preg_match('/^(.*?)\s*=\s*(.*?)$/', $line, $matches)) { $key = $matches[1]; $value = $matches[2]; if ($key == 'step') { $this->step = $value; } elseif (preg_match('/^ds\[([a-zA-Z0-9_]+)\]\.(.*?)$/', $key, $matches)) { $dsname = $matches[1]; $dsattribute = $matches[2]; if (!isset($this->datasources[$dsname])) { $this->datasources[$dsname] = array(); } switch ($dsattribute) { case 'type': $value = trim($value, '"'); $this->datasources[$dsname]['type'] = $value; switch ($value) { case 'GAUGE': case 'COUNTER': case 'DERIVE': case 'ABSOLUTE': $this->values[$dsname] = 'U'; break; case 'COMPUTE': break; default: throw new Exception('Unknown Datasource-type: ' . $value); break; } break; case 'cdef': $value = trim($value, '"'); $this->datasources[$dsname]['expression'] = $value; break; case 'min': if ($value == 'NaN') { $this->datasources[$dsname]['min'] = 'U'; } else { $this->datasources[$dsname]['min'] = floatval($value); } break; case 'max': if ($value == 'NaN') { $this->datasources[$dsname]['max'] = 'U'; } else { $this->datasources[$dsname]['max'] = floatval($value); } break; case 'minimal_heartbeat': $this->datasources[$dsname]['heartbeat'] = intval($value); break; } } /* Not all values can be imported this way, but the RRA-definition is not needed for rrdupdate, so we may skip this */ /* elseif (preg_match('/^rra\[([0-9]+)\]\.(.*?)$/', $key, $matches)) { $rranum = $matches[1]; $rraattribute = $matches[2]; if (!isset($this->archives[$rranum])) { $this->archives[$rranum] = array(); } switch ($rraattribute) { case 'cf': $value = trim($value, '"'); $this->archives[$rranum]['cf'] = $value; break; case 'rows': $this->archives[$rranum]['rows'] = intval($value); break; case 'xff': $this->archives[$rranum]['xff'] = floatval($value); break; case 'pdp_per_row': $this->archives[$rranum]['steps'] = intval($value); break; case 'alpha': $this->archives[$rranum]['alpha'] = floatval($value); break; case 'beta': $this->archives[$rranum]['beta'] = floatval($value); break; case 'gamma': $this->archives[$rranum]['gamma'] = floatval($value); break; case 'failure_threshold': $this->archives[$rranum]['threshold'] = $value; break; case 'window_length': $this->archives[$rranum][''] = $value; break; } } */ } } $this->created = true; } public function create() { $params = ' create ' . escapeshellarg($this->rrdfile); $params .= ' -s ' . escapeshellarg($this->step); foreach ($this->datasources as $name => $ds) { // Backwards compability if (isset($ds['name'])) { $name = $ds['name']; } switch($ds['type']) { case 'GAUGE': case 'COUNTER': case 'DERIVE': case 'ABSOLUTE': // Params: heartbeat, min, max $dsstring = 'DS:' . $name . ':' . $ds['type'] . ':' . $ds['heartbeat'] . ':' . $ds['min'] . ':' . $ds['max']; break; case 'COMPUTE': $dsstring = 'DS:' . $name . ':' . $ds['type'] . ':' . $ds['expression']; break; default: throw new Exception('Unknown Datasource-type: ' . $type); break; } $params .= ' ' . escapeshellarg($dsstring); } foreach ($this->archives as $rra) { switch ($rra['cf']) { case 'AVERAGE': case 'MIN': case 'MAX': case 'LAST': // Params: xff, steps, rows $rrastring = 'RRA:' . $rra['cf'] . ':' . $rra['xff'] . ':' . $rra['steps'] . ':' . $rra['rows']; break; case 'HWPREDICT': // Params: rows, alpha, beta, seasonal_period, rra-num $rrastring = 'RRA:' . $rra['cf'] . ':' . $rra['rows'] . ':' . $rra['alpha'] . ':' . $rra['beta'] . ':' . $rra['seasonal_period'] . ':' . $rra['rra-num']; break; case 'SEASONAL': case 'DEVSEASONAL': // Params: seasonal_period, gamma, rra-num $rrastring = 'RRA:' . $rra['cf'] . ':' . $rra['seasonal_period'] . ':' . $rra['gamma'] . ':' . $rra['rra-num']; break; case 'DEVPREDICT': // Params: rows, rra-num $rrastring = 'RRA:' . $rra['cf'] . ':' . $rra['rows'] . ':' . $rra['rra-num']; break; case 'FAILURES': // Params: rows, threshold, window_length, rra-num $rrastring = 'RRA:' . $rra['cf'] . ':' . $rra['rows'] . ':' . $rra['threshold'] . ':' . $rra['window_length'] . ':' . $rra['rra-num']; break; default: throw new Exception('Unknown CF: ' . $cf); break; } $params .= ' ' . escapeshellarg($rrastring); } $output = array(); $return = 0; $command = escapeshellcmd($this->rrdtoolbin) . $params; exec($command . ' 2>&1', $output, $return); if ($return != 0) { throw new Exception('rrdtool ("' . $command . '") finished with exitcode ' . $return . "\n" . implode("\n", $output)); } $this->created = true; } public function addDatasource($name, $type, $p1 = null, $p2 = null, $p3 = null) { if ($this->created) { throw new Exception('RRD is created, you cannot add any datasources'); } if (isset($this->datasources[$name])) { throw new Exception('Datasourcename "' . $name .'" already taken'); } switch($type) { case 'GAUGE': case 'COUNTER': case 'DERIVE': case 'ABSOLUTE': // Params: heartbeat, min, max if (!isset($p1)) { $p1 = $this->getDefaultHeartbeat(); } if (!isset($p2)) { $p2 = 'U'; } if (!isset($p3)) { $p3 = 'U'; } $this->datasources[$name] = array( 'min' => $p2, 'max' => $p3, 'type' => $type, 'heartbeat' => $p1 ); $this->values[$name] = 'U'; break; case 'COMPUTE': // Params: expression if (!isset($p1)) { throw new Exception('Wrong Paramcount for DST ' . $type); } $this->datasources[$name] = array( 'type' => $type, 'expression' => $p1 ); break; default: throw new Exception('Unknown Datasource-type: ' . $type); break; } } public function addArchive($cf, $p1 = null, $p2 = null, $p3 = null, $p4 = null, $p5 = null) { if ($this->created) { throw new Exception('RRD is created, you cannot add any archives'); } switch ($cf) { case 'AVERAGE': case 'MIN': case 'MAX': case 'LAST': // Params: xff, steps, rows if (!(isset($p1) && isset($p2) && isset($p3))) { throw new Exception('Wrong Paramcount for CF ' . $cf); } $this->archives[] = array( 'cf' => $cf, 'xff' => $p1, 'steps' => $p2, 'rows' => $p3 ); break; case 'HWPREDICT': // Params: rows, alpha, beta, seasonal_period, rra-num if (!(isset($p1) && isset($p2) && isset($p3) && isset($p4) && isset($p5))) { throw new Exception('Wrong Paramcount for CF ' . $cf); } $this->archives[] = array( 'cf' => $cf, 'rows' => $p1, 'alpha' => $p2, 'beta' => $p3, 'seasonal_period' => $p4, 'rra-num' => $p5 ); break; case 'SEASONAL': case 'DEVSEASONAL': // Params: seasonal_period, gamma, rra-num if (!(isset($p1) && isset($p2) && isset($p3))) { throw new Exception('Wrong Paramcount for CF ' . $cf); } $this->archives[] = array( 'cf' => $cf, 'seasonal_period' => $p1, 'gamma' => $p2, 'rra-num' => $p3 ); break; case 'DEVPREDICT': // Params: rows, rra-num if (!(isset($p1) && isset($p2))) { throw new Exception('Wrong Paramcount for CF ' . $cf); } $this->archives[] = array( 'cf' => $cf, 'rows' => $p1, 'rra-num' => $p2 ); break; case 'FAILURES': // Params: rows, threshold, window_length, rra-num if (!(isset($p1) && isset($p2) && isset($p3) && isset($p4))) { throw new Exception('Wrong Paramcount for CF ' . $cf); } $this->archives[] = array( 'cf' => $cf, 'rows' => $p1, 'threshold' => $p2, 'window_length' => $p3, 'rra-num' => $p4 ); break; default: throw new Exception('Unknown CF: ' . $cf); break; } } public function setValue($dsname, $value) { if (!isset($this->values[$dsname])) { throw new Exception('Datasource "' . $dsname . '" unknown or computed'); } if ($this->values[$dsname] != 'U') { throw new Exception('Datasource already set'); } if ($value == null) { // No need to update return; } $this->values[$dsname] = $value; } public function update() { $params = ' update ' . escapeshellarg($this->rrdfile); $updatestr = 'N'; $templatestr = ''; $precision = ini_get('precision'); if (empty($precision)) { $precision = 12; } else { $precision = intval($precision); } foreach ($this->values as $dsname => $dsvalue) { $templatestr .= $dsname . ':'; if (is_double($dsvalue)) { $stringrep = strval($dsvalue); $parts = array(); if (preg_match('/^([+\-]?[0-9]+)(\.([0-9]+))?[eE]([+\-]?[0-9]+)$/', $stringrep, $parts)) { $exponent = intval($parts[4]); $decimals = $precision - $exponent; if ($decimals < 0) { $decimals = 0; } $dsvalue = number_format($dsvalue, $decimals, '.', ''); } } $updatestr .= ':' . $dsvalue; } $templatestr = substr($templatestr, 0, -1); $params .= ' -t ' . escapeshellarg($templatestr); $params .= ' ' . escapeshellarg($updatestr); $output = array(); $return = 0; $command = escapeshellcmd($this->rrdtoolbin) . $params; exec($command . ' 2>&1', $output, $return); if ($return != 0) { throw new Exception('rrdtool ("' . $command . '") finished with exitcode ' . $return . "\n" . implode("\n", $output)); } } public function checkVersion($compare, $neededversion) { $output = array(); $command = escapeshellcmd($this->rrdtoolbin); exec($command . ' 2>&1', $output); if (isset($output[0]) && preg_match('/^rrdtool\s+(\d+\.\d+\.\d+)/i', $output[0], $parts)) { $rrdversion = $parts[1]; return version_compare($rrdversion, $neededversion, $compare); } else { throw new Exception('rrdtool version check failed!'); } } public function hasDatasource($name) { return isset($this->datasources[$name]); } public function getDatasources() { return $this->datasources; } public function getArchives() { return $this->archives; } public function getRRDFile() { return $this->rrdfile; } public function getRRDToolBin() { return $this->rrdtoolbin; } public function setStep($step) { $this->step = $step; } public function getStep() { return $this->step; } public function getDefaultHeartbeat() { return $this->step * 4; } public static function escapeDsName($name) { return preg_replace('/[^a-zA-Z0-9_]/', '_', $name); } } ?> serverstats-0.8.2/includes/source_cached.class.php0000644000175000017500000000227310725006400020102 0ustar meme serverstats-0.8.2/includes/source_rrd.class.php0000644000175000017500000000216410725006400017461 0ustar meme serverstats-0.8.2/includes/logger_syslog.class.php0000644000175000017500000000417410725006400020174 0ustar meme__toString()); } } ?> serverstats-0.8.2/includes/lang.class.php0000644000175000017500000000335010725006400016231 0ustar meme serverstats-0.8.2/includes/config.class.php0000644000175000017500000000750410725006400016562 0ustar memedir = $dir; if (isset($rootConfig)) { if ($rootConfig instanceof config) { $this->rootConfig = $rootConfig; } else { throw new Exception('Config: Param error'); } } else { $this->rootConfig = $this; } } private function isOffsetValid($offset) { return preg_match('/^[a-zA-Z0-9_]+$/', $offset); } private function checkOffset($offset) { if (!$this->isOffsetValid($offset)) { throw new Exception('Offset "' . $offset . '" is not allowed'); } } public function offsetExists($offset) { if (isset($this->vars[$offset])) { return true; } else { $this->checkOffset($offset); if (is_readable($this->dir . $offset . '.php') || is_dir($this->dir . $offset)) { return true; } else { return false; } } } protected static function loadConfig(&$config, $file, $rootConfig) { if (require_once($file)) { if (isset($config)) { return $config; } else { throw new Exception('Error while loading "' . $file . '" (Not a valid config?)'); } } else { throw new Exception('File "' . $file . '" could not be loaded'); } } protected function loadOffset($offset) { $this->checkOffset($offset); if (is_readable($this->dir . $offset . '.php')) { $this->vars[$offset] = array(); self::loadConfig($this->vars[$offset], $this->dir . $offset . '.php', $this->rootConfig); } elseif (is_dir($this->dir . $offset)) { $this->vars[$offset] = array(); } else { throw new Exception('Offset "' . $offset . '" does not exist'); } return $this->offsetGet($offset); } public function offsetGet($offset) { if (!isset($this->vars[$offset])) { $this->loadOffset($offset); } if (is_array($this->vars[$offset])) { $subconfig = new config( $this->dir . $offset . DIRECTORY_SEPARATOR, $this->rootConfig); $subconfig->vars = &$this->vars[$offset]; return $subconfig; } else { return $this->vars[$offset]; } } public function getIterator() { if (is_dir($this->dir)) { $files = scandir($this->dir); foreach ($files as $file) { if (preg_match('/^([a-zA-Z0-9_]+)(\.php)?$/', $file, $parts)) { $offset = $parts[1]; if (!isset($this->vars[$offset])) { $this->loadOffset($offset); } } } } $iteratorVars = array(); foreach (array_keys($this->vars) as $offset) { $iteratorVars[$offset] = $this->offsetGet($offset); } return new ArrayIterator($iteratorVars); } public function offsetSet($offset, $value) { throw new Exception('Config may not be changed'); } public function offsetUnset($offset) { throw new Exception('Config may not be changed'); } } ?> serverstats-0.8.2/includes/logger.class.php0000644000175000017500000000314710725006400016573 0ustar meme= $config['log']['level']); } abstract public function logString($loglevel, $string); abstract public function logException($loglevel, Exception $exception); } ?> serverstats-0.8.2/includes/logger_none.class.php0000644000175000017500000000217510725006400017612 0ustar meme serverstats-0.8.2/includes/source.class.php0000644000175000017500000000233010725006400016605 0ustar meme serverstats-0.8.2/includes/logger_mail.class.php0000644000175000017500000000316210725006400017572 0ustar memeaddress = $address; $this->subject = $subject; } private function sendEmail($loglevel, $message) { mail( $this->address, $this->subject . ': ' . logger::levelToString($loglevel), $message ); } public function logString($loglevel, $string) { if (!logger::needsLogging($loglevel)) return; $this->sendEmail($loglevel, $string); } public function logException($loglevel, Exception $exception) { if (!logger::needsLogging($loglevel)) return; $this->sendEmail($loglevel, $exception->__toSTring()); } } ?> serverstats-0.8.2/includes/rrdgraph.class.php0000644000175000017500000002514410725006400017126 0ustar memerrdtoolbin = $rrdtoolbin; $this->start = $start; $this->end = $end; } public function setTitle($title) { $this->title = $title; } public function setWidth($width) { $this->width = $width; } public function setHeight($height) { $this->height = $height; } public static function escape($text) { return str_replace(':', '\\:', $text); } public function add($type, $p1 = null, $p2 = null, $p3 = null, $p4 = null, $p5 = null, $p6 = null, $p7 = null, $p8 = null) { switch ($type) { case 'DEF': // DEF:=::[:step=][:start=