Remove HTTP service check
Remove HTTP service check functionality as the React application is now frontend only.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { FormControl, FormField, FormItem, FormLabel } from "@/components/ui/form";
|
import { FormControl, FormField, FormItem, FormLabel } from "@/components/ui/form";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { Globe } from "lucide-react";
|
import { Globe, Wifi, Server, Globe2 } from "lucide-react";
|
||||||
import { UseFormReturn } from "react-hook-form";
|
import { UseFormReturn } from "react-hook-form";
|
||||||
import { ServiceFormData } from "./types";
|
import { ServiceFormData } from "./types";
|
||||||
|
|
||||||
@@ -10,6 +10,21 @@ interface ServiceTypeFieldProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||||
|
const getServiceIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "http":
|
||||||
|
return <Globe className="w-4 h-4" />;
|
||||||
|
case "ping":
|
||||||
|
return <Wifi className="w-4 h-4" />;
|
||||||
|
case "tcp":
|
||||||
|
return <Server className="w-4 h-4" />;
|
||||||
|
case "dns":
|
||||||
|
return <Globe2 className="w-4 h-4" />;
|
||||||
|
default:
|
||||||
|
return <Globe className="w-4 h-4" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@@ -24,13 +39,13 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
|||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue>
|
<SelectValue>
|
||||||
{field.value === "http" && (
|
{field.value && (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Globe className="w-4 h-4" />
|
{getServiceIcon(field.value)}
|
||||||
<span>HTTP/S</span>
|
<span>{field.value.toUpperCase()}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{field.value !== "http" && "Select a service type"}
|
{!field.value && "Select a service type"}
|
||||||
</SelectValue>
|
</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -41,13 +56,43 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
|||||||
<span>HTTP/S</span>
|
<span>HTTP/S</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
Monitor websites and REST APIs with HTTP/HTTPS protocol
|
Monitor websites and REST APIs with HTTP/HTTPS Protocol
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="ping">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Wifi className="w-4 h-4" />
|
||||||
|
<span>PING</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
|
Monitor host availability with PING Protocol
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="tcp">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Server className="w-4 h-4" />
|
||||||
|
<span>TCP</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
|
Monitor TCP port connectivity with TCP Protocol
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="dns">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Globe2 className="w-4 h-4" />
|
||||||
|
<span>DNS</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
|
Monitor DNS resolution
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="ping">PING</SelectItem>
|
|
||||||
<SelectItem value="tcp">TCP</SelectItem>
|
|
||||||
<SelectItem value="dns">DNS</SelectItem>
|
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import { monitoringIntervals } from './monitoringIntervals';
|
import { monitoringIntervals } from './monitoringIntervals';
|
||||||
import { checkHttpService } from './httpChecker';
|
|
||||||
import {
|
import {
|
||||||
startMonitoringService,
|
startMonitoringService,
|
||||||
pauseMonitoring,
|
pauseMonitoring,
|
||||||
@@ -12,6 +11,5 @@ export const monitoringService = {
|
|||||||
startMonitoringService,
|
startMonitoringService,
|
||||||
pauseMonitoring,
|
pauseMonitoring,
|
||||||
resumeMonitoring,
|
resumeMonitoring,
|
||||||
checkHttpService,
|
|
||||||
startAllActiveServices
|
startAllActiveServices
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
import { pb } from '@/lib/pocketbase';
|
import { pb } from '@/lib/pocketbase';
|
||||||
import { monitoringIntervals } from '../monitoringIntervals';
|
import { monitoringIntervals } from '../monitoringIntervals';
|
||||||
import { checkHttpService } from '../httpChecker';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start monitoring for a specific service
|
* Start monitoring for a specific service
|
||||||
@@ -30,35 +29,21 @@ export async function startMonitoringService(serviceId: string): Promise<void> {
|
|||||||
status: "up",
|
status: "up",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start with an immediate check
|
// The actual service checking is now handled by the Go microservice
|
||||||
await checkHttpService(serviceId);
|
// This frontend service just tracks the monitoring state
|
||||||
|
const intervalMs = (service.heartbeat_interval || 60) * 1000;
|
||||||
|
console.log(`Service ${service.name} monitoring delegated to backend service`);
|
||||||
|
|
||||||
// Then schedule regular checks based on the interval
|
// Store a placeholder interval to track that this service is being monitored
|
||||||
const intervalMs = (service.heartbeat_interval || 60) * 1000; // Convert from seconds to milliseconds
|
const intervalId = window.setInterval(() => {
|
||||||
console.log(`Setting check interval for ${service.name} to ${intervalMs}ms (${service.heartbeat_interval || 60} seconds)`);
|
console.log(`Monitoring active for service ${service.name} (handled by backend)`);
|
||||||
|
|
||||||
// Store the interval ID so we can clear it later if needed
|
|
||||||
const intervalId = window.setInterval(async () => {
|
|
||||||
try {
|
|
||||||
// Check if service has been paused since scheduling
|
|
||||||
const currentService = await pb.collection('services').getOne(serviceId);
|
|
||||||
if (currentService.status === "paused") {
|
|
||||||
console.log(`Service ${serviceId} is now paused. Skipping scheduled check.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Running scheduled check for service ${service.name}`);
|
|
||||||
await checkHttpService(serviceId);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error in scheduled check for ${service.name}:`, error);
|
|
||||||
}
|
|
||||||
}, intervalMs);
|
}, intervalMs);
|
||||||
|
|
||||||
// Store the interval ID for this service
|
// Store the interval ID for this service
|
||||||
monitoringIntervals.set(serviceId, intervalId);
|
monitoringIntervals.set(serviceId, intervalId);
|
||||||
|
|
||||||
console.log(`Monitoring scheduled for service ${serviceId} every ${service.heartbeat_interval || 60} seconds`);
|
console.log(`Monitoring registered for service ${serviceId}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error starting service monitoring:", error);
|
console.error("Error starting service monitoring:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,149 +56,4 @@ export function formatRecordId(id: string): string {
|
|||||||
export function formatCurrentTime(): string {
|
export function formatCurrentTime(): string {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
return now.toISOString();
|
return now.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an HTTP request to a service endpoint with retry logic
|
|
||||||
* Improved to better handle different response scenarios and detection issues
|
|
||||||
*/
|
|
||||||
export async function makeHttpRequest(url: string, maxRetries: number = 3): Promise<{ isUp: boolean; responseTime: number }> {
|
|
||||||
let retries = 0;
|
|
||||||
let isUp = false;
|
|
||||||
let responseTime = 0;
|
|
||||||
let lastError = null;
|
|
||||||
|
|
||||||
const startTime = performance.now();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Ensure URL has proper protocol
|
|
||||||
const targetUrl = ensureHttpsProtocol(url);
|
|
||||||
|
|
||||||
while (retries < maxRetries && !isUp) {
|
|
||||||
try {
|
|
||||||
// Use fetch API with a timeout to prevent long-hanging requests
|
|
||||||
const controller = new AbortController();
|
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
|
||||||
|
|
||||||
console.log(`Attempt ${retries + 1}/${maxRetries} checking ${targetUrl}`);
|
|
||||||
|
|
||||||
// IMPROVED APPROACH: Try multiple detection methods in sequence
|
|
||||||
|
|
||||||
// Method 1: Try HEAD request first as it's lightweight
|
|
||||||
try {
|
|
||||||
console.log(`Trying HEAD request to ${targetUrl}`);
|
|
||||||
const headResponse = await fetch(targetUrl, {
|
|
||||||
method: 'HEAD',
|
|
||||||
signal: controller.signal,
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {
|
|
||||||
'Accept': '*/*',
|
|
||||||
'User-Agent': 'ServiceMonitor/1.0'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If HEAD request succeeds with any status code, service is reachable
|
|
||||||
isUp = true;
|
|
||||||
console.log(`HEAD request successful with status ${headResponse.status}`);
|
|
||||||
} catch (headError) {
|
|
||||||
console.log(`HEAD request failed: ${headError.message}`);
|
|
||||||
lastError = headError;
|
|
||||||
|
|
||||||
// Method 2: Fall back to standard GET with proper error handling
|
|
||||||
try {
|
|
||||||
console.log(`Trying standard GET request to ${targetUrl}`);
|
|
||||||
const getResponse = await fetch(targetUrl, {
|
|
||||||
method: 'GET',
|
|
||||||
signal: controller.signal,
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {
|
|
||||||
'Accept': '*/*',
|
|
||||||
'User-Agent': 'ServiceMonitor/1.0'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If GET returns any response, consider the service up
|
|
||||||
isUp = true;
|
|
||||||
console.log(`GET request successful with status ${getResponse.status}`);
|
|
||||||
} catch (getError) {
|
|
||||||
console.log(`Standard GET request failed: ${getError.message}`);
|
|
||||||
lastError = getError;
|
|
||||||
|
|
||||||
// Method 3: Try with no-cors mode as a last resort
|
|
||||||
try {
|
|
||||||
console.log(`Trying no-cors GET request to ${targetUrl}`);
|
|
||||||
const noCorsResponse = await fetch(targetUrl, {
|
|
||||||
method: 'GET',
|
|
||||||
mode: 'no-cors', // This allows requests to succeed even if CORS is restricted
|
|
||||||
signal: controller.signal,
|
|
||||||
cache: 'no-cache'
|
|
||||||
});
|
|
||||||
|
|
||||||
// In no-cors mode, we can't read the response, but if we get here without an exception,
|
|
||||||
// the request succeeded and the service is likely up
|
|
||||||
isUp = true;
|
|
||||||
console.log(`No-cors GET request succeeded, assuming service is UP`);
|
|
||||||
} catch (corsError) {
|
|
||||||
console.log(`No-cors GET request also failed: ${corsError.message}`);
|
|
||||||
lastError = corsError;
|
|
||||||
isUp = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method 4: If all fetches fail but error is CORS-related, consider service up
|
|
||||||
if (!isUp && lastError &&
|
|
||||||
(lastError.message.includes('CORS') ||
|
|
||||||
lastError.message.includes('blocked') ||
|
|
||||||
lastError.message.includes('policy'))) {
|
|
||||||
console.log("CORS error detected, but this likely means the service is running.");
|
|
||||||
console.log("Setting service as UP despite CORS restriction.");
|
|
||||||
isUp = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
responseTime = Math.round(performance.now() - startTime);
|
|
||||||
|
|
||||||
if (isUp) {
|
|
||||||
console.log(`Service is detected as UP after ${retries + 1} attempts, response time: ${responseTime}ms`);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
console.log(`All connection attempts failed for attempt ${retries + 1}`);
|
|
||||||
retries++;
|
|
||||||
|
|
||||||
// Add a short delay between retries
|
|
||||||
if (retries < maxRetries) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`HTTP request attempt ${retries + 1} failed with error:`, error);
|
|
||||||
lastError = error;
|
|
||||||
retries++;
|
|
||||||
|
|
||||||
if (retries < maxRetries) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Critical error in makeHttpRequest:', error);
|
|
||||||
isUp = false;
|
|
||||||
responseTime = Math.round(performance.now() - startTime);
|
|
||||||
lastError = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Final check for status
|
|
||||||
if (!isUp && lastError) {
|
|
||||||
console.log("Final connection attempt failed with error:", lastError);
|
|
||||||
// Check for specific errors that might indicate the site is actually up
|
|
||||||
if (lastError.name === 'AbortError') {
|
|
||||||
console.log("Request timed out which may indicate a slow response rather than service down");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the final result for debugging
|
|
||||||
console.log(`Final service check result - URL: ${url}, isUp: ${isUp}, responseTime: ${responseTime}ms, retries: ${retries}`);
|
|
||||||
|
|
||||||
return { isUp, responseTime };
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { pb } from '@/lib/pocketbase';
|
import { pb } from '@/lib/pocketbase';
|
||||||
import { Service, CreateServiceParams, UptimeData } from '@/types/service.types';
|
import { Service, CreateServiceParams, UptimeData } from '@/types/service.types';
|
||||||
import { monitoringService } from './monitoring';
|
import { monitoringService } from './monitoring';
|
||||||
@@ -144,10 +143,9 @@ export const serviceService = {
|
|||||||
startMonitoringService: monitoringService.startMonitoringService,
|
startMonitoringService: monitoringService.startMonitoringService,
|
||||||
pauseMonitoring: monitoringService.pauseMonitoring,
|
pauseMonitoring: monitoringService.pauseMonitoring,
|
||||||
resumeMonitoring: monitoringService.resumeMonitoring,
|
resumeMonitoring: monitoringService.resumeMonitoring,
|
||||||
checkHttpService: monitoringService.checkHttpService,
|
|
||||||
startAllActiveServices: monitoringService.startAllActiveServices,
|
startAllActiveServices: monitoringService.startAllActiveServices,
|
||||||
|
|
||||||
// Re-export uptime functions
|
// Re-export uptime functions
|
||||||
recordUptimeData: uptimeService.recordUptimeData,
|
recordUptimeData: uptimeService.recordUptimeData,
|
||||||
getUptimeHistory: uptimeService.getUptimeHistory
|
getUptimeHistory: uptimeService.getUptimeHistory
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user