Web监控工具:不断发送通知

时间:2016-12-16 10:44:27

标签: php laravel

我开发了一个网络监控工具。它应该检查网站的状态代码,并决定它是向上还是向下。如果响应代码是200,它将保存得很好,它在数据库中保存为up,否则为down。如果状态代码发生变化,则应该发送更多通知,即从上到下或反之,(它使用保存在数据库中的最后一个状态代码检查新的resCode(响应代码))。但如果网站总是在运行,请不要发送通知。但如果网站关闭,请检查警报频率并发送通知。 sendNotification函数对此负责,但由于某种原因并收到通知的垃圾邮件。它只是在不检查警报频率和状态变化的情况下继续发送通知。任何可以查看我的代码的人。 tnx提前。

 <?php
namespace App\Http\Controllers;

use \GuzzleHttp\Client;
use App\Utilities\Reporter;
use GuzzleHttp\Exception\ClientException;
use App\Notification;
use App\Status;
use App\Setting;
use Carbon;
class GuzzleController extends Controller
{
    private $default_check_frequency;

    protected $client;

    protected $reporter;

    public function __construct()
    {
        $this->client = new Client();

        $this->reporter = new Reporter;

        $this->default_check_frequency = Setting::defaultCheckFrequency();


    }

    private function addStatusToNotification(Notification $notification, Status $status, $resCode)
    {
        $notification->statuses()->attach($status, [
            'values' => $resCode === 200
            ? 'up'
            : 'down'
            ]);
    }

    private function report(Notification $notification, $resCode)
    {
       if(empty($resCode)){
            $resCode = "no response found";
        }
        if($resCode <> 200){
                $this->reporter->slack($notification->website_url . ':' . '  is down' . ' this is the status code!' . ' @- ' .$resCode,
                        $notification->slack_channel);

                $this->reporter->mail($notification->email,$notification->website_url.' is down '. ' this is the status Code: '. $resCode);

        }else{
                $this->reporter->slack($notification->website_url . ':' . '  is up' . ' this is the status code!' . ' @- ' .$resCode,
                        $notification->slack_channel);
        }
    }

    private function sendNotification(Notification $notification, Status $status, $status_health, $frequency, $resCode)
    {
        $elapsed_time = \Carbon\Carbon::parse($status_health['timestamp'])->diffInMinutes();

        if ($elapsed_time >= $frequency) {

            $this->addStatusToNotification($notification, $status, $resCode);
        } 
        if ($resCode === 200){

            if($resCode <> $status_health['value']){
                var_dump($status_health['value']);
                die();
                $this->report($notification, $resCode);

            }
        }else{
            if($resCode === $status_health['value'] && $elapsed_time >= $notification->alert_frequency){
                $this->report($notification, $resCode);

            }
        }
    }


    public function status()
    {
        $notifications = Notification::where('active', 1)->get();

        $status = Status::where('name', 'health')->first();

        foreach ($notifications as $notification) {
            $this->updateStatus($notification, $status);
        }
    }

    private function updateStatus(Notification $notification, Status $status)
    {
        $resCode = $this->getStatusCode($notification->website_url);

        $this->sendNotification(
            $notification,
            $status,
            $notification->status('health'),
            $this->getFrequency($notification,$resCode),
            $resCode
            );
    }

    private function getFrequency(Notification $notification) 
    {           

            return isset($notification->check_frequency)
            ? intval($notification->check_frequency)
            : $this->default_check_frequency;                
    }

    private function getStatusCode($url)
    {
        try {
            $response = $this->client->get($url, [
                'http_errors' => false
                ]);
            return $response->getStatusCode();  
        } catch (\GuzzleHttp\Exception\ConnectException $e) {

        }
    }
}

这实际上是我从数据库中获取status_health,模型,从上到下的地方

<?php

namespace App;
use App\Status;
use App\Notification;

use Illuminate\Database\Eloquent\Model;

class Notification extends Model
{
    protected $fillable = ['id','website_url','email','slack_channel','check_frequency','alert_frequency','speed_frequency','active'];

    public function statuses(){
        return $this->belongsToMany('App\Status')->withPivot('values')->withTimestamps();
    }

    public function status($s_type)
    {
        if (!in_array($s_type, ['speed', 'health'])){
            return false;
        }

        $o_status = Status::where('name', strval($s_type))->first();
        $o_response = $this->statuses()->where('status_id', $o_status->id)
        ->select('values', 'created_at')->orderBy('created_at','DESC')->first();

        if($o_response === null){
            return false;
        }

        return [
            'value' => $o_response->values,
            'timestamp' => $o_response->created_at
        ];
    }

