mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-24 06:28:27 +01:00
Added conditional notifications
- Absolute values - Percentage threshold
This commit is contained in:
@@ -10,6 +10,7 @@ use Illuminate\Support\Facades\File;
|
|||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use InvalidArgumentException;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
|
|
||||||
class SpeedtestHelper {
|
class SpeedtestHelper {
|
||||||
@@ -301,4 +302,77 @@ class SpeedtestHelper {
|
|||||||
'msg' => 'There was an error backing up the database. No speedtests have been deleted.'
|
'msg' => 'There was an error backing up the database. No speedtests have been deleted.'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work out if a test is lower than the threshold for historic tests
|
||||||
|
*
|
||||||
|
* @param String $type
|
||||||
|
* @param Speedtest $test
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function testIsLowerThanThreshold(String $type, Speedtest $test)
|
||||||
|
{
|
||||||
|
if($type == 'percentage') {
|
||||||
|
$avg = Speedtest::select(DB::raw('AVG(ping) as ping, AVG(download) as download, AVG(upload) as upload'))
|
||||||
|
->where('failed', false)
|
||||||
|
->get()
|
||||||
|
->toArray()[0];
|
||||||
|
|
||||||
|
$threshold = SettingsHelper::get('threshold_alert_percentage')->value;
|
||||||
|
|
||||||
|
if($threshold == '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
foreach($avg as $key => $value) {
|
||||||
|
if($key == 'ping') {
|
||||||
|
$threshold = (float)$value * (1 + ( $threshold / 100 ));
|
||||||
|
|
||||||
|
if($test->$key > $threshold) {
|
||||||
|
array_push($errors, $key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$threshold = (float)$value * (1 - ( $threshold / 100 ));
|
||||||
|
|
||||||
|
if($test->$key < $threshold) {
|
||||||
|
array_push($errors, $key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($type == 'absolute') {
|
||||||
|
$thresholds = [
|
||||||
|
'download' => SettingsHelper::get('threshold_alert_absolute_download')->value,
|
||||||
|
'upload' => SettingsHelper::get('threshold_alert_absolute_upload')->value,
|
||||||
|
'ping' => SettingsHelper::get('threshold_alert_absolute_ping')->value,
|
||||||
|
];
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
foreach($thresholds as $key => $value) {
|
||||||
|
if($value == '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($key == 'ping') {
|
||||||
|
if($test->$key > $value) {
|
||||||
|
array_push($errors, $key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if($test->$key < $value) {
|
||||||
|
array_push($errors, $key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@
|
|||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
use App\Helpers\SettingsHelper;
|
use App\Helpers\SettingsHelper;
|
||||||
|
use App\Helpers\SpeedtestHelper;
|
||||||
|
use App\Notifications\SpeedtestAbsoluteThresholdNotificationSlack;
|
||||||
use App\Notifications\SpeedtestCompleteSlack;
|
use App\Notifications\SpeedtestCompleteSlack;
|
||||||
use App\Notifications\SpeedtestCompleteTelegram;
|
use App\Notifications\SpeedtestCompleteTelegram;
|
||||||
|
use App\Notifications\SpeedtestPercentageThresholdNotificationSlack;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
@@ -32,9 +35,40 @@ class SpeedtestCompleteListener
|
|||||||
*/
|
*/
|
||||||
public function handle($event)
|
public function handle($event)
|
||||||
{
|
{
|
||||||
|
Log::info('handling event');
|
||||||
|
Log::info(SettingsHelper::get('threshold_alert_percentage_notifications')->value);
|
||||||
|
if((bool)SettingsHelper::get('threshold_alert_percentage_notifications')->value == true) {
|
||||||
|
$data = $event->speedtest;
|
||||||
|
$errors = SpeedtestHelper::testIsLowerThanThreshold('percentage', $data);
|
||||||
|
if(sizeof($errors) > 0) {
|
||||||
|
try {
|
||||||
|
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
|
||||||
|
->notify(new SpeedtestPercentageThresholdNotificationSlack($errors));
|
||||||
|
} catch(Exception $e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((bool)SettingsHelper::get('threshold_alert_absolute_notifications')->value == true) {
|
||||||
|
$data = $event->speedtest;
|
||||||
|
Log::info('absolute nots enabled');
|
||||||
|
Log::info($data);
|
||||||
|
$errors = SpeedtestHelper::testIsLowerThanThreshold('absolute', $data);
|
||||||
|
Log::info($errors);
|
||||||
|
if(sizeof($errors) > 0) {
|
||||||
|
try {
|
||||||
|
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
|
||||||
|
->notify(new SpeedtestAbsoluteThresholdNotificationSlack($errors));
|
||||||
|
} catch(Exception $e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(SettingsHelper::get('speedtest_notifications')->value == true) {
|
if(SettingsHelper::get('speedtest_notifications')->value == true) {
|
||||||
$data = $event->speedtest;
|
$data = $event->speedtest;
|
||||||
if(SettingsHelper::get('slack_webhook')) {
|
if(SettingsHelper::get('slack_webhook')->value) {
|
||||||
try {
|
try {
|
||||||
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
|
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
|
||||||
->notify(new SpeedtestCompleteSlack($data));
|
->notify(new SpeedtestCompleteSlack($data));
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class SpeedtestAbsoluteThresholdNotificationSlack extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
protected $errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @param array $errors
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(array $errors)
|
||||||
|
{
|
||||||
|
$this->errors = $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['slack'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format slack notification
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return SlackMessage
|
||||||
|
*/
|
||||||
|
public function toSlack($notifiable)
|
||||||
|
{
|
||||||
|
return (new SlackMessage)
|
||||||
|
->warning()
|
||||||
|
->attachment(function ($attachment) {
|
||||||
|
$attachment->title('Speedtest absolute threshold error')
|
||||||
|
->content($this->formatMessage());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse $this->errors and format message
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public function formatMessage()
|
||||||
|
{
|
||||||
|
$msg = 'For the latest speedtest, the ';
|
||||||
|
|
||||||
|
for($i = 0; $i < sizeof($this->errors); $i++) {
|
||||||
|
$key = $this->errors[$i];
|
||||||
|
$msg = $msg . $key;
|
||||||
|
if(sizeof($this->errors) > 1 && $i < (sizeof($this->errors) - 1)) {
|
||||||
|
$msg = $msg . ', ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($msg[-1] != '') {
|
||||||
|
$msg = $msg . ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sizeof($this->errors) > 1) {
|
||||||
|
$msg = $msg . 'values ';
|
||||||
|
} else {
|
||||||
|
$msg = $msg . 'value ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = $msg . 'exceeded the absolute threshold';
|
||||||
|
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class SpeedtestPercentageThresholdNotificationSlack extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
protected $errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @param array $errors
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(array $errors)
|
||||||
|
{
|
||||||
|
$this->errors = $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['slack'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format slack notification
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return SlackMessage
|
||||||
|
*/
|
||||||
|
public function toSlack($notifiable)
|
||||||
|
{
|
||||||
|
return (new SlackMessage)
|
||||||
|
->warning()
|
||||||
|
->attachment(function ($attachment) {
|
||||||
|
$attachment->title('Speedtest percentage threshold error')
|
||||||
|
->content($this->formatMessage());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse $this->errors and format message
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public function formatMessage()
|
||||||
|
{
|
||||||
|
$msg = 'For the latest speedtest, the ';
|
||||||
|
|
||||||
|
for($i = 0; $i < sizeof($this->errors); $i++) {
|
||||||
|
$key = $this->errors[$i];
|
||||||
|
$msg = $msg . $key;
|
||||||
|
if(sizeof($this->errors) > 1 && $i < (sizeof($this->errors) - 1)) {
|
||||||
|
$msg = $msg . ', ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($msg[-1] != '') {
|
||||||
|
$msg = $msg . ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sizeof($this->errors) > 1) {
|
||||||
|
$msg = $msg . 'values ';
|
||||||
|
} else {
|
||||||
|
$msg = $msg . 'value ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = $msg . 'exceeded the percentage threshold';
|
||||||
|
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Helpers\SettingsHelper;
|
||||||
|
use App\Setting;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddConditionalNotificationsSettings extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if(!SettingsHelper::get('threshold_alert_percentage_notifications')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_percentage_notifications',
|
||||||
|
'value' => false,
|
||||||
|
'description' => 'Enable/disable theshold percentage notifications'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SettingsHelper::get('threshold_alert_percentage')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_percentage',
|
||||||
|
'value' => 15,
|
||||||
|
'description' => 'When any value of a speedtest is x percent lower than the average, a notification will be sent.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SettingsHelper::get('threshold_alert_absolute_notifications')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_absolute_notifications',
|
||||||
|
'value' => false,
|
||||||
|
'description' => 'Enable/disable absolute theshold notifications'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SettingsHelper::get('threshold_alert_absolute_download')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_absolute_download',
|
||||||
|
'value' => '',
|
||||||
|
'description' => 'When the download is lower than this value, a notification will be sent. Leave blank to disable'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SettingsHelper::get('threshold_alert_absolute_upload')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_absolute_upload',
|
||||||
|
'value' => '',
|
||||||
|
'description' => 'When the upload is lower than this value, a notification will be sent. Leave blank to disable'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SettingsHelper::get('threshold_alert_absolute_ping')) {
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'threshold_alert_absolute_ping',
|
||||||
|
'value' => '',
|
||||||
|
'description' => 'When the ping is higher than this value, a notification will be sent. Leave blank to disable'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Setting::whereIn('name', [
|
||||||
|
'threshold_alert_percentage',
|
||||||
|
'threshold_alert_absolute_download',
|
||||||
|
'threshold_alert_absolute_upload',
|
||||||
|
'threshold_alert_absolute_ping',
|
||||||
|
'threshold_alert_percentage_notifications',
|
||||||
|
'threshold_alert_absolute_notifications'
|
||||||
|
])->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
resources/js/components/Settings/Settings.js
vendored
37
resources/js/components/Settings/Settings.js
vendored
@@ -158,6 +158,43 @@ export default class Settings extends Component {
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 23
|
max: 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: {
|
||||||
|
id: (Math.floor(Math.random() * 10000) + 1),
|
||||||
|
name: "Conditional Notifications",
|
||||||
|
description: ""
|
||||||
|
},
|
||||||
|
type: 'group',
|
||||||
|
children: [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_percentage_notifications,
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_percentage,
|
||||||
|
type: 'number',
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_absolute_notifications,
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_absolute_download,
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_absolute_upload,
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.threshold_alert_absolute_ping,
|
||||||
|
type: 'number',
|
||||||
}
|
}
|
||||||
]} />
|
]} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
Reference in New Issue
Block a user