This commit is contained in:
Flatlogic Bot 2026-02-25 23:31:37 +00:00
parent 6fabe9540d
commit dc9d779de8
2 changed files with 104 additions and 81 deletions

Binary file not shown.

View File

@ -5,12 +5,14 @@ require_once __DIR__ . '/db/config.php';
$lockFile = __DIR__ . '/monitor.lock'; $lockFile = __DIR__ . '/monitor.lock';
$fp = fopen($lockFile, 'c'); $fp = fopen($lockFile, 'c');
if (!flock($fp, LOCK_EX | LOCK_NB)) { if (!flock($fp, LOCK_EX | LOCK_NB)) {
die("Another instance is already running.\n"); // Silently exit if already running (good for cron)
exit(0);
} }
echo "Monitoring started with Multi-Threading...\n"; echo "Monitoring started with Multi-Threading...\n";
function sendTelegramNotification($message) { function sendTelegramNotification($message) {
try {
$db = db(); $db = db();
$stmt = $db->query("SELECT name, value FROM settings WHERE name IN ('telegram_bot_token', 'telegram_chat_id')"); $stmt = $db->query("SELECT name, value FROM settings WHERE name IN ('telegram_bot_token', 'telegram_chat_id')");
$settings = []; $settings = [];
@ -36,34 +38,40 @@ function sendTelegramNotification($message) {
curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_exec($ch); curl_exec($ch);
curl_close($ch); curl_close($ch);
} catch (Exception $e) {
// Suppress errors to not break the monitor loop
}
} }
// Loop indefinitely
while (true) { while (true) {
$startLoop = microtime(true); try {
$db = db(); $db = db();
$urls = $db->query("SELECT * FROM urls WHERE is_active = 1")->fetchAll(); $urls = $db->query("SELECT * FROM urls WHERE is_active = 1")->fetchAll();
if (count($urls) > 0) { if (count($urls) > 0) {
$mh = curl_multi_init(); $mh = curl_multi_init();
$ch_list = []; $curl_arr = [];
$url_info = [];
// Add handles
foreach ($urls as $urlData) { foreach ($urls as $urlData) {
$ch = curl_init($urlData['url']); $ch = curl_init($urlData['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HEADER, false); // We don't need body, just headers
curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_NOBODY, true); // HEAD request is faster
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 10s timeout
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_multi_add_handle($mh, $ch); curl_multi_add_handle($mh, $ch);
$ch_list[(int)$ch] = [ $curl_arr[] = $ch;
'id' => $urlData['id'], // Store info mapped by intval of handle
'url' => $urlData['url'], $url_info[(int)$ch] = $urlData;
'old_status' => $urlData['status'],
'start_time' => microtime(true)
];
} }
// Execute handles
$active = null; $active = null;
do { do {
$mrc = curl_multi_exec($mh, $active); $mrc = curl_multi_exec($mh, $active);
@ -77,30 +85,45 @@ while (true) {
} }
} }
foreach ($ch_list as $ch_id => $data) { // Read results
$ch = null; foreach ($curl_arr as $ch) {
// Find the handle $ch_id = (int)$ch;
foreach ($ch_list as $handle_id => $info) { $urlData = $url_info[$ch_id];
if ($handle_id == $ch_id) {
// This is tricky in PHP to get handle by int. $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Actually we can just keep the handles in an array. $total_time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
} $total_time_ms = round($total_time * 1000);
}
// Determine new status: UP if 200-399
$new_status = ($http_code >= 200 && $http_code < 400) ? 'UP' : 'DOWN';
$old_status = $urlData['status'];
// Update database
$stmt = $db->prepare("UPDATE urls SET status = ?, last_checked = NOW() WHERE id = ?");
$stmt->execute([$new_status, $urlData['id']]);
$stmt = $db->prepare("INSERT INTO logs (url_id, status, response_time, checked_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$urlData['id'], $new_status, $total_time_ms]);
// Check for status change and notify
if ($old_status && $old_status !== $new_status) {
$icon = $new_status === 'UP' ? '✅' : '🚨';
$msg = "{$icon} <b>Monitor Alert</b>\n\n";
$msg .= "<b>URL:</b> {$urlData['url']}\n";
$msg .= "<b>Status:</b> {$new_status} (HTTP {$http_code})\n";
$msg .= "<b>Response:</b> {$total_time_ms}ms";
sendTelegramNotification($msg);
} }
// Re-doing the loop for better handle management curl_multi_remove_handle($mh, $ch);
foreach ($ch_list as $ch_int => $info) { curl_close($ch);
// Wait, I need the actual handle.
} }
curl_multi_close($mh);
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
} }
// SIMPLIFIED Sequential for stability if multi is complex in 1s loop // Wait 30 seconds before next check
// Let's stick to sequential but optimized for now, or fix multi properly. sleep(30);
// Actually, curl_multi is better. Let's do it right.
// (Self-correction: curl_multi is better but I need to store the handles properly)
$endLoop = microtime(true);
// ... sleep ...
usleep(1000000); // Temporary simplified sleep
} }