Skip to content

Commit

Permalink
Complete p2p top peers
Browse files Browse the repository at this point in the history
  • Loading branch information
barryo committed Sep 25, 2024
1 parent bf4e8c4 commit 58b1bbb
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 69 deletions.
74 changes: 74 additions & 0 deletions app/Console/Commands/Grapher/PruneDailyP2p.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace IXP\Console\Commands\Grapher;

/*
* Copyright (C) 2009 - 2024 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
*
* IXP Manager 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, version v2.0 of the License.
*
* IXP Manager 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 v2.0
* along with IXP Manager. If not, see:
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/
use Illuminate\Support\Facades\DB;

use IXP\Console\Commands\Command as IXPCommand;

use IXP\Models\{ApiKey, Log, P2pDailyStats, UserLoginHistory, UserRememberToken};

/**
* Prune p2p_daily_stats
*
* @author Barry O'Donovan <[email protected]>
* @package IXP\Console\Commands\Grapher
* @copyright Copyright (C) 2009 - 2024 Internet Neutral Exchange Association Company Limited By Guarantee
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU GPL V2.0
*/
class PruneDailyP2p extends IXPCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'grapher:prune-daily-p2p {--all} {--days=}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Delete --all or records older than --days from p2p_daily_stats';

public function handle()
{
if( $this->option('all') ) {
$before = now();
} else {
if( !$this->option('days') || !is_numeric( $this->option('days') ) ) {
$this->error( 'Please specify if you want to delete --all records or those from more than --days=x ago');
}
$before = now()->subDays( (int)$this->option('days' ) );
}

$cnt = P2pDailyStats::where( 'day', '<', $before->format('Y-m-d') )->delete();

if( $this->isVerbosityVerbose() ) {
$this->info( "Deleted $cnt records older than {$before->format('Y-m-d')}" );
}

return 0;
}
}
7 changes: 3 additions & 4 deletions app/Console/Commands/Grapher/UploadDailyP2p.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
use IXP\Models\Customer;
use IXP\Models\P2pDailyStats;
use IXP\Models\VlanInterface;
use Grapher;
use Log;
use IXP\Support\Facades\Grapher;
use Illuminate\Support\Facades\DB;

use IXP\Services\Grapher\Graph;
Expand Down Expand Up @@ -63,12 +62,12 @@ public function handle(): int
$this->storeStatistics( $stats, $c, $start );

if($this->isVerbosityNormal()) {
Log::debug("Completed {$c->name} in " . (microtime(true) - $iterTime) . " seconds");
$this->info("Completed {$c->name} in " . (microtime(true) - $iterTime) . " seconds");
}
});

if($this->isVerbosityNormal()) {
Log::debug("All Completed in " . (microtime(true) - $startTime) . " seconds");
$this->info("All Completed in " . (microtime(true) - $startTime) . " seconds");
}
return 0;
}
Expand Down
9 changes: 8 additions & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ protected function schedule( Schedule $schedule ): void
$schedule->command( 'grapher:upload-pi-stats-to-db' )->dailyAt( '2:10' )
->skip( function() { return env( 'TASK_SCHEDULER_SKIP_GRAPHER_UPLOAD_STATS_TO_DB', false ); } );

// https://docs.ixpmanager.org/latest/features/peeringdb/#existence-of-peeringdb-records
if( config( 'grapher.backends.sflow.enabled' ) ) {
$schedule->command( 'grapher:prune-daily-p2p --days=30' )->dailyAt( '0:05' );
$schedule->command( 'grapher:upload-daily-p2p ' . now()->subDay()->format( 'Y-m-d' ) )->dailyAt( '0:10' );
}



// https://docs.ixpmanager.org/latest/features/peeringdb/#existence-of-peeringdb-records
$schedule->command('ixp-manager:update-in-peeringdb')->daily()
->skip( function() { return env( 'TASK_SCHEDULER_SKIP_UPDATE_IN_PEERINGDB', false ); } );

Expand Down
4 changes: 3 additions & 1 deletion app/Http/Controllers/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
BillingDetailsRequest
};

