Skip to content

Commit

Permalink
πŸ”¨ WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
OwenMelbz committed Aug 18, 2019
1 parent da9ae81 commit d39c716
Show file tree
Hide file tree
Showing 19 changed files with 639 additions and 154 deletions.
68 changes: 68 additions & 0 deletions app/Checkers/Uptime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace App\Checkers;

use App\RobotScan;
use App\UptimeScan;
use GuzzleHttp\Client;
use App\Website;
use GuzzleHttp\TransferStats;
use Illuminate\Support\Str;
use SebastianBergmann\Diff\Differ;


class Uptime
{
private $website;

public function __construct(Website $website)
{
$this->website = $website;
}

public function run()
{
$this->fetch();
// $this->compare();
}

private function fetch()
{
$client = new Client();

$response_time = 3001;

$response = $client->request('GET', $this->website->url, [
'on_stats' => function ($stats) use (&$response_time) {
$response_time = $stats->getTransferTime();
},
'verify' => false,
'allow_redirects' => true,
'headers' => [
'User-Agent' => 'Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.uptimerobot.com/; Odin)'
],
]);

$scan = new UptimeScan([
'response_status' => sprintf('%s (%d)', $response->getReasonPhrase(), $response->getStatusCode()),
'response_time' => $response_time,
'was_online' => Str::contains($response->getBody(), $this->website->uptime_keyword)
]);

$this->website->uptimes()->save($scan);
}

private function compare()
{
$scans = $this->website->last_robot_scans;

if ($scans->isEmpty() || $scans->count() === 1) {
return;
}

$diff = (new Differ)->diff($scans->last()->txt, $scans->first()->txt);

$scans->first()->diff = $diff;
$scans->first()->save();
}
}
48 changes: 48 additions & 0 deletions app/Console/Commands/UptimeCheckCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Console\Commands;

use App\Jobs\UptimeCheck;
use App\Website;
use Illuminate\Console\Command;

class UptimeCheckCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'check:uptime {website}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$websiteId = $this->argument('website');

UptimeCheck::dispatchNow(
Website::findOrFail($websiteId)
);
}
}
25 changes: 25 additions & 0 deletions app/HasRobots.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php


namespace App;


trait HasRobots
{

public function robots()
{
return $this->hasMany(RobotScan::class);
}

public function getLastRobotScansAttribute()
{
return $this->robots()->orderBy('created_at', 'desc')->take(2)->get();
}

public function getRobotsUrlAttribute()
{
return $this->url . '/robots.txt';
}

}
141 changes: 141 additions & 0 deletions app/HasUptime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php


namespace App;


use Illuminate\Support\Collection;

