mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Use Measurements for all statistic collection (#13333)
* Use Measurements for all statistic collection * fix space * Use colors cleanup * fix style * manually fix license notice * add return times and new line * add return times and new line * fix mistake in copyright template * fix style
This commit is contained in:
92
app/Polling/Measure/Measurement.php
Normal file
92
app/Polling/Measure/Measurement.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Measurement.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Polling\Measure;
|
||||
|
||||
class Measurement
|
||||
{
|
||||
private $start;
|
||||
private $type;
|
||||
private $duration;
|
||||
|
||||
private function __construct(string $type, float $duration = null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->start = microtime(true);
|
||||
if ($duration !== null) {
|
||||
$this->duration = $duration;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a measurement with an existing duration
|
||||
*/
|
||||
public static function make(string $type, float $duration): Measurement
|
||||
{
|
||||
return new static($type, $duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the timer for a new operation
|
||||
*
|
||||
* @param string $type
|
||||
* @return static
|
||||
*/
|
||||
public static function start(string $type): Measurement
|
||||
{
|
||||
return new static($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* End the timer for this operation
|
||||
*/
|
||||
public function end(): Measurement
|
||||
{
|
||||
$this->duration = microtime(true) - $this->start;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the operation
|
||||
*/
|
||||
public function getDuration(): float
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the operation
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function manager(): MeasurementManager
|
||||
{
|
||||
return app(MeasurementManager::class);
|
||||
}
|
||||
}
|
85
app/Polling/Measure/MeasurementCollection.php
Normal file
85
app/Polling/Measure/MeasurementCollection.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* MeasurementCollection.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Polling\Measure;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class MeasurementCollection extends Collection
|
||||
{
|
||||
public function getTotalCount(): int
|
||||
{
|
||||
return $this->sumStat('getCount');
|
||||
}
|
||||
|
||||
public function getTotalDuration(): float
|
||||
{
|
||||
return $this->sumStat('getDuration');
|
||||
}
|
||||
|
||||
public function getCountDiff(): int
|
||||
{
|
||||
return $this->sumStat('getCountDiff');
|
||||
}
|
||||
|
||||
public function getDurationDiff(): float
|
||||
{
|
||||
return $this->sumStat('getDurationDiff');
|
||||
}
|
||||
|
||||
public function checkpoint(): void
|
||||
{
|
||||
$this->each->checkpoint();
|
||||
}
|
||||
|
||||
public function record(Measurement $measurement): void
|
||||
{
|
||||
$type = $measurement->getType();
|
||||
|
||||
if (! $this->has($type)) {
|
||||
$this->put($type, new MeasurementSummary($type));
|
||||
}
|
||||
|
||||
$this->get($type)->add($measurement);
|
||||
}
|
||||
|
||||
public function getSummary(string $type): MeasurementSummary
|
||||
{
|
||||
return $this->get($type, new MeasurementSummary($type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method method on measurement class to call
|
||||
* @return int|float
|
||||
*/
|
||||
private function sumStat(string $method)
|
||||
{
|
||||
return $this->reduce(function ($sum, $measurement) use ($method) {
|
||||
$sum += $measurement->$method();
|
||||
|
||||
return $sum;
|
||||
}, 0);
|
||||
}
|
||||
}
|
142
app/Polling/Measure/MeasurementManager.php
Normal file
142
app/Polling/Measure/MeasurementManager.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* MeasurementManager.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Polling\Measure;
|
||||
|
||||
use DB;
|
||||
use Illuminate\Database\Events\QueryExecuted;
|
||||
|
||||
class MeasurementManager
|
||||
{
|
||||
const SNMP_COLOR = "\e[0;36m";
|
||||
const DB_COLOR = "\e[1;33m";
|
||||
const DATASTORE_COLOR = "\e[0;32m";
|
||||
const NO_COLOR = "\e[0m";
|
||||
|
||||
/**
|
||||
* @var MeasurementCollection
|
||||
*/
|
||||
private static $snmp;
|
||||
|
||||
/**
|
||||
* @var MeasurementCollection
|
||||
*/
|
||||
private static $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (self::$snmp === null) {
|
||||
self::$snmp = new MeasurementCollection();
|
||||
self::$db = new MeasurementCollection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register DB listener to record sql query stats
|
||||
*/
|
||||
public function listenDb(): void
|
||||
{
|
||||
DB::listen(function (QueryExecuted $event) {
|
||||
$type = strtolower(substr($event->sql, 0, strpos($event->sql, ' ')));
|
||||
$this->recordDb(Measurement::make($type, $event->time ? $event->time / 100 : 0));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update statistics for db operations
|
||||
*/
|
||||
public function recordDb(Measurement $measurement): void
|
||||
{
|
||||
self::$db->record($measurement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the stats totals since the last checkpoint
|
||||
*/
|
||||
public function printChangedStats(): void
|
||||
{
|
||||
printf(
|
||||
'>> %sSNMP%s: [%d/%.2fs] %sMySQL%s: [%d/%.2fs]',
|
||||
self::SNMP_COLOR,
|
||||
self::NO_COLOR,
|
||||
self::$snmp->getCountDiff(),
|
||||
self::$snmp->getDurationDiff(),
|
||||
self::DB_COLOR,
|
||||
self::NO_COLOR,
|
||||
self::$db->getCountDiff(),
|
||||
self::$db->getDurationDiff()
|
||||
);
|
||||
|
||||
app('Datastore')->getStats()->each(function (MeasurementCollection $stats, $datastore) {
|
||||
printf(' %s%s%s: [%d/%.2fs]', self::DATASTORE_COLOR, $datastore, self::NO_COLOR, $stats->getCountDiff(), $stats->getDurationDiff());
|
||||
});
|
||||
|
||||
$this->checkpoint();
|
||||
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new checkpoint so to compare against
|
||||
*/
|
||||
public function checkpoint(): void
|
||||
{
|
||||
self::$snmp->checkpoint();
|
||||
self::$db->checkpoint();
|
||||
app('Datastore')->getStats()->each->checkpoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a measurement for snmp
|
||||
*/
|
||||
public function recordSnmp(Measurement $measurement): void
|
||||
{
|
||||
self::$snmp->record($measurement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print global stat arrays
|
||||
*/
|
||||
public function printStats(): void
|
||||
{
|
||||
$this->printSummary('SNMP', self::$snmp, self::SNMP_COLOR);
|
||||
$this->printSummary('SQL', self::$db, self::DB_COLOR);
|
||||
|
||||
app('Datastore')->getStats()->each(function (MeasurementCollection $stats, string $datastore) {
|
||||
$this->printSummary($datastore, $stats, self::DATASTORE_COLOR);
|
||||
});
|
||||
}
|
||||
|
||||
private function printSummary(string $name, MeasurementCollection $collection, string $color = ''): void
|
||||
{
|
||||
printf('%s%s%s [%d/%.2fs]:', $color, $name, $color ? self::NO_COLOR : '', $collection->getTotalCount(), $collection->getTotalDuration());
|
||||
|
||||
$collection->each(function (MeasurementSummary $stat) {
|
||||
printf(' %s[%d/%.2fs]', ucfirst($stat->getType()), $stat->getCount(), $stat->getDuration());
|
||||
});
|
||||
|
||||
echo PHP_EOL;
|
||||
}
|
||||
}
|
93
app/Polling/Measure/MeasurementSummary.php
Normal file
93
app/Polling/Measure/MeasurementSummary.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* MeasurementSummary.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Polling\Measure;
|
||||
|
||||
class MeasurementSummary
|
||||
{
|
||||
private $type;
|
||||
private $count = 0;
|
||||
private $duration = 0.0;
|
||||
|
||||
private $checkpointCount = 0;
|
||||
private $checkpointDuration = 0.0;
|
||||
|
||||
public function __construct(string $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function add(Measurement $measurement): void
|
||||
{
|
||||
$this->count++;
|
||||
$this->duration += $measurement->getDuration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the measurement summary
|
||||
* ['count' => #, 'duration' => s]
|
||||
*/
|
||||
public function get(): array
|
||||
{
|
||||
return [
|
||||
'count' => $this->count,
|
||||
'duration' => $this->duration,
|
||||
];
|
||||
}
|
||||
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getDuration(): float
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new checkpoint to compare against with diff methods
|
||||
*/
|
||||
public function checkpoint(): void
|
||||
{
|
||||
$this->checkpointCount = $this->count;
|
||||
$this->checkpointDuration = $this->duration;
|
||||
}
|
||||
|
||||
public function getCountDiff(): int
|
||||
{
|
||||
return $this->count - $this->checkpointCount;
|
||||
}
|
||||
|
||||
public function getDurationDiff(): float
|
||||
{
|
||||
return $this->duration - $this->checkpointDuration;
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Sensor;
|
||||
use App\Polling\Measure\MeasurementManager;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -38,8 +39,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(MeasurementManager $measure)
|
||||
{
|
||||
$measure->listenDb();
|
||||
\Illuminate\Pagination\Paginator::useBootstrap();
|
||||
|
||||
$this->app->booted('\LibreNMS\DB\Eloquent::initLegacyListeners');
|
||||
|
Reference in New Issue
Block a user