use IXP\Models\{Aggregators\RsPrefixAggregator, Customer, CustomerNote, NetworkInfo, User};
use IXP\Models\{Aggregators\RsPrefixAggregator, Customer, CustomerNote, NetworkInfo, P2pDailyStats, User};

use IXP\Utils\View\Alert\{
Alert,
Expand Down Expand Up @@ -134,6 +134,8 @@ public function index( Request $r, string $tab = null ): RedirectResponse|View
'dataNocDetail' => $dataNocDetail,
'countries' => Countries::getList('name' ),
'tab' => strtolower( $tab ) ?: false,
'p2pstats' => P2pDailyStats::latestN( $c ),

]);
}

Expand Down
103 changes: 84 additions & 19 deletions app/Http/Controllers/StatisticsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,11 @@ public function latency( VlanInterface $vli, string $protocol ): View|RedirectRe
*
* @throws ParameterException
*/
public function p2pPrepare( Request $request, Customer $customer ): array
public function p2pPrepare( Request $request, ?Customer $customer, ?VlanInterface $dstVli = null ): array
{
if( !$customer ) {
$customer = Auth::user()->customer;
}

$requestCategory = Graph::processParameterCategory( $request->category, true );
$requestPeriod = Graph::processParameterPeriod( $request->period );
Expand Down Expand Up @@ -562,6 +565,25 @@ public function p2pPrepare( Request $request, Customer $customer ): array
throw new ParameterException("There were no destination interfaces available for traffic exchange for the given criteria." );
}

if( $dstVli ) {
if( $srcVli->vlan->id !== $dstVli->vlan->id ) {
// otherwise, is there an appropriate dstVLi on srcVli->vlan?
foreach( $dstVli->virtualInterface->customer->virtualInterfaces as $vi ) {
foreach( $vi->vlanInterfaces as $vli ) {
if( $vli->vlan->id === $srcVli->vlan->id ) {
$dstVli = $vli;
}
}
}
}

if( $srcVli->vlan->id !== $dstVli->vlan->id ) {
// okay, bounce back to p2p overview page
throw new ParameterException( "No valid destination customer in this peering LAN" );
}
}


return [
'c' => $customer,
'category' => $requestCategory,
Expand All @@ -570,6 +592,7 @@ public function p2pPrepare( Request $request, Customer $customer ): array
'srcVlis' => $srcVlis,
'srcVli' => $srcVli,
'dstVlis' => $dstVlis,
'dstVli' => $dstVli,
];
}

Expand All @@ -585,7 +608,7 @@ public function p2pPrepare( Request $request, Customer $customer ): array
*
* @throws ParameterException
*/
public function p2ps( Request $request, Customer $customer = null ): RedirectResponse|View
public function p2ps( Request $request, ?Customer $customer = null ): RedirectResponse|View
{
try {
$data = $this->p2pPrepare( $request, $customer );
Expand Down Expand Up @@ -642,22 +665,7 @@ public function p2pPost( Request $request ): RedirectResponse|View
$srcVli = VlanInterface::findOrFail($request->svli);
$dstVli = VlanInterface::findOrFail($request->dvli);

if( $srcVli->vlan->id === $dstVli->vlan->id ) {
return $this->p2p( $request, $srcVli, $dstVli );
}

// otherwise, is there an appropriate dstVLi on srcVli->vlan?
foreach( $dstVli->virtualInterface->customer->virtualInterfaces as $vi ) {
foreach( $vi->vlanInterfaces as $vli ) {
if( $vli->vlan->id === $srcVli->vlan->id ) {
return $this->p2p( $request, $srcVli, $vli );
}
}
}

// okay, bounce back to p2p overview page
AlertContainer::push( 'No valid destination customer in this peering LAN', Alert::WARNING );
return redirect( route('statistics@p2ps-get', ['customer' => $srcVli->virtualInterface->custid ] ) );
return $this->p2p( $request, $srcVli, $dstVli );
}

/**
Expand All @@ -672,7 +680,9 @@ public function p2pPost( Request $request ): RedirectResponse|View
public function p2p( Request $request, VlanInterface $srcVli, VlanInterface $dstVli ): RedirectResponse|View
{
try {
$data = $this->p2pPrepare( $request, $srcVli->virtualInterface->customer );
$data = $this->p2pPrepare( $request, $srcVli->virtualInterface->customer, $dstVli );
$srcVli = $data['srcVli'];
$dstVli = $data['dstVli'];
} catch( ParameterException $e ) {
AlertContainer::push( $e->getMessage(), Alert::WARNING );
return redirect()->back();
Expand Down Expand Up @@ -704,6 +714,61 @@ public function p2p( Request $request, VlanInterface $srcVli, VlanInterface $dst
]) );
}



/**
* Show p2p stats for a given customer and day.
*
* @param Request $r
*
* @return \Illuminate\Foundation\Application|\Illuminate\Routing\Redirector|RedirectResponse
*
* @throws
*/
public function p2pTable( Request $r ): View|RedirectResponse
{
if( !Auth::check() ) {
abort( 403, "You are not authorised to view this page." );
}

if( !Auth::user()->isSuperUser() ) {
$r->merge( [ 'custid' => Auth::user()->custid ] );
}

$days = P2pDailyStats::select('day')->distinct('day')->orderBy('day','desc')->get()->pluck('day')->toArray();

if( empty( $days ) ) {
AlertContainer::push( "The P2P daily stats database table is empty.", Alert::WARNING );
return redirect( route('statistics@member', ['cust' => $r->custid ] ) );
}

if( !$r->day || !in_array( $r->day, $days ) ) {
$r->merge( [ 'day' => $days[0] ] );
}

$customers = Customer::currentActive(true,true,true)
->get()->keyBy('id');

$stats = [];
if( $r->custid ) {
$stats = P2pDailyStats::with('peer')
->where('day', $r->day)->where('cust_id', $r->custid )->get();
}

return view( 'statistics/p2p-table' )->with( [
'day' => $r->day,
'days' => $days,
'stats' => $stats,
'customers' => $customers,
'c' => $r->custid ? $customers[$r->custid] : false,
] );
}






/**
* Show daily traffic for customers in a table.
*
Expand Down
39 changes: 39 additions & 0 deletions app/Models/P2pDailyStats.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
*/


use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\DB;
use IXP\Traits\Observable;

Expand Down Expand Up @@ -62,6 +65,7 @@
* @method static \Illuminate\Database\Eloquent\Builder|P2pDailyStats whereIpv6TotalOut($value)
* @method static \Illuminate\Database\Eloquent\Builder|P2pDailyStats wherePeerId($value)
* @method static \Illuminate\Database\Eloquent\Builder|P2pDailyStats whereUpdatedAt($value)
* @property-read \IXP\Models\Customer|null $peer
* @mixin \Eloquent
*/
class P2pDailyStats extends Model
Expand Down Expand Up @@ -94,6 +98,23 @@ class P2pDailyStats extends Model
'ipv6_max_out',
];

/**
* Get the logo for the customer
*/
public function peer(): HasOne
{
return $this->hasOne(Customer::class, 'id', 'peer_id' );
}

/**
* Accessor for total traffic
*/
public function total_traffic(): int
{
return $this->ipv4_total_out + $this->ipv4_total_in + $this->ipv6_total_out + $this->ipv6_total_in;
}



/**
* Get the total traffic a customer exchanges with its peers for the latest day in the database.
Expand All @@ -115,5 +136,23 @@ public static function latestTotalTraffic( Customer $c ): array
->get()->pluck('total_traffic', 'peer_id')->toArray();
}

/**
* Get the latest n P2pDailyStats for this customer.
*
* @param Customer $c
* @return P2pDailyStats[]
*/
public static function latestN( Customer $c, int $n = 5 ): Collection
{
// latest day for which we have results
if( !( $day = self::whereCustId( $c->id )->max('day') ) ) {
return [];
}

return self::select( DB::raw( '*, ipv6_total_out + ipv4_total_out + ipv6_total_in + ipv4_total_in as total_traffic' ) )
->where( 'cust_id', $c->id )->where( 'day', $day)
->limit( $n )->orderBy( 'total_traffic', 'desc' )->get();
}


}
Loading

0 comments on commit 58b1bbb

Please sign in to comment.