trait HasUptime
{
public function uptimes()
{
return $this->hasMany(UptimeScan::class)->orderBy('created_at', 'desc');
}

public function getRecentEventsAttribute()
{
return $this->uptimes->sortByDesc('created_at')->take(10);
}

public function getLastIncidentAttribute()
{
$event = $this->uptimes
->where('was_online', 0)
->sortByDesc('created_at')
->first();

if (!$event) {
return 'No downtime recorded';
}

$downtime = 'xxx';
$when = $event->created_at->format('D jS M "y @ h:ia');

return sprintf('Was down for %s on %s', $downtime, $when);

return 'Will update later';
}

public function getCurrentStateAttribute()
{
$event = $this->uptimes->sortByDesc('created_at')->first();

if (!$event) {
return true;
}

return $event->was_online;
}

public function getUptimeAttribute()
{
$latest = $this->uptimes->sortByDesc('created_at')->first();
$online = $this->uptimes->firstWhere('was_online', 1);
$offline = $this->uptimes->firstWhere('was_online', 0);

if (!$latest) {
return 'Still collecting data...';
}

if ($latest->offline) {
if ($offline && $online) {
return now()->diffAsCarbonInterval($online->created_at)->forHumans(['join' => true]);
}

return 'Site never previously recorded as online.';
}

if (!$offline) {
return now()->diffAsCarbonInterval($online->created_at)->forHumans(['join' => true]);
}

return $offline->created_at->diffAsCarbonInterval(now())->forHumans(['join' => true]);
}

public function getResponseTimesAttribute()
{
return $this->uptimes
->sortByDesc('created_at')
->take(25)
->transform(function (UptimeScan $scan) {
return [
'date' => $scan->created_at,
'value' => $scan->response_time,
];
})
->values();
}

public function getResponseTimeAttribute()
{
$time = $this->response_times->first();

if (!$time) {
return '-';
}

return $time['value'];
}

public function getUptimeSummaryAttribute()
{
/* @var Collection $events */
$events = $this->uptimes;

$upCount = $events->where('was_online', 1);
$totalPercentage = ($upCount->count() * 100) / $events->count();

$today = now();
$lastWeek = now()->subDays(7);
$lastMonth = now()->subDays(30);

$todayEvents = $events->filter(function ($item) use ($today) {
return $item->created_at->format('d/m/y') === $today->format('d/m/y');
});

$todayUpEvents = $todayEvents->where('was_online', 1);
$todayPercentage = ($todayUpEvents->count() * 100) / $todayEvents->count();

$weeklyEvents = $events->filter(function ($item) use ($lastWeek, $today) {
return $item->created_at->isBetween($lastWeek, $today);
});

$weeklyUpEvents = $weeklyEvents->where('was_online', 1);
$weeklyPercentage = ($weeklyUpEvents->count() * 100) / $weeklyEvents->count();

$monthlyEvents = $events->filter(function ($item) use ($lastMonth, $today) {
return $item->created_at->isBetween($lastMonth, $today);
});

$monthlyUpEvents = $monthlyEvents->where('was_online', 1);
$monthlyPercentage = ($monthlyUpEvents->count() * 100) / $monthlyEvents->count();

return [
'total' => floor($totalPercentage),
'day' => floor($todayPercentage),
'week' => floor($weeklyPercentage),
'month' => floor($monthlyPercentage),
];
}
}
43 changes: 43 additions & 0 deletions app/Http/Controllers/UptimeReportController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Http\Controllers;

use App\UptimeScan;
use App\Website;
use Illuminate\Http\Request;

class UptimeReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param Website $website
* @return array
*/
public function __invoke(Request $request, Website $website)
{
$website->load(['uptimes']);

$response = [
'uptime' => $website->uptime_summary,
'response_time' => $website->response_time,
'response_times' => $website->response_times,
'online' => $website->current_state,
'online_time' => $website->uptime,
'last_incident' => $website->last_incident,
'events' => $website->recent_events->transform(function (UptimeScan $scan) {
return [
'id' => $scan->getKey(),
'date' => $scan->created_at,
'type' => $scan->was_online ? 'up' : 'down',
'reason' => $scan->response_status,
'duration' => 10,
];
})->values(),
];

// return view('debug', ['data' => $response]);
return response($response);
}
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/WebsiteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public function store(Request $request)
'robots_enabled' => 'boolean',
'dns_enabled' => 'boolean',
'uptime_enabled' => 'boolean',
'uptime_keyword' => 'required_if:uptime_enabled,1'
]);

$this->panel->beforeSave(function ($data) use ($request) {
Expand Down Expand Up @@ -148,6 +149,7 @@ public function update(Request $request, Website $website)
'robots_enabled' => 'boolean',
'dns_enabled' => 'boolean',
'uptime_enabled' => 'boolean',
'uptime_keyword' => 'required_if:uptime_enabled,1'
]);

$this->panel->setEntry($website);
Expand Down
42 changes: 42 additions & 0 deletions app/Jobs/UptimeCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace App\Jobs;

use App\Checkers\Uptime;
use App\Website;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class UptimeCheck implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
* @var Website
*/
private $website;

/**
* Create a new job instance.
*
* @param Website $website
*/
public function __construct(Website $website)
{
$this->website = $website;
}

/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$checker = new Uptime($this->website);
$checker->run();
}
}
Loading

0 comments on commit d39c716

Please sign in to comment.