mirror of
https://github.com/nidebr/as-stats-gui.git
synced 2025-02-20 11:23:18 +08:00
save
This commit is contained in:
parent
ad457e9a30
commit
72a24ec46c
13
asstats.yml
13
asstats.yml
@ -20,6 +20,19 @@ config:
|
||||
## Size of graphs on top N AS page ##
|
||||
top_graph_width: 600
|
||||
top_graph_height: 220
|
||||
linksusage:
|
||||
top: 3
|
||||
color:
|
||||
- A6CEE3
|
||||
- 1F78B4
|
||||
- B2DF8A
|
||||
- 33A02C
|
||||
- FB9A99
|
||||
- E31A1C
|
||||
- FDBF6F
|
||||
- FF7F00
|
||||
- CAB2D6
|
||||
- 6A3D9A
|
||||
|
||||
##
|
||||
# Custom time intervals for top N AS */
|
||||
|
@ -148,4 +148,30 @@ class ConfigApplication
|
||||
|
||||
return self::getAsStatsConfig()['graph'];
|
||||
}
|
||||
|
||||
public static function getLinksUsageColor(): array
|
||||
{
|
||||
if (false === \array_key_exists('linksusage', self::getAsStatsConfig())) {
|
||||
throw new ConfigErrorException('Unable to found config.linksusage variable');
|
||||
}
|
||||
|
||||
if (false === \array_key_exists('color', self::getAsStatsConfig()['linksusage'])) {
|
||||
throw new ConfigErrorException('Unable to found config.linksusage.color variable');
|
||||
}
|
||||
|
||||
return self::getAsStatsConfig()['linksusage']['color'];
|
||||
}
|
||||
|
||||
public static function getLinksUsageTop(): int
|
||||
{
|
||||
if (false === \array_key_exists('linksusage', self::getAsStatsConfig())) {
|
||||
throw new ConfigErrorException('Unable to found config.linksusage variable');
|
||||
}
|
||||
|
||||
if (false === \array_key_exists('top', self::getAsStatsConfig()['linksusage'])) {
|
||||
throw new ConfigErrorException('Unable to found config.linksusage.top variable');
|
||||
}
|
||||
|
||||
return self::getAsStatsConfig()['linksusage']['top'];
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Repository\KnowlinksRepository;
|
||||
use App\Util\Annotation\Menu;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
@ -12,7 +13,7 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
path: '/links/usage',
|
||||
)]
|
||||
#[Menu('links_usage')]
|
||||
class LinkUsageController extends BaseController
|
||||
class LinksUsageController extends BaseController
|
||||
{
|
||||
protected array $data = [];
|
||||
|
||||
@ -25,6 +26,7 @@ class LinkUsageController extends BaseController
|
||||
{
|
||||
return $this->render('pages/link_usage/index.html.twig', [
|
||||
'base_data' => $this->base_data,
|
||||
'knownlinks' => KnowlinksRepository::get(),
|
||||
]);
|
||||
}
|
||||
|
@ -4,7 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Repository\RRDRepository;
|
||||
use App\Application\ConfigApplication;
|
||||
use App\Exception\ConfigErrorException;
|
||||
use App\Exception\DbErrorException;
|
||||
use App\Repository\GetAsDataRepository;
|
||||
use App\Repository\RRDAsnRepository;
|
||||
use App\Repository\RRDLinksUsageRepository;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@ -24,7 +30,41 @@ class RenderController extends AbstractController
|
||||
int $as,
|
||||
Request $request,
|
||||
): Response {
|
||||
$cmd = new RRDRepository($as, $request->query->all());
|
||||
$cmd = new RRDAsnRepository($as, $request->query->all());
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Content-type', 'image/png');
|
||||
$response->sendHeaders();
|
||||
$response->setContent(
|
||||
\sprintf(
|
||||
'%s',
|
||||
passthru($cmd->generateCmd())
|
||||
)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ConfigErrorException
|
||||
* @throws DbErrorException
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Route(
|
||||
path: '/links/usage/graph/{link}',
|
||||
name: 'render.links.usage.graph',
|
||||
methods: ['GET'],
|
||||
)]
|
||||
public function renderGraphLinksUsage(
|
||||
string $link,
|
||||
Request $request,
|
||||
GetAsDataRepository $asDataRepository,
|
||||
): Response {
|
||||
$cmd = new RRDLinksUsageRepository(
|
||||
$link,
|
||||
$request->query->all(),
|
||||
$asDataRepository::get(ConfigApplication::getLinksUsageTop(), '', [$link => true])
|
||||
);
|
||||
|
||||
$response = new Response();
|
||||
$response->headers->set('Content-type', 'image/png');
|
||||
|
@ -5,68 +5,31 @@ declare(strict_types=1);
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Application\ConfigApplication;
|
||||
use App\Util\RRDGraph;
|
||||
|
||||
class RRDRepository
|
||||
class RRDAsnRepository
|
||||
{
|
||||
private int $as;
|
||||
private array $request;
|
||||
private array $knowlinks;
|
||||
private string $rrdfile;
|
||||
private string $v6;
|
||||
private RRDGraph $rrdGraph;
|
||||
|
||||
public function __construct(int $as, array $req)
|
||||
{
|
||||
$this->as = $as;
|
||||
$this->request = $req;
|
||||
|
||||
$this->rrdGraph = new RRDGraph($this->request);
|
||||
$this->knowlinks = $this->selectedLinks();
|
||||
$this->rrdfile = $this->getRRDFileForAS();
|
||||
$this->v6 = $this->addV6Graph();
|
||||
}
|
||||
|
||||
private function getRRDFileForAS(): string
|
||||
{
|
||||
return \sprintf(
|
||||
'%s/%s/%s.rrd',
|
||||
ConfigApplication::getAsStatsConfigGraph()['rrdpath'],
|
||||
\sprintf('%02x', $this->as % 256),
|
||||
$this->as
|
||||
);
|
||||
}
|
||||
|
||||
private function getGraphSize(): array
|
||||
{
|
||||
$width = ConfigApplication::getAsStatsConfigGraph()['default_graph_width'];
|
||||
$height = ConfigApplication::getAsStatsConfigGraph()['default_graph_height'];
|
||||
|
||||
if (isset($this->request['width'])) {
|
||||
$width = (int) $this->request['width'];
|
||||
}
|
||||
|
||||
if (isset($this->request['height'])) {
|
||||
$height = (int) $this->request['height'];
|
||||
}
|
||||
|
||||
return [
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
];
|
||||
}
|
||||
|
||||
private function addV6Graph(): string
|
||||
{
|
||||
if ($this->request['v'] === '6') {
|
||||
return 'v6_';
|
||||
}
|
||||
|
||||
return '';
|
||||
$this->rrdfile = $this->rrdGraph->getRRDFileForAS($as);
|
||||
$this->v6 = $this->rrdGraph->addV6Graph();
|
||||
}
|
||||
|
||||
private function selectedLinks(): array
|
||||
{
|
||||
$knownlinks = KnowlinksRepository::get();
|
||||
|
||||
if (isset($this->request['selected_links']) && $this->request['selected_links'] !== '') {
|
||||
if (isset($this->request['selected_links']) && '' !== $this->request['selected_links']) {
|
||||
$reverse = [];
|
||||
|
||||
foreach ($knownlinks as $link) {
|
||||
@ -99,43 +62,6 @@ class RRDRepository
|
||||
return $knownlinks;
|
||||
}
|
||||
|
||||
private function verticalLabel(): string
|
||||
{
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['vertical_label']) {
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['outispositive']) {
|
||||
return '--vertical-label \'<- IN | OUT ->\' ';
|
||||
}
|
||||
|
||||
return '--vertical-label \'<- OUT | IN ->\' ';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function addLegend(): string
|
||||
{
|
||||
if (isset($this->request['legend']) && $this->request['legend'] === '0') {
|
||||
return '--no-legend ';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function addStartEnd(): string
|
||||
{
|
||||
$cmd = '';
|
||||
|
||||
if (isset($this->request['start']) && is_numeric($this->request['start'])) {
|
||||
$cmd .= \sprintf('--start %s ', $this->request['start']);
|
||||
}
|
||||
|
||||
if (isset($this->request['end']) && is_numeric($this->request['end'])) {
|
||||
$cmd .= \sprintf('--end %s ', $this->request['end']);
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
private function addData(): string
|
||||
{
|
||||
$cmd = '';
|
||||
@ -183,7 +109,7 @@ class RRDRepository
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function generateStackAreaInbound(): string
|
||||
private function generateStackAreaInbound(): string
|
||||
{
|
||||
$cmd = '';
|
||||
$i = 0;
|
||||
@ -194,7 +120,7 @@ class RRDRepository
|
||||
$col = $link['color'];
|
||||
}
|
||||
|
||||
$descr = \str_replace(':', '\:', $link['descr']); # Escaping colons in description
|
||||
$descr = \str_replace(':', '\:', $link['descr']); // Escaping colons in description
|
||||
$cmd .= \sprintf('AREA:%s_%sin_bits#%s:"%s"', $link['tag'], $this->v6, $col, $descr);
|
||||
|
||||
if ($i > 0) {
|
||||
@ -202,13 +128,13 @@ class RRDRepository
|
||||
}
|
||||
|
||||
$cmd .= ' ';
|
||||
$i++;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function generateStackAreaOutbound(): string
|
||||
private function generateStackAreaOutbound(): string
|
||||
{
|
||||
$cmd = '';
|
||||
$i = 0;
|
||||
@ -226,13 +152,13 @@ class RRDRepository
|
||||
}
|
||||
|
||||
$cmd .= ' ';
|
||||
$i++;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function add95th(): string
|
||||
private function add95th(): string
|
||||
{
|
||||
$cmd = '';
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['show95th']) {
|
||||
@ -245,20 +171,9 @@ class RRDRepository
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function addTitle(): string
|
||||
{
|
||||
$cmd = '';
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['showtitledetail'] && isset($this->request['title']) && $this->request['title'] !== '') {
|
||||
$cmd .= \sprintf('--title %s ', \escapeshellarg(\sprintf('%s', $this->request['title'])));
|
||||
} elseif (isset($this->request['v']) && is_numeric($this->request['v'])) {
|
||||
$cmd .= \sprintf('--title IPv%s ', $this->request['v']);
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
public function generateCmd(): string
|
||||
{
|
||||
$graphSize = $this->getGraphSize();
|
||||
$graphSize = $this->rrdGraph->getGraphSize();
|
||||
|
||||
return \sprintf(
|
||||
'%s graph - --slope-mode --alt-autoscale --upper-limit 0 --lower-limit 0 --imgformat=PNG \
|
||||
@ -268,10 +183,10 @@ class RRDRepository
|
||||
ConfigApplication::getAsStatsConfigGraph()['rrdtool'],
|
||||
$graphSize['height'],
|
||||
$graphSize['width'],
|
||||
$this->verticalLabel(),
|
||||
$this->addTitle(),
|
||||
$this->addLegend(),
|
||||
$this->addStartEnd(),
|
||||
$this->rrdGraph->verticalLabel(),
|
||||
$this->rrdGraph->addTitle(),
|
||||
$this->rrdGraph->addLegend(),
|
||||
$this->rrdGraph->addStartEnd(),
|
||||
$this->addData(),
|
||||
$this->generateStackAreaInbound(),
|
||||
$this->generateStackAreaOutbound(),
|
117
src/Repository/RRDLinksUsageRepository.php
Normal file
117
src/Repository/RRDLinksUsageRepository.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Application\ConfigApplication;
|
||||
use App\Util\RRDGraph;
|
||||
|
||||
class RRDLinksUsageRepository
|
||||
{
|
||||
private string $link;
|
||||
private array $request;
|
||||
private array $topas;
|
||||
private array $colors;
|
||||
// private array $knowlinks;
|
||||
// private string $rrdfile;
|
||||
private string $v6;
|
||||
private RRDGraph $rrdGraph;
|
||||
|
||||
public function __construct(string $link, array $req, array $topas)
|
||||
{
|
||||
$this->link = $link;
|
||||
$this->request = $req;
|
||||
$this->topas = $topas;
|
||||
|
||||
//dump($topas);
|
||||
|
||||
$this->rrdGraph = new RRDGraph($this->request);
|
||||
// $this->knowlinks = $this->selectedLinks();
|
||||
// $this->rrdfile = $this->getRRDFileForAS();
|
||||
$this->v6 = $this->rrdGraph->addV6Graph();
|
||||
$this->colors = ConfigApplication::getLinksUsageColor();
|
||||
}
|
||||
|
||||
private function addData(): string
|
||||
{
|
||||
$cmd = '';
|
||||
|
||||
foreach ($this->topas['asinfo'] as $as => $value) {
|
||||
$rrdfile = $this->rrdGraph->getRRDFileForAS($as);
|
||||
$cmd .= \sprintf('DEF:as%1$s_%2$sin="%3$s":%4$s_%2$sin:AVERAGE ', $as, $this->v6, $rrdfile, $this->link);
|
||||
$cmd .= \sprintf('DEF:as%1$s_%2$sout="%3$s":%4$s_%2$sout:AVERAGE ', $as, $this->v6, $rrdfile, $this->link);
|
||||
}
|
||||
|
||||
foreach ($this->topas['asinfo'] as $as => $value) {
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['outispositive']) {
|
||||
$cmd .= \sprintf('CDEF:as%1$s_%2$sin_bits=as%1$s_%2$sin,-8,* ', $as, $this->v6);
|
||||
$cmd .= \sprintf('CDEF:as%1$s_%2$sout_bits=as%1$s_%2$sout,8,* ', $as, $this->v6);
|
||||
} else {
|
||||
$cmd .= \sprintf('CDEF:as%1$s_%2$sin_bits=as%1$s_%2$sin,8,* ', $as, $this->v6);
|
||||
$cmd .= \sprintf('CDEF:as%1$s_%2$sout_bits=as%1$s_%2$sout,-8,* ', $as, $this->v6);
|
||||
}
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
private function generateStackAreaInbound(): string
|
||||
{
|
||||
$cmd = '';
|
||||
$i = 0;
|
||||
|
||||
foreach ($this->topas['asinfo'] as $as => $value) {
|
||||
$descr = \str_replace(':', '\:', $value['info']['description']); // Escaping colons in description
|
||||
$cmd .= \sprintf('AREA:as%1$s_%2$sin_bits#%3$s:"AS%1$s (%4$s)\\n"', $as, $this->v6, $this->colors[$i], $descr);
|
||||
|
||||
if ($i > 0) {
|
||||
$cmd .= ':STACK';
|
||||
}
|
||||
$cmd .= ' ';
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
private function generateStackAreaOutbound(): string
|
||||
{
|
||||
$cmd = '';
|
||||
$i = 0;
|
||||
|
||||
foreach ($this->topas['asinfo'] as $as => $value) {
|
||||
$cmd .= \sprintf('AREA:as%s_%sout_bits#%s:', $as, $this->v6, $this->colors[$i]);
|
||||
|
||||
if ($i > 0) {
|
||||
$cmd .= ':STACK';
|
||||
}
|
||||
$cmd .= ' ';
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function generateCmd(): string
|
||||
{
|
||||
$graphSize = $this->rrdGraph->getGraphSize();
|
||||
|
||||
return \sprintf(
|
||||
'%s graph - --slope-mode --alt-autoscale --upper-limit 0 --lower-limit 0 --imgformat=PNG \
|
||||
--base=1000 --height=%s --width=%s --full-size-mode \
|
||||
--color BACK#ffffff00 --color SHADEA#ffffff00 --color SHADEB#ffffff00 \
|
||||
%s %s %s %s %s %s %s HRULE:0#00000080',
|
||||
ConfigApplication::getAsStatsConfigGraph()['rrdtool'],
|
||||
$graphSize['height'],
|
||||
$graphSize['width'],
|
||||
$this->rrdGraph->verticalLabel(),
|
||||
$this->rrdGraph->addTitle(),
|
||||
$this->rrdGraph->addLegend(),
|
||||
$this->rrdGraph->addStartEnd(),
|
||||
$this->addData(),
|
||||
$this->generateStackAreaInbound(),
|
||||
$this->generateStackAreaOutbound(),
|
||||
);
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ class GenGraphExtension extends AbstractExtension
|
||||
{
|
||||
return [
|
||||
new TwigFunction('gen_graph', [$this, 'genGraph'], ['is_safe' => ['html']]),
|
||||
//new TwigFunction('gen_graph_linkusage', [$this, 'genGraphLinkUsage'], ['is_safe' => ['html']]),
|
||||
];
|
||||
}
|
||||
|
||||
|
105
src/Util/RRDGraph.php
Normal file
105
src/Util/RRDGraph.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Util;
|
||||
|
||||
use App\Application\ConfigApplication;
|
||||
|
||||
final class RRDGraph
|
||||
{
|
||||
private array $request;
|
||||
|
||||
public function __construct(array $req)
|
||||
{
|
||||
$this->request = $req;
|
||||
}
|
||||
|
||||
public function getGraphSize(): array
|
||||
{
|
||||
$width = ConfigApplication::getAsStatsConfigGraph()['default_graph_width'];
|
||||
$height = ConfigApplication::getAsStatsConfigGraph()['default_graph_height'];
|
||||
|
||||
if (isset($this->request['width'])) {
|
||||
$width = (int) $this->request['width'];
|
||||
}
|
||||
|
||||
if (isset($this->request['height'])) {
|
||||
$height = (int) $this->request['height'];
|
||||
}
|
||||
|
||||
return [
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
];
|
||||
}
|
||||
|
||||
public function addV6Graph(): string
|
||||
{
|
||||
if ('6' === $this->request['v']) {
|
||||
return 'v6_';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function addLegend(): string
|
||||
{
|
||||
if (isset($this->request['legend']) && '0' === $this->request['legend']) {
|
||||
return '--no-legend ';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function verticalLabel(): string
|
||||
{
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['vertical_label']) {
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['outispositive']) {
|
||||
return '--vertical-label \'<- IN | OUT ->\' ';
|
||||
}
|
||||
|
||||
return '--vertical-label \'<- OUT | IN ->\' ';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function addStartEnd(): string
|
||||
{
|
||||
$cmd = '';
|
||||
|
||||
if (isset($this->request['start']) && is_numeric($this->request['start'])) {
|
||||
$cmd .= \sprintf('--start %s ', $this->request['start']);
|
||||
}
|
||||
|
||||
if (isset($this->request['end']) && is_numeric($this->request['end'])) {
|
||||
$cmd .= \sprintf('--end %s ', $this->request['end']);
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function addTitle(): string
|
||||
{
|
||||
$cmd = '';
|
||||
|
||||
if (ConfigApplication::getAsStatsConfigGraph()['showtitledetail'] && isset($this->request['title']) && '' !== $this->request['title']) {
|
||||
$cmd .= \sprintf('--title %s ', \escapeshellarg(\sprintf('%s', $this->request['title'])));
|
||||
} elseif (isset($this->request['v']) && is_numeric($this->request['v'])) {
|
||||
$cmd .= \sprintf('--title IPv%s ', $this->request['v']);
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function getRRDFileForAS(int $as): string
|
||||
{
|
||||
return \sprintf(
|
||||
'%s/%s/%s.rrd',
|
||||
ConfigApplication::getAsStatsConfigGraph()['rrdpath'],
|
||||
\sprintf('%02x', $as % 256),
|
||||
$as
|
||||
);
|
||||
}
|
||||
}
|
@ -11,15 +11,7 @@
|
||||
|
||||
<div class="navbar-nav flex-row order-md-last">
|
||||
<div class="my-1 flex-grow-1 flex-md-grow-0 order-first">
|
||||
<!--<form method="get" autocomplete="off" novalidate="">
|
||||
<div class="input-icon">
|
||||
<span class="input-icon-addon">
|
||||
{{ icon('filter') }}
|
||||
</span>
|
||||
<input type="number" name='top' min=1 class="form-control" value="{{ base_data.request.top|default('') }}" placeholder="Top AS">
|
||||
</div>
|
||||
</form>-->
|
||||
{% if form.top is defined %}
|
||||
{% if form.top is defined %}
|
||||
{{ form_start(form.top) }}
|
||||
<div class="input-icon">
|
||||
<span class="input-icon-addon">
|
||||
|
Loading…
x
Reference in New Issue
Block a user