111 lines
3.4 KiB
PHP
111 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\Site;
|
|
use App\Models\UptimeCheck;
|
|
use App\Notifications\UptimeAlert;
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\ConnectException;
|
|
use GuzzleHttp\Exception\RequestException;
|
|
use Illuminate\Bus\Batchable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Notification;
|
|
|
|
class CheckUptime implements ShouldQueue
|
|
{
|
|
use Queueable, Batchable;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*/
|
|
public function __construct(
|
|
public Site $site
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
$client = new Client([
|
|
'timeout' => 5,
|
|
'connect_timeout' => 5,
|
|
'allow_redirects' => [
|
|
'max' => 5,
|
|
'track_redirects' => true,
|
|
],
|
|
'http_errors' => false, // Don't throw exceptions on 4xx/5xx responses
|
|
]);
|
|
|
|
$statusCode = null;
|
|
$responseTime = null;
|
|
$startTime = microtime(true);
|
|
|
|
|
|
try {
|
|
// Validate URL format
|
|
if (!filter_var($this->site->url, FILTER_VALIDATE_URL)) {
|
|
Log::warning("Invalid URL format for site {$this->site->id}: {$this->site->url}");
|
|
$statusCode = null;
|
|
$responseTime = null;
|
|
|
|
} else {
|
|
// Send HEAD request for faster checks
|
|
$response = $client->head($this->site->url);
|
|
|
|
$endTime = microtime(true);
|
|
$responseTime = (int) round(($endTime - $startTime) * 1000); // Convert to milliseconds
|
|
$statusCode = $response->getStatusCode();
|
|
|
|
}
|
|
} catch (ConnectException $e) {
|
|
// Connection timeout or DNS failure
|
|
Log::info("Connection failed for site {$this->site->id}: {$e->getMessage()}");
|
|
$statusCode = null;
|
|
$responseTime = null;
|
|
|
|
} catch (RequestException $e) {
|
|
// HTTP error occurred
|
|
$endTime = microtime(true);
|
|
$responseTime = (int) round(($endTime - $startTime) * 1000);
|
|
$statusCode = $e->getResponse() ? $e->getResponse()->getStatusCode() : null;
|
|
|
|
Log::info("Request failed for site {$this->site->id}: HTTP {$statusCode}");
|
|
|
|
} catch (\Exception $e) {
|
|
// Any other exception
|
|
Log::error("Unexpected error checking site {$this->site->id}: {$e->getMessage()}");
|
|
$statusCode = null;
|
|
$responseTime = null;
|
|
|
|
}
|
|
|
|
// Store the uptime check result
|
|
UptimeCheck::create([
|
|
'site_id' => $this->site->id,
|
|
'check_type' => 'http',
|
|
'status_code' => $statusCode,
|
|
'response_time_ms' => $responseTime,
|
|
'is_online' => $statusCode !== null && $statusCode < 400,
|
|
'checked_at' => now(),
|
|
]);
|
|
|
|
|
|
// Send notification if site is down (status >= 400 or unreachable)
|
|
if ($statusCode === null || $statusCode >= 400) {
|
|
$this->site->user->notify(new UptimeAlert(
|
|
$this->site,
|
|
$statusCode,
|
|
$responseTime
|
|
));
|
|
|
|
Log::warning("Downtime alert sent for site {$this->site->id}: HTTP {$statusCode}");
|
|
}
|
|
Log::info("Uptime check completed for site {$this->site->id} ({$this->site->url}): HTTP {$statusCode}, {$responseTime}ms");
|
|
}
|
|
}
|