diff --git a/app/includes/config.php b/app/includes/config.php index 6019c88..358143b 100644 --- a/app/includes/config.php +++ b/app/includes/config.php @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -// Disable error reporting to screen -/*ini_set('display_errors', 0); -error_reporting(E_ALL);*/ +// Uncomment to enable error reporting to the screen +/*ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +ferror_reporting(E_ALL);*/ // Set the default system Timezone date_default_timezone_set('Europe/London'); @@ -27,6 +28,12 @@ // Path of vnstat $vnstat_bin_dir = '/usr/bin/vnstat'; +// Path of config file +/*$vnstat_config = '/etc/vnstat.conf';*/ + +// linear or logarithmic graphs. Uncomment for logarithmic +/*$graph_type = 'log';*/ + // Set to true to set your own interfaces $use_predefined_interfaces = false; diff --git a/app/includes/utilities.php b/app/includes/utilities.php index 351e376..01193c1 100644 --- a/app/includes/utilities.php +++ b/app/includes/utilities.php @@ -17,6 +17,19 @@ * along with this program. If not, see . */ +$logk = log(1024); + +function getScale($bytes) +{ + global $logk; + + $ui = floor(round(log($bytes)/$logk,3)); + if ($ui < 0) { $ui = 0; } + if ($ui > 8) { $ui = 8; } + + return $ui; +} + // Get the largest value in an array function getLargestValue($array) { return $max = array_reduce($array, function ($a, $b) { @@ -24,35 +37,73 @@ function getLargestValue($array) { }); } -function formatSize($bytes, $vnstatJsonVersion) { +function getBaseValue($array, $scale) +{ + $big = pow(1024,9); + + // Find the smallest non-zero value + $sml = array_reduce($array, function ($a, $b) { + if ((1 <= $b['rx']) && ($b['rx'] < $b['tx'])) { + $sm = $b['rx']; + } else { + $sm = $b['tx']; + } + if (($sm < 1) || ($a < $sm)) { + return $a; + } else { + return $sm; + } + }, $big); + + if ($sml >= $big/2) { + $sml = 1; + } + + // divide by scale then round down to a power of 10 + $base = pow(10,floor(round(log10($sml/pow(1024,$scale)),3))); + + // convert back to bytes + $baseByte = $base * pow(1024, $scale); + + // Don't make the bar invisable - must be > 5% difference + if ($sml / $baseByte < 1.05) { + $base = $base / 10; + } + + return $base; +} + +function formatSize($bytes, $vnstatJsonVersion, $decimals = 2) { + // json version 1 = convert from KiB // json version 2 = convert from bytes if ($vnstatJsonVersion == 1) { $bytes *= 1024; // convert from kibibytes to bytes } - return formatBytes($bytes); + return formatBytes($bytes, $decimals); } -function formatBytes($bytes, $decimals = 2) { - $base = log(floatval($bytes), 1024); +function getLargestPrefix($scale) +{ $suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + return $suffixes[$scale]; +} + +function formatBytes($bytes, $decimals = 3) { - return round(pow(1024, $base - floor($base)), $decimals) .' '. $suffixes[floor($base)]; + $scale = getScale($bytes); + + return round($bytes/pow(1024, $scale), $decimals) .' '. getLargestPrefix($scale); } -function formatBytesTo($bytes, $delimiter, $decimals = 2) { +function formatBytesTo($bytes, $scale, $decimals = 4) { + if ($bytes == 0) { return '0'; } - $k = 1024; - $dm = $decimals < 0 ? 0 : $decimals; - $sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - - $i = array_search($delimiter, $sizes); - - return number_format(($bytes / pow($k, $i)), $decimals); + return number_format(($bytes / pow(1024, $scale)), $decimals, ".", ""); } function kibibytesToBytes($kibibytes, $vnstatJsonVersion) { @@ -63,20 +114,6 @@ function kibibytesToBytes($kibibytes, $vnstatJsonVersion) { } } -function getLargestPrefix($kb) -{ - $units = ['TB', 'GB', 'MB', 'KB', 'B']; - $scale = 1024 * 1024 * 1024 * 1024; - $ui = 0; - - while ((($kb < $scale) && ($scale > 1))) { - $ui++; - $scale = $scale / 1024; - } - - return $units[$ui]; -} - function sortingFunction($item1, $item2) { if ($item1['time'] == $item2['time']) { return 0; diff --git a/app/includes/vnstat.php b/app/includes/vnstat.php index 965ec8f..971fcf6 100644 --- a/app/includes/vnstat.php +++ b/app/includes/vnstat.php @@ -78,7 +78,11 @@ public function getInterfaces() { $vnstatInterfaces = []; foreach($this->vnstatData['interfaces'] as $interface) { + if ($this->vnstatJsonVersion == 1) { array_push($vnstatInterfaces, $interface['id']); + } else { + array_push($vnstatInterfaces, $interface['name']); + } } return $vnstatInterfaces; @@ -87,15 +91,21 @@ public function getInterfaces() { public function getInterfaceData($timeperiod, $type, $interface) { // If json version equals 1, add an 's' onto the end of each type. // e.g. 'top' becomes 'tops' + $typeAppend = ''; if ($this->vnstatJsonVersion == 1) { $typeAppend = 's'; } // Blank placeholder $trafficData = []; + $i = -1; // Get the array index for the chosen interface - $arrayIndex = array_search($interface, array_column($this->vnstatData['interfaces'], 'id')); + if ($this->vnstatJsonVersion == 1) { + $arrayIndex = array_search($interface, array_column($this->vnstatData['interfaces'], 'id')); + } else { + $arrayIndex = array_search($interface, array_column($this->vnstatData['interfaces'], 'name')); + } if ($timeperiod == 'top10') { if ($type == 'table') { @@ -113,6 +123,34 @@ public function getInterfaceData($timeperiod, $type, $interface) { } } + if (($this->vnstatJsonVersion > 1) && ($timeperiod == 'five')) { + if ($type == 'table') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['fiveminute'] as $traffic) { + if (is_array($traffic)) { + $i++; + + $trafficData[$i]['label'] = date("d/m/Y H:i", mktime($traffic['time']['hour'], $traffic['time']['minute'], 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year'])); + $trafficData[$i]['time'] = mktime($traffic['time']['hour'], $traffic['time']['minute'], 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year']); + $trafficData[$i]['rx'] = formatSize($traffic['rx'], $this->vnstatJsonVersion); + $trafficData[$i]['tx'] = formatSize($traffic['tx'], $this->vnstatJsonVersion); + $trafficData[$i]['total'] = formatSize(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); + } + } + } else if ($type == 'graph') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['fiveminute'] as $traffic) { + if (is_array($traffic)) { + $i++; + + $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d, %d, %d)", $traffic['date']['year'], $traffic['date']['month']-1, $traffic['date']['day'], $traffic['time']['hour'], $traffic['time']['minute']); + $trafficData[$i]['time'] = mktime($traffic['time']['hour'], $traffic['time']['minute'], 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year']); + $trafficData[$i]['rx'] = kibibytesToBytes($traffic['rx'], $this->vnstatJsonVersion); + $trafficData[$i]['tx'] = kibibytesToBytes($traffic['tx'], $this->vnstatJsonVersion); + $trafficData[$i]['total'] = kibibytesToBytes(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); + } + } + } + } + if ($timeperiod == 'hourly') { if ($type == 'table') { foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['hour'.$typeAppend] as $traffic) { @@ -133,7 +171,6 @@ public function getInterfaceData($timeperiod, $type, $interface) { } } - usort($trafficData, sortingFunction); } else if ($type == 'graph') { foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['hour'.$typeAppend] as $traffic) { @@ -146,7 +183,8 @@ public function getInterfaceData($timeperiod, $type, $interface) { $hour = $traffic['time']['hour']; } - $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d, %d, %d, %d)", $traffic['date']['year'], $traffic['date']['month']-1, $traffic['date']['day'], $hour, 0, 0); + $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d, %d)", $traffic['date']['year'], $traffic['date']['month']-1, $traffic['date']['day'], $hour); + $trafficData[$i]['time'] = mktime($hour, 0, 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year']); $trafficData[$i]['rx'] = kibibytesToBytes($traffic['rx'], $this->vnstatJsonVersion); $trafficData[$i]['tx'] = kibibytesToBytes($traffic['tx'], $this->vnstatJsonVersion); $trafficData[$i]['total'] = kibibytesToBytes(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); @@ -162,6 +200,7 @@ public function getInterfaceData($timeperiod, $type, $interface) { $i++; $trafficData[$i]['label'] = date('d/m/Y', mktime(0, 0, 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year'])); + $trafficData[$i]['time'] = mktime(0, 0, 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year']); $trafficData[$i]['rx'] = formatSize($traffic['rx'], $this->vnstatJsonVersion); $trafficData[$i]['tx'] = formatSize($traffic['tx'], $this->vnstatJsonVersion); $trafficData[$i]['total'] = formatSize(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); @@ -172,7 +211,8 @@ public function getInterfaceData($timeperiod, $type, $interface) { if (is_array($traffic)) { $i++; - $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d, %d, %d, %d)", $traffic['date']['year'], $traffic['date']['month']-1, $traffic['date']['day'], 0, 0, 0); + $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d)", $traffic['date']['year'], $traffic['date']['month']-1, $traffic['date']['day']); + $trafficData[$i]['time'] = mktime(0, 0, 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year']); $trafficData[$i]['rx'] = kibibytesToBytes($traffic['rx'], $this->vnstatJsonVersion); $trafficData[$i]['tx'] = kibibytesToBytes($traffic['tx'], $this->vnstatJsonVersion); $trafficData[$i]['total'] = kibibytesToBytes(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); @@ -188,6 +228,7 @@ public function getInterfaceData($timeperiod, $type, $interface) { $i++; $trafficData[$i]['label'] = date('F Y', mktime(0, 0, 0, $traffic['date']['month'], 10, $traffic['date']['year'])); + $trafficData[$i]['time'] = mktime(0, 0, 0, $traffic['date']['month'], 10, $traffic['date']['year']); $trafficData[$i]['rx'] = formatSize($traffic['rx'], $this->vnstatJsonVersion); $trafficData[$i]['tx'] = formatSize($traffic['tx'], $this->vnstatJsonVersion); $trafficData[$i]['total'] = formatSize(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); @@ -198,7 +239,8 @@ public function getInterfaceData($timeperiod, $type, $interface) { if (is_array($traffic)) { $i++; - $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d, %d, %d, %d)", $traffic['date']['year'], $traffic['date']['month'] - 1, 10, 0, 0, 0); + $trafficData[$i]['label'] = sprintf("Date(%d, %d, %d)", $traffic['date']['year'], $traffic['date']['month'] - 1, 10); + $trafficData[$i]['time'] = mktime(0, 0, 0, $traffic['date']['month'], 10, $traffic['date']['year']); $trafficData[$i]['rx'] = kibibytesToBytes($traffic['rx'], $this->vnstatJsonVersion); $trafficData[$i]['tx'] = kibibytesToBytes($traffic['tx'], $this->vnstatJsonVersion); $trafficData[$i]['total'] = kibibytesToBytes(($traffic['rx'] + $traffic['tx']), $this->vnstatJsonVersion); @@ -207,17 +249,32 @@ public function getInterfaceData($timeperiod, $type, $interface) { } } + if ($timeperiod != 'top10') { + usort($trafficData, 'sortingFunction'); + } + if ($type == 'graph') { // Get the largest value and then prefix (B, KB, MB, GB, etc) $trafficLargestValue = getLargestValue($trafficData); - $trafficLargestPrefix = getLargestPrefix($trafficLargestValue); + $trafficScale = getScale($trafficLargestValue); + $trafficLargestPrefix = getLargestPrefix($trafficScale); + $trafficBase = getBaseValue($trafficData, $trafficScale); + if (($trafficBase < .0099) && ($trafficScale >= 1)) + { + $trafficScale = $trafficScale - 1; + $trafficLargestPrefix = getLargestPrefix($trafficScale); + $trafficBase = getBaseValue($trafficData, $trafficScale); + } - foreach($trafficData as $key => $value) { - $trafficData[$key]['rx'] = formatBytesTo($value['rx'], $trafficLargestPrefix); - $trafficData[$key]['tx'] = formatBytesTo($value['tx'], $trafficLargestPrefix); - $trafficData[$key]['total'] = formatBytesTo($value['total'], $trafficLargestPrefix); - $trafficData[$key]['delimiter'] = $trafficLargestPrefix; + foreach($trafficData as &$value) { + $value['rx'] = formatBytesTo($value['rx'], $trafficScale); + $value['tx'] = formatBytesTo($value['tx'], $trafficScale); + $value['total'] = formatBytesTo($value['total'], $trafficScale); } + + unset($value); + $trafficData[0]['delimiter'] = $trafficLargestPrefix; + $trafficData[0]['base'] = $trafficBase; } return $trafficData; diff --git a/app/index.php b/app/index.php index a1ebcc9..dfdd2c4 100644 --- a/app/index.php +++ b/app/index.php @@ -19,12 +19,22 @@ // Require includes require __DIR__ . '/vendor/autoload.php'; -require __DIR__ . '/includes/vnstat.php'; require __DIR__ . '/includes/utilities.php'; +require __DIR__ . '/includes/vnstat.php'; require __DIR__ . '/includes/config.php'; +if (isset($vnstat_config)) { + $vnstat_cmd = $vnstat_bin_dir.' --config '.$vnstat_config; +} else { + $vnstat_cmd = $vnstat_bin_dir; +} + +if (empty($graph_type)) { + $graph_type = 'linear'; +} + // Initiaite vnStat class -$vnstat = new vnStat($vnstat_bin_dir); +$vnstat = new vnStat($vnstat_cmd); // Initiate Smarty $smarty = new Smarty(); @@ -51,13 +61,22 @@ $thisInterface = reset($interface_list); } +$smarty->assign('graph_type', $graph_type); $smarty->assign('current_interface', $thisInterface); // Assign interface options -$smarty->assign('interface_list', $vnstat->getInterfaces()); +$smarty->assign('interface_list', $interface_list); + +// JsonVersion +$smarty->assign('jsonVersion', $vnstat->getVnstatJsonVersion()); // Populate table data +if ($vnstat->getVnstatJsonVersion() > 1) { + $fiveData = $vnstat->getInterfaceData('five', 'table', $thisInterface); + $smarty->assign('fiveTableData', $fiveData); +} + $hourlyData = $vnstat->getInterfaceData('hourly', 'table', $thisInterface); $smarty->assign('hourlyTableData', $hourlyData); @@ -71,17 +90,26 @@ $smarty->assign('top10TableData', $top10Data); // Populate graph data +if ($vnstat->getVnstatJsonVersion() > 1) { + $fiveGraphData = $vnstat->getInterfaceData('five', 'graph', $thisInterface); + $smarty->assign('fiveGraphData', $fiveGraphData); + $smarty->assign('fiveLargestPrefix', $fiveGraphData[0]['delimiter']); + $smarty->assign('fiveBase', $fiveGraphData[0]['base']); +} + $hourlyGraphData = $vnstat->getInterfaceData('hourly', 'graph', $thisInterface); $smarty->assign('hourlyGraphData', $hourlyGraphData); -$smarty->assign('hourlyLargestPrefix', $hourlyGraphData[1]['delimiter']); +$smarty->assign('hourlyLargestPrefix', $hourlyGraphData[0]['delimiter']); +$smarty->assign('hourlyBase', $hourlyGraphData[0]['base']); $dailyGraphData = $vnstat->getInterfaceData('daily', 'graph', $thisInterface); $smarty->assign('dailyGraphData', $dailyGraphData); -$smarty->assign('dailyLargestPrefix', $dailyGraphData[1]['delimiter']); +$smarty->assign('dailyLargestPrefix', $dailyGraphData[0]['delimiter']); +$smarty->assign('dailyBase', $dailyGraphData[0]['base']); $monthlyGraphData = $vnstat->getInterfaceData('monthly', 'graph', $thisInterface); $smarty->assign('monthlyGraphData', $monthlyGraphData); -$smarty->assign('monthlyLargestPrefix', $monthlyGraphData[1]['delimiter']); +$smarty->assign('monthlyLargestPrefix', $monthlyGraphData[0]['delimiter']); // Display the page $smarty->display('templates/site_index.tpl'); diff --git a/app/templates/module_graph.tpl b/app/templates/module_graph.tpl index 84784f8..a01f68c 100644 --- a/app/templates/module_graph.tpl +++ b/app/templates/module_graph.tpl @@ -1,8 +1,17 @@
-
-
-
+ {if $jsonVersion gt 1} +
+
+
+ +
+
+
+ {else} +
+
+
+ {/if}
diff --git a/app/templates/module_graph_js.tpl b/app/templates/module_graph_js.tpl index 9247ac4..a99eed4 100644 --- a/app/templates/module_graph_js.tpl +++ b/app/templates/module_graph_js.tpl @@ -1,11 +1,80 @@