From 918a248b8f56235ce93672bfd819f367cee318df Mon Sep 17 00:00:00 2001 From: Tola Leng Date: Fri, 20 Jun 2025 20:13:18 +0700 Subject: [PATCH] feat: Add error message and details columns Adds error_message and details columns to the Incident History table in the service detail page. --- .../hooks/useRealTimeUpdates.tsx | 5 +- .../services/hooks/useUptimeData.ts | 6 +- .../incident-history/IncidentTable.tsx | 22 ++++- .../handlers/serviceStatusHandlers.ts | 8 +- .../service-status/resumeMonitoring.ts | 3 +- .../services/monitoring/utils/httpUtils.ts | 1 + application/src/services/uptimeService.ts | 16 ++-- application/src/types/service.types.ts | 83 ++++++++++++++++--- 8 files changed, 116 insertions(+), 28 deletions(-) diff --git a/application/src/components/services/ServiceDetailContainer/hooks/useRealTimeUpdates.tsx b/application/src/components/services/ServiceDetailContainer/hooks/useRealTimeUpdates.tsx index 20f0687..1d096df 100644 --- a/application/src/components/services/ServiceDetailContainer/hooks/useRealTimeUpdates.tsx +++ b/application/src/components/services/ServiceDetailContainer/hooks/useRealTimeUpdates.tsx @@ -55,7 +55,8 @@ export const useRealTimeUpdates = ({ setUptimeData(prev => { const newData: UptimeData = { id: e.record.id, - serviceId: e.record.service_id, + service_id: e.record.service_id, // Include service_id + serviceId: e.record.service_id, // Keep for backward compatibility timestamp: e.record.timestamp, status: e.record.status, responseTime: e.record.response_time || 0, @@ -84,4 +85,4 @@ export const useRealTimeUpdates = ({ console.error("Error setting up real-time updates:", error); } }, [serviceId, startDate, endDate, setService, setUptimeData]); -}; +}; \ No newline at end of file diff --git a/application/src/components/services/hooks/useUptimeData.ts b/application/src/components/services/hooks/useUptimeData.ts index 91e5391..34f7b88 100644 --- a/application/src/components/services/hooks/useUptimeData.ts +++ b/application/src/components/services/hooks/useUptimeData.ts @@ -68,7 +68,8 @@ export const useUptimeData = ({ serviceId, serviceType, status, interval }: UseU const placeholderHistory: UptimeData[] = Array(20).fill(null).map((_, index) => ({ id: `placeholder-${serviceId}-${index}`, - serviceId: serviceId || "", + service_id: serviceId || "", // Include service_id + serviceId: serviceId || "", // Keep for backward compatibility timestamp: new Date(Date.now() - (index * interval * 1000)).toISOString(), status: statusValue as "up" | "down" | "warning" | "paused", responseTime: 0 @@ -96,7 +97,8 @@ export const useUptimeData = ({ serviceId, serviceType, status, interval }: UseU return { id: `padding-${serviceId}-${index}`, - serviceId: serviceId || "", + service_id: serviceId || "", // Include service_id + serviceId: serviceId || "", // Keep for backward compatibility timestamp: new Date(baseTime - timeOffset).toISOString(), status: lastStatus, responseTime: 0 diff --git a/application/src/components/services/incident-history/IncidentTable.tsx b/application/src/components/services/incident-history/IncidentTable.tsx index 5f7c125..d8118ed 100644 --- a/application/src/components/services/incident-history/IncidentTable.tsx +++ b/application/src/components/services/incident-history/IncidentTable.tsx @@ -25,6 +25,8 @@ export function IncidentTable({ incidents }: IncidentTableProps) { {t("time")} {t("status")} {t("responseTime")} + Error Message + Details @@ -52,10 +54,28 @@ export function IncidentTable({ incidents }: IncidentTableProps) { ? `${check.responseTime}ms` : "N/A"} + + {check.error_message ? ( +
+ {check.error_message} +
+ ) : ( + - + )} +
+ + {check.details ? ( +
+ {check.details} +
+ ) : ( + - + )} +
); })}
); -} +} \ No newline at end of file diff --git a/application/src/services/monitoring/handlers/serviceStatusHandlers.ts b/application/src/services/monitoring/handlers/serviceStatusHandlers.ts index 8bd31c0..9405c38 100644 --- a/application/src/services/monitoring/handlers/serviceStatusHandlers.ts +++ b/application/src/services/monitoring/handlers/serviceStatusHandlers.ts @@ -13,7 +13,8 @@ export async function handleServiceUp(service: any, responseTime: number, format // Create a history record of this check with a more accurate timestamp const uptimeData: UptimeData = { - serviceId: service.id, + service_id: service.id, // Include service_id + serviceId: service.id, // Keep for backward compatibility timestamp: new Date().toISOString(), status: "up", responseTime: responseTime, @@ -92,7 +93,8 @@ export async function handleServiceDown(service: any, formattedTime: string): Pr // Create a history record of this check const uptimeData: UptimeData = { - serviceId: service.id, + service_id: service.id, // Include service_id + serviceId: service.id, // Keep for backward compatibility timestamp: new Date().toISOString(), status: "down", responseTime: 0, @@ -161,4 +163,4 @@ export async function handleServiceDown(service: any, formattedTime: string): Pr } catch (error) { console.error("Error handling service DOWN state:", error); } -} +} \ No newline at end of file diff --git a/application/src/services/monitoring/service-status/resumeMonitoring.ts b/application/src/services/monitoring/service-status/resumeMonitoring.ts index 0c4f020..47fdcc6 100644 --- a/application/src/services/monitoring/service-status/resumeMonitoring.ts +++ b/application/src/services/monitoring/service-status/resumeMonitoring.ts @@ -37,6 +37,7 @@ export async function resumeMonitoring(serviceId: string): Promise { id: service.id, name: service.name, url: service.url || "", + host: service.host || "", // Include host property type: service.service_type || service.type || "HTTP", status: "up", responseTime: service.response_time || 0, @@ -77,4 +78,4 @@ export async function resumeMonitoring(serviceId: string): Promise { } catch (error) { console.error("Error resuming service:", error); } -} +} \ No newline at end of file diff --git a/application/src/services/monitoring/utils/httpUtils.ts b/application/src/services/monitoring/utils/httpUtils.ts index 08f959d..1987b19 100644 --- a/application/src/services/monitoring/utils/httpUtils.ts +++ b/application/src/services/monitoring/utils/httpUtils.ts @@ -19,6 +19,7 @@ export function prepareServiceForNotification(pbRecord: any, status: string, res id: pbRecord.id, name: pbRecord.name, url: pbRecord.url, + host: pbRecord.host || "", // Include host property with fallback type: pbRecord.type || pbRecord.service_type || "HTTP", status: status as any, responseTime: responseTime, diff --git a/application/src/services/uptimeService.ts b/application/src/services/uptimeService.ts index 5a6808c..10fa139 100644 --- a/application/src/services/uptimeService.ts +++ b/application/src/services/uptimeService.ts @@ -31,22 +31,23 @@ const getCollectionForServiceType = (serviceType: string): string => { export const uptimeService = { async recordUptimeData(data: UptimeData): Promise { try { - console.log(`Recording uptime data for service ${data.serviceId}: Status ${data.status}, Response time: ${data.responseTime}ms`); + console.log(`Recording uptime data for service ${data.serviceId || data.service_id}: Status ${data.status}, Response time: ${data.responseTime}ms`); const options = { $autoCancel: false, - $cancelKey: `uptime_record_${data.serviceId}_${Date.now()}` + $cancelKey: `uptime_record_${data.serviceId || data.service_id}_${Date.now()}` }; const record = await pb.collection('uptime_data').create({ - service_id: data.serviceId, + service_id: data.service_id || data.serviceId, timestamp: data.timestamp, status: data.status, response_time: data.responseTime }, options); // Invalidate cache for this service - const keysToDelete = Array.from(uptimeCache.keys()).filter(key => key.includes(`uptime_${data.serviceId}`)); + const serviceId = data.service_id || data.serviceId; + const keysToDelete = Array.from(uptimeCache.keys()).filter(key => key.includes(`uptime_${serviceId}`)); keysToDelete.forEach(key => uptimeCache.delete(key)); console.log(`Uptime data recorded successfully with ID: ${record.id}`); @@ -116,12 +117,15 @@ export const uptimeService = { // Transform the response items to UptimeData format const uptimeData = response.items.map(item => ({ id: item.id, - serviceId: item.service_id, + service_id: item.service_id, // Include service_id + serviceId: item.service_id, // Keep for backward compatibility timestamp: item.timestamp, status: item.status as "up" | "down" | "warning" | "paused", responseTime: item.response_time || 0, date: item.timestamp, - uptime: 100 + uptime: 100, + error_message: item.error_message, + details: item.details })); // Cache the result diff --git a/application/src/types/service.types.ts b/application/src/types/service.types.ts index a3b810a..b9da956 100644 --- a/application/src/types/service.types.ts +++ b/application/src/types/service.types.ts @@ -2,22 +2,36 @@ export interface Service { id: string; name: string; - url: string; - host?: string; // Add host field for PING and TCP services - port?: number; // Add port field for TCP services - type: "HTTP" | "HTTPS" | "TCP" | "DNS" | "PING" | "HTTP" | "http" | "https" | "tcp" | "dns" | "ping" | "smtp" | "icmp"; - status: "up" | "down" | "paused" | "pending" | "warning"; + url?: string; + host?: string; // Make host optional since it's not always required + port?: number; + domain?: string; // Add domain field for DNS services + type: "http" | "https" | "tcp" | "ping" | "icmp" | "dns"; + status: "up" | "down" | "paused" | "warning"; responseTime: number; - uptime: number; + uptime?: number; lastChecked: string; interval: number; + timeout?: number; retries: number; - notificationChannel?: string; + created?: string; + updated?: string; + notification_channel?: string; + notificationChannel?: string; // Keep for backward compatibility alertTemplate?: string; - muteAlerts?: boolean; // Keep this to avoid breaking existing code alerts?: "muted" | "unmuted"; // Make sure alerts is properly typed as union + muteAlerts?: boolean; // Keep this to avoid breaking existing code muteChangedAt?: string; - domain?: string; // Add domain field for DNS services + follow_redirects?: boolean; + verify_ssl?: boolean; + expected_status_code?: number; + keyword_check?: string; + keyword_check_type?: "contains" | "not_contains"; + dns_record_type?: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS"; + dns_expected_value?: string; + headers?: string; + body?: string; + method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"; } export interface CreateServiceParams { @@ -34,11 +48,54 @@ export interface CreateServiceParams { } export interface UptimeData { - date?: string; - uptime?: number; id?: string; - serviceId?: string; + service_id?: string; // Make service_id optional for backward compatibility + serviceId?: string; // Keep for backward compatibility timestamp: string; - status: "up" | "down" | "paused" | "pending" | "warning"; + status: "up" | "down" | "paused" | "warning"; responseTime: number; + error_message?: string; + details?: string; + created?: string; + updated?: string; + date?: string; // Keep for backward compatibility + uptime?: number; // Keep for backward compatibility +} + +export interface PingData { + id?: string; + service_id: string; + timestamp: string; + status: "up" | "down" | "paused" | "warning"; + responseTime: number; + packet_loss?: number; + error_message?: string; + details?: string; + created?: string; + updated?: string; +} + +export interface DNSData { + id?: string; + service_id: string; + timestamp: string; + status: "up" | "down" | "paused" | "warning"; + responseTime: number; + resolved_ip?: string; + error_message?: string; + details?: string; + created?: string; + updated?: string; +} + +export interface TCPData { + id?: string; + service_id: string; + timestamp: string; + status: "up" | "down" | "paused" | "warning"; + responseTime: number; + error_message?: string; + details?: string; + created?: string; + updated?: string; } \ No newline at end of file