    public function history($s_type)
    {
        if (!in_array($s_type, ['speed', 'health'])){
            return false;
        }

        $o_status = Status::where('name', strval($s_type))->first();
        $o_response = $this->statuses()->where('status_id', $o_status->id)
        ->select('values', 'created_at')->orderBy('created_at','DESC')->get();

        if($o_response === null || $o_response->count() === 0){
            return false;
        }


        $a_ret = [];
        $last = null;

        foreach ($o_response as $o_status) {
            if($last != $o_status->values) {
                $a_ret[] = [
                'value' => $o_status->values,
                'timestamp' => $o_status->created_at
                ];
                $last = $o_status->values;
            }
        }
        return $a_ret;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以将状态保存到数据库,如果您从上次检查获得的状态与保存到数据库的状态不同,则可以发送通知并更新de数据库中的状态。

使用此方法,只有在状态发生变化时才会发送通知,而不是每次检查状态时都会发送通知。

如果您使用保存在数据库中的最新支票核对function(aa, bb, Overlaps) ,您可以进行比较并考虑发送通知。

当您调用将发送新状态的功能时,您可以检查status_code!= status_code

希望这有效!

答案 1 :(得分:0)

经过大量调试后我得到了答案。问题不在于代码本身。来自http请求的响应代码是一个数字例外字符串200,404等,然后它被保存为字符串值为&#34; up&#34;或&#34; down&#34;。当我使用比较resCode(响应代码)和status_health [&#39;值&#39;](我从数据库获得的值是一个字符串&#34; up&#34;或&#34; down&# 34;。我实际上是在比较字符串和int值。然后我将resCode更改为字符串,我的问题得到修复.sendNotification函数中的代码得到了改进.Tnx适用于所有试图帮助@Robin Dirksen的人。这里是新代码

<?php
namespace App\Http\Controllers;

use \GuzzleHttp\Client;
use App\Utilities\Reporter;
use GuzzleHttp\Exception\ClientException;
use App\Notification;
use App\Status;
use App\Setting;
use Carbon;
class GuzzleController extends Controller
{
    private $default_check_frequency;

    protected $client;

    protected $reporter;

    public function __construct()
    {
        $this->client = new Client();

        $this->reporter = new Reporter;

        $this->default_check_frequency = Setting::defaultCheckFrequency();


    }

    private function addStatusToNotification(Notification $notification, Status $status, $resCode)
    {
        $notification->statuses()->attach($status, [
            'values' => $resCode === 200
            ? 'up'
            : 'down'
            ]);
    }

    private function report(Notification $notification, $resCode)
    {
       if(empty($resCode)){
            $resCode = "no response found";
        }
        if($resCode <> 200){
                $this->reporter->slack($notification->website_url . ':' . '  is down' . ' this is the status code!' . ' @- ' .$resCode,
                        $notification->slack_channel);

                $this->reporter->mail($notification->email,$notification->website_url.' is down '. ' this is the status Code: '. $resCode);

        }else{
                $this->reporter->slack($notification->website_url . ':' . '  is up' . ' this is the status code!' . ' @- ' .$resCode,
                        $notification->slack_channel);
        }
    }

    private function sendNotification(Notification $notification, Status $status, $status_health, $frequency, $resCode)
    {
        $elapsed_time = \Carbon\Carbon::parse($status_health['timestamp'])->diffInMinutes();

        if ($elapsed_time >= $frequency) {

            $this->addStatusToNotification($notification, $status, $resCode);
        }

        if ($resCode === 200){
            $resCode ='up';
            if($resCode <> $status_health['value']){               
                $this->report($notification, $resCode);               
            }
        }else{
            $resCode ='down';
            if($resCode <> $status_health['value'] ){
                $this->report($notification, $resCode);
            }else{
                if($elapsed_time >= $notification->alert_frequency){
                     $this->report($notification, $resCode);
                }
            }

                /*if($elapsed_time >= $notification->alert_frequency){*/

               /* }*/               

        }
    }


    public function status()
    {
        $notifications = Notification::where('active', 1)->get();

        $status = Status::where('name', 'health')->first();

        foreach ($notifications as $notification) {
            $this->updateStatus($notification, $status);
        }
    }

    private function updateStatus(Notification $notification, Status $status)
    {
        $resCode = $this->getStatusCode($notification->website_url);

        $this->sendNotification(
            $notification,
            $status,
            $notification->status('health'),
            $this->getFrequency($notification,$resCode),
            $resCode
            );
    }

    private function getFrequency(Notification $notification) 
    {           

            return isset($notification->check_frequency)
            ? intval($notification->check_frequency)
            : $this->default_check_frequency;                
    }

    private function getStatusCode($url)
    {
        try {
            $response = $this->client->get($url, [
                'http_errors' => false
                ]);
            return $response->getStatusCode();  
        } catch (\GuzzleHttp\Exception\ConnectException $e) {

        }
    }
}