From 31f2ee91dd9ee3c3d89e1cb9a29b5d4ef8ec65d1 Mon Sep 17 00:00:00 2001 From: Stille Date: Tue, 8 Jun 2021 20:47:17 +0800 Subject: [PATCH] Create vnstat-dashboard --- .github/workflows/vnstat-dashboard.yml | 42 +++ vnstat-dashboard/.editorconfig | 9 + vnstat-dashboard/Dockerfile | 17 ++ vnstat-dashboard/README.md | 8 + vnstat-dashboard/_config.yml | 1 + vnstat-dashboard/app/assets/css/style.css | 50 +++ vnstat-dashboard/app/composer.json | 5 + vnstat-dashboard/app/includes/config.php | 45 +++ vnstat-dashboard/app/includes/utilities.php | 125 ++++++++ vnstat-dashboard/app/includes/vnstat.php | 284 ++++++++++++++++++ vnstat-dashboard/app/index.php | 117 ++++++++ .../app/templates/module_footer.tpl | 16 + .../app/templates/module_graph.tpl | 46 +++ .../app/templates/module_graph_js.tpl | 256 ++++++++++++++++ .../app/templates/module_header.tpl | 33 ++ .../app/templates/module_table.tpl | 146 +++++++++ vnstat-dashboard/app/templates/site_index.tpl | 7 + vnstat-dashboard/docker-compose.yml | 11 + vnstat-dashboard/docs/README.md | 0 19 files changed, 1218 insertions(+) create mode 100644 .github/workflows/vnstat-dashboard.yml create mode 100644 vnstat-dashboard/.editorconfig create mode 100644 vnstat-dashboard/Dockerfile create mode 100644 vnstat-dashboard/README.md create mode 100644 vnstat-dashboard/_config.yml create mode 100644 vnstat-dashboard/app/assets/css/style.css create mode 100644 vnstat-dashboard/app/composer.json create mode 100644 vnstat-dashboard/app/includes/config.php create mode 100644 vnstat-dashboard/app/includes/utilities.php create mode 100644 vnstat-dashboard/app/includes/vnstat.php create mode 100644 vnstat-dashboard/app/index.php create mode 100644 vnstat-dashboard/app/templates/module_footer.tpl create mode 100644 vnstat-dashboard/app/templates/module_graph.tpl create mode 100644 vnstat-dashboard/app/templates/module_graph_js.tpl create mode 100644 vnstat-dashboard/app/templates/module_header.tpl create mode 100644 vnstat-dashboard/app/templates/module_table.tpl create mode 100644 vnstat-dashboard/app/templates/site_index.tpl create mode 100644 vnstat-dashboard/docker-compose.yml create mode 100644 vnstat-dashboard/docs/README.md diff --git a/.github/workflows/vnstat-dashboard.yml b/.github/workflows/vnstat-dashboard.yml new file mode 100644 index 0000000..1ddd776 --- /dev/null +++ b/.github/workflows/vnstat-dashboard.yml @@ -0,0 +1,42 @@ +name: "vnstat-dashboard docker build" + +env: + PROJECT: vnstat-dashboard + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: true + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set tag + id: tag + run: | + TAG=$(cat ${{ env.PROJECT }}/Dockerfile | awk 'NR==4 {print $3}') + echo "::set-env name=TAG::$TAG" + - name: Docker Hub login + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + run: | + echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin + - name: Set up Docker Buildx + id: buildx + uses: crazy-max/ghaction-docker-buildx@v1 + with: + buildx-version: latest + - name: Build Dockerfile + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + run: | + docker buildx build \ + --platform=linux/amd64,linux/arm64 \ + --output "type=image,push=true" \ + --file ${{ env.PROJECT }}/Dockerfile ./${{ env.PROJECT }} \ + --tag $(echo "${DOCKER_USERNAME}" | tr '[:upper:]' '[:lower:]')/${{ env.PROJECT }}:latest \ + --tag $(echo "${DOCKER_USERNAME}" | tr '[:upper:]' '[:lower:]')/${{ env.PROJECT }}:${TAG} diff --git a/vnstat-dashboard/.editorconfig b/vnstat-dashboard/.editorconfig new file mode 100644 index 0000000..3c44241 --- /dev/null +++ b/vnstat-dashboard/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/vnstat-dashboard/Dockerfile b/vnstat-dashboard/Dockerfile new file mode 100644 index 0000000..332e0ef --- /dev/null +++ b/vnstat-dashboard/Dockerfile @@ -0,0 +1,17 @@ +FROM php:7.0-apache +MAINTAINER Alex Marston + +ENV VERSION 1.0 +# Install Git +RUN apt-get update && apt-get install -y git unzip + +# Install Composer to handle dependencies +RUN curl -sS https://getcomposer.org/installer | php && mv composer.phar /usr/local/bin/composer + +# Copy application source code to html directory +COPY ./app/ /var/www/html/ + +# Install dependencies +RUN composer install + +RUN mkdir -p /var/lib/vnstat diff --git a/vnstat-dashboard/README.md b/vnstat-dashboard/README.md new file mode 100644 index 0000000..f9a6595 --- /dev/null +++ b/vnstat-dashboard/README.md @@ -0,0 +1,8 @@ +# vnstat-dashboard for docker + +GitHub [stilleshan/dockerfile](https://github.com/stilleshan/dockerfile) +Docker [stilleshan/vnstat-dashboard](https://hub.docker.com/r/stilleshan/vnstat-dashboard) +> *docker image support for X86 and ARM* + +## 使用 +本仓库参考 [tomangert/vnstat-dashboard](https://github.com/tomangert/vnstat-dashboard) 对原作者仓库 [alexandermarston/vnstat-dashboard](https://github.com/alexandermarston/vnstat-dashboard) 进行部分 bug 修复后构建 docker 镜像,主要用与自用和存档备份,具体使用教程请参考原作者仓库`README`文件. diff --git a/vnstat-dashboard/_config.yml b/vnstat-dashboard/_config.yml new file mode 100644 index 0000000..c741881 --- /dev/null +++ b/vnstat-dashboard/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file diff --git a/vnstat-dashboard/app/assets/css/style.css b/vnstat-dashboard/app/assets/css/style.css new file mode 100644 index 0000000..6ba73b5 --- /dev/null +++ b/vnstat-dashboard/app/assets/css/style.css @@ -0,0 +1,50 @@ +/* +Copyright (C) 2019 Alexander Marston (alexander.marston@gmail.com) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* http://stackoverflow.com/questions/17206631/why-are-bootstrap-tabs-displaying-tab-pane-divs-with-incorrect-widths-when-using */ +/* bootstrap hack: fix content width inside hidden tabs */ +.tab-content > .tab-pane:not(.active), +.pill-content > .pill-pane:not(.active) { + display: block; + height: 0; + overflow-y: hidden; +} +/* bootstrap hack end */ + +/* Sticky footer styles +-------------------------------------------------- */ +html { + position: relative; + min-height: 100%; +} +body { + margin-bottom: 60px; /* Margin bottom by footer height */ +} +.footer { + position: absolute; + bottom: 0; + width: 100%; + height: 60px; /* Set the fixed height of the footer here */ + line-height: 60px; /* Vertically center the text there */ + background-color: #f5f5f5; +} +.nav-tabs { + margin-bottom: 10px; +} +.navbar { + margin-bottom: 25px; +} diff --git a/vnstat-dashboard/app/composer.json b/vnstat-dashboard/app/composer.json new file mode 100644 index 0000000..6bc30dd --- /dev/null +++ b/vnstat-dashboard/app/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "smarty/smarty": "~3.1" + } +} diff --git a/vnstat-dashboard/app/includes/config.php b/vnstat-dashboard/app/includes/config.php new file mode 100644 index 0000000..358143b --- /dev/null +++ b/vnstat-dashboard/app/includes/config.php @@ -0,0 +1,45 @@ +. + */ + +// 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'); + +// 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; + +if ($use_predefined_interfaces == true) { + $interface_list = ["eth0", "eth1"]; + + $interface_name['eth0'] = "Internal #1"; + $interface_name['eth1'] = "Internal #2"; +} diff --git a/vnstat-dashboard/app/includes/utilities.php b/vnstat-dashboard/app/includes/utilities.php new file mode 100644 index 0000000..01193c1 --- /dev/null +++ b/vnstat-dashboard/app/includes/utilities.php @@ -0,0 +1,125 @@ +. + */ + +$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) { + return $a > $b['total'] ? $a : $b['total']; + }); +} + +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, $decimals); +} + +function getLargestPrefix($scale) +{ + $suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + return $suffixes[$scale]; +} + +function formatBytes($bytes, $decimals = 3) { + + $scale = getScale($bytes); + + return round($bytes/pow(1024, $scale), $decimals) .' '. getLargestPrefix($scale); +} + +function formatBytesTo($bytes, $scale, $decimals = 4) { + + if ($bytes == 0) { + return '0'; + } + + return number_format(($bytes / pow(1024, $scale)), $decimals, ".", ""); +} + +function kibibytesToBytes($kibibytes, $vnstatJsonVersion) { + if ($vnstatJsonVersion == 1) { + return $kibibytes *= 1024; + } else { + return $kibibytes; + } +} + +function sortingFunction($item1, $item2) { + if ($item1['time'] == $item2['time']) { + return 0; + } else { + return $item1['time'] > $item2['time'] ? -1 : 1; + } +}; + +?> diff --git a/vnstat-dashboard/app/includes/vnstat.php b/vnstat-dashboard/app/includes/vnstat.php new file mode 100644 index 0000000..971fcf6 --- /dev/null +++ b/vnstat-dashboard/app/includes/vnstat.php @@ -0,0 +1,284 @@ +. + */ + +class vnStat { + protected $executablePath; + protected $vnstatVersion; + protected $vnstatJsonVersion; + protected $vnstatData; + + public function __construct ($executablePath) { + if (isset($executablePath)) { + $this->executablePath = $executablePath; + + // Execute a command to output a json dump of the vnstat data + $vnstatStream = popen("$this->executablePath --json", 'r'); + + // Is the stream valid? + if (is_resource($vnstatStream)) { + $streamBuffer = ''; + + while (!feof($vnstatStream)) { + $streamBuffer .= fgets($vnstatStream); + } + + // Close the handle + pclose($vnstatStream); + + $this->processVnstatData($streamBuffer); + } else { + + } + + + } else { + die(); + } + } + + private function processVnstatData($vnstatJson) { + $decodedJson = json_decode($vnstatJson, true); + + // Check the JSON is valid + if (json_last_error() != JSON_ERROR_NONE) { + throw new Exception('JSON is invalid'); + } + + $this->vnstatData = $decodedJson; + $this->vnstatVersion = $decodedJson['vnstatversion']; + $this->vnstatJsonVersion = $decodedJson['jsonversion']; + } + + public function getVnstatVersion() { + return $this->vnstatVersion; + } + + public function getVnstatJsonVersion() { + return $this->vnstatJsonVersion; + } + + public function getInterfaces() { + // Create a placeholder array + $vnstatInterfaces = []; + + foreach($this->vnstatData['interfaces'] as $interface) { + if ($this->vnstatJsonVersion == 1) { + array_push($vnstatInterfaces, $interface['id']); + } else { + array_push($vnstatInterfaces, $interface['name']); + } + } + + return $vnstatInterfaces; + } + + 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 + 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') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['top'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $i++; + + $trafficData[$i]['label'] = date('d/m/Y', strtotime($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); + $trafficData[$i]['totalraw'] = ($traffic['rx'] + $traffic['tx']); + } + } + } + } + + 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) { + if (is_array($traffic)) { + $i++; + + if ($this->vnstatJsonVersion == 1) { + $hour = $traffic['id']; + } else { + $hour = $traffic['time']['hour']; + } + + $trafficData[$i]['label'] = date("d/m/Y H:i", mktime($hour, 0, 0, $traffic['date']['month'], $traffic['date']['day'], $traffic['date']['year'])); + $trafficData[$i]['time'] = mktime($hour, 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); + } + } + + + } else if ($type == 'graph') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['hour'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $i++; + + if ($this->vnstatJsonVersion == 1) { + $hour = $traffic['id']; + } else { + $hour = $traffic['time']['hour']; + } + + $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); + } + } + } + } + + if ($timeperiod == 'daily') { + if ($type == 'table') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['day'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $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); + } + } + } else if ($type == 'graph') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['day'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $i++; + + $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); + } + } + } + } + + if ($timeperiod == 'monthly') { + if ($type == 'table') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['month'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $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); + } + } + } else if ($type == 'graph') { + foreach ($this->vnstatData['interfaces'][$arrayIndex]['traffic']['month'.$typeAppend] as $traffic) { + if (is_array($traffic)) { + $i++; + + $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); + } + } + } + } + + if ($timeperiod != 'top10') { + usort($trafficData, 'sortingFunction'); + } + + if ($type == 'graph') { + // Get the largest value and then prefix (B, KB, MB, GB, etc) + $trafficLargestValue = getLargestValue($trafficData); + $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 &$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/vnstat-dashboard/app/index.php b/vnstat-dashboard/app/index.php new file mode 100644 index 0000000..dfdd2c4 --- /dev/null +++ b/vnstat-dashboard/app/index.php @@ -0,0 +1,117 @@ +. + */ + +// Require includes +require __DIR__ . '/vendor/autoload.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_cmd); + +// Initiate Smarty +$smarty = new Smarty(); + +// Set the current year +$smarty->assign('year', date("Y")); + +// Set the list of interfaces +$interface_list = $vnstat->getInterfaces(); + +// Set the current interface +$thisInterface = ""; + +if (isset($_GET['i'])) { + $interfaceChosen = rawurldecode($_GET['i']); + + if (in_array($interfaceChosen, $interface_list, true)) { + $thisInterface = $interfaceChosen; + } else { + $thisInterface = reset($interface_list); + } +} else { + // Assume they mean the first interface + $thisInterface = reset($interface_list); +} + +$smarty->assign('graph_type', $graph_type); + +$smarty->assign('current_interface', $thisInterface); + +// Assign interface options +$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); + +$dailyData = $vnstat->getInterfaceData('daily', 'table', $thisInterface); +$smarty->assign('dailyTableData', $dailyData); + +$monthlyData = $vnstat->getInterfaceData('monthly', 'table', $thisInterface); +$smarty->assign('monthlyTableData', $monthlyData); + +$top10Data = $vnstat->getInterfaceData('top10', 'table', $thisInterface); +$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[0]['delimiter']); +$smarty->assign('hourlyBase', $hourlyGraphData[0]['base']); + +$dailyGraphData = $vnstat->getInterfaceData('daily', 'graph', $thisInterface); +$smarty->assign('dailyGraphData', $dailyGraphData); +$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[0]['delimiter']); + +// Display the page +$smarty->display('templates/site_index.tpl'); + +?> diff --git a/vnstat-dashboard/app/templates/module_footer.tpl b/vnstat-dashboard/app/templates/module_footer.tpl new file mode 100644 index 0000000..748798e --- /dev/null +++ b/vnstat-dashboard/app/templates/module_footer.tpl @@ -0,0 +1,16 @@ + + + + + +{include file="module_graph_js.tpl"} + + + + diff --git a/vnstat-dashboard/app/templates/module_graph.tpl b/vnstat-dashboard/app/templates/module_graph.tpl new file mode 100644 index 0000000..a01f68c --- /dev/null +++ b/vnstat-dashboard/app/templates/module_graph.tpl @@ -0,0 +1,46 @@ +
+ + +
+ {if $jsonVersion gt 1} +
+
+
+ +
+
+
+ {else} +
+
+
+ {/if} + +
+
+
+ +
+
+
+
+
diff --git a/vnstat-dashboard/app/templates/module_graph_js.tpl b/vnstat-dashboard/app/templates/module_graph_js.tpl new file mode 100644 index 0000000..a99eed4 --- /dev/null +++ b/vnstat-dashboard/app/templates/module_graph_js.tpl @@ -0,0 +1,256 @@ + diff --git a/vnstat-dashboard/app/templates/module_header.tpl b/vnstat-dashboard/app/templates/module_header.tpl new file mode 100644 index 0000000..7b1aa82 --- /dev/null +++ b/vnstat-dashboard/app/templates/module_header.tpl @@ -0,0 +1,33 @@ + + + + Network Traffic + + + + + + + + + + + + + diff --git a/vnstat-dashboard/app/templates/module_table.tpl b/vnstat-dashboard/app/templates/module_table.tpl new file mode 100644 index 0000000..dfb200d --- /dev/null +++ b/vnstat-dashboard/app/templates/module_table.tpl @@ -0,0 +1,146 @@ +
+ + +
+ {if $jsonVersion gt 1} +
+ + + + + + + + + + +{foreach from=$fiveTableData key=key item=value} + + + + + + +{/foreach} + +
TimeReceivedSentTotal
{$value.label}{$value.rx}{$value.tx}{$value.total}
+
+ +
+ {else} +
+ {/if} + + + + + + + + + + +{foreach from=$hourlyTableData key=key item=value} + + + + + + +{/foreach} + +
HourReceivedSentTotal
{$value.label}{$value.rx}{$value.tx}{$value.total}
+
+ +
+ + + + + + + + + + +{foreach from=$dailyTableData key=key item=value} + + + + + + +{/foreach} + +
DayReceivedSentTotal
{$value.label}{$value.rx}{$value.tx}{$value.total}
+
+ +
+ + + + + + + + + + +{foreach from=$monthlyTableData key=key item=value} + + + + + + +{/foreach} + +
MonthReceivedSentTotal
{$value.label}{$value.rx}{$value.tx}{$value.total}
+
+ +
+ + + + + + + + + + +{foreach from=$top10TableData key=key item=value} + + + + + + +{/foreach} + +
DayReceivedSentTotal
{$value.label}{$value.rx}{$value.tx}{$value.total}
+
+
+
diff --git a/vnstat-dashboard/app/templates/site_index.tpl b/vnstat-dashboard/app/templates/site_index.tpl new file mode 100644 index 0000000..81201bf --- /dev/null +++ b/vnstat-dashboard/app/templates/site_index.tpl @@ -0,0 +1,7 @@ +{include file="module_header.tpl"} + +{include file="module_graph.tpl"} + +{include file="module_table.tpl"} + +{include file="module_footer.tpl"} diff --git a/vnstat-dashboard/docker-compose.yml b/vnstat-dashboard/docker-compose.yml new file mode 100644 index 0000000..a46f955 --- /dev/null +++ b/vnstat-dashboard/docker-compose.yml @@ -0,0 +1,11 @@ +version: '3' +services: + vnstat-dashboard: + build: . + network_mode: "host" + container_name: vnstat-dashboard + volumes: + - /var/lib/vnstat:/var/lib/vnstat + - /usr/bin/vnstat:/usr/local/bin/vnstat + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock diff --git a/vnstat-dashboard/docs/README.md b/vnstat-dashboard/docs/README.md new file mode 100644 index 0000000..e69de29