feat: Add error message and details columns
Adds error_message and details columns to the Incident History table in the service detail page.
This commit is contained in:
+3
-2
@@ -55,7 +55,8 @@ export const useRealTimeUpdates = ({
|
|||||||
setUptimeData(prev => {
|
setUptimeData(prev => {
|
||||||
const newData: UptimeData = {
|
const newData: UptimeData = {
|
||||||
id: e.record.id,
|
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,
|
timestamp: e.record.timestamp,
|
||||||
status: e.record.status,
|
status: e.record.status,
|
||||||
responseTime: e.record.response_time || 0,
|
responseTime: e.record.response_time || 0,
|
||||||
@@ -84,4 +85,4 @@ export const useRealTimeUpdates = ({
|
|||||||
console.error("Error setting up real-time updates:", error);
|
console.error("Error setting up real-time updates:", error);
|
||||||
}
|
}
|
||||||
}, [serviceId, startDate, endDate, setService, setUptimeData]);
|
}, [serviceId, startDate, endDate, setService, setUptimeData]);
|
||||||
};
|
};
|
||||||
@@ -68,7 +68,8 @@ export const useUptimeData = ({ serviceId, serviceType, status, interval }: UseU
|
|||||||
|
|
||||||
const placeholderHistory: UptimeData[] = Array(20).fill(null).map((_, index) => ({
|
const placeholderHistory: UptimeData[] = Array(20).fill(null).map((_, index) => ({
|
||||||
id: `placeholder-${serviceId}-${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(),
|
timestamp: new Date(Date.now() - (index * interval * 1000)).toISOString(),
|
||||||
status: statusValue as "up" | "down" | "warning" | "paused",
|
status: statusValue as "up" | "down" | "warning" | "paused",
|
||||||
responseTime: 0
|
responseTime: 0
|
||||||
@@ -96,7 +97,8 @@ export const useUptimeData = ({ serviceId, serviceType, status, interval }: UseU
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
id: `padding-${serviceId}-${index}`,
|
id: `padding-${serviceId}-${index}`,
|
||||||
serviceId: serviceId || "",
|
service_id: serviceId || "", // Include service_id
|
||||||
|
serviceId: serviceId || "", // Keep for backward compatibility
|
||||||
timestamp: new Date(baseTime - timeOffset).toISOString(),
|
timestamp: new Date(baseTime - timeOffset).toISOString(),
|
||||||
status: lastStatus,
|
status: lastStatus,
|
||||||
responseTime: 0
|
responseTime: 0
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ export function IncidentTable({ incidents }: IncidentTableProps) {
|
|||||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("time")}</TableHead>
|
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("time")}</TableHead>
|
||||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("status")}</TableHead>
|
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("status")}</TableHead>
|
||||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("responseTime")}</TableHead>
|
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("responseTime")}</TableHead>
|
||||||
|
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>Error Message</TableHead>
|
||||||
|
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>Details</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -52,10 +54,28 @@ export function IncidentTable({ incidents }: IncidentTableProps) {
|
|||||||
? `${check.responseTime}ms`
|
? `${check.responseTime}ms`
|
||||||
: "N/A"}
|
: "N/A"}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell className={`text-sm ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} max-w-[200px]`}>
|
||||||
|
{check.error_message ? (
|
||||||
|
<div className="truncate" title={check.error_message}>
|
||||||
|
{check.error_message}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span className={theme === 'dark' ? 'text-gray-500' : 'text-gray-400'}>-</span>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className={`text-sm ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} max-w-[250px]`}>
|
||||||
|
{check.details ? (
|
||||||
|
<div className="truncate" title={check.details}>
|
||||||
|
{check.details}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span className={theme === 'dark' ? 'text-gray-500' : 'text-gray-400'}>-</span>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -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
|
// Create a history record of this check with a more accurate timestamp
|
||||||
const uptimeData: UptimeData = {
|
const uptimeData: UptimeData = {
|
||||||
serviceId: service.id,
|
service_id: service.id, // Include service_id
|
||||||
|
serviceId: service.id, // Keep for backward compatibility
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
status: "up",
|
status: "up",
|
||||||
responseTime: responseTime,
|
responseTime: responseTime,
|
||||||
@@ -92,7 +93,8 @@ export async function handleServiceDown(service: any, formattedTime: string): Pr
|
|||||||
|
|
||||||
// Create a history record of this check
|
// Create a history record of this check
|
||||||
const uptimeData: UptimeData = {
|
const uptimeData: UptimeData = {
|
||||||
serviceId: service.id,
|
service_id: service.id, // Include service_id
|
||||||
|
serviceId: service.id, // Keep for backward compatibility
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
status: "down",
|
status: "down",
|
||||||
responseTime: 0,
|
responseTime: 0,
|
||||||
@@ -161,4 +163,4 @@ export async function handleServiceDown(service: any, formattedTime: string): Pr
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error handling service DOWN state:", error);
|
console.error("Error handling service DOWN state:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,7 @@ export async function resumeMonitoring(serviceId: string): Promise<void> {
|
|||||||
id: service.id,
|
id: service.id,
|
||||||
name: service.name,
|
name: service.name,
|
||||||
url: service.url || "",
|
url: service.url || "",
|
||||||
|
host: service.host || "", // Include host property
|
||||||
type: service.service_type || service.type || "HTTP",
|
type: service.service_type || service.type || "HTTP",
|
||||||
status: "up",
|
status: "up",
|
||||||
responseTime: service.response_time || 0,
|
responseTime: service.response_time || 0,
|
||||||
@@ -77,4 +78,4 @@ export async function resumeMonitoring(serviceId: string): Promise<void> {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error resuming service:", error);
|
console.error("Error resuming service:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ export function prepareServiceForNotification(pbRecord: any, status: string, res
|
|||||||
id: pbRecord.id,
|
id: pbRecord.id,
|
||||||
name: pbRecord.name,
|
name: pbRecord.name,
|
||||||
url: pbRecord.url,
|
url: pbRecord.url,
|
||||||
|
host: pbRecord.host || "", // Include host property with fallback
|
||||||
type: pbRecord.type || pbRecord.service_type || "HTTP",
|
type: pbRecord.type || pbRecord.service_type || "HTTP",
|
||||||
status: status as any,
|
status: status as any,
|
||||||
responseTime: responseTime,
|
responseTime: responseTime,
|
||||||
|
|||||||
@@ -31,22 +31,23 @@ const getCollectionForServiceType = (serviceType: string): string => {
|
|||||||
export const uptimeService = {
|
export const uptimeService = {
|
||||||
async recordUptimeData(data: UptimeData): Promise<void> {
|
async recordUptimeData(data: UptimeData): Promise<void> {
|
||||||
try {
|
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 = {
|
const options = {
|
||||||
$autoCancel: false,
|
$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({
|
const record = await pb.collection('uptime_data').create({
|
||||||
service_id: data.serviceId,
|
service_id: data.service_id || data.serviceId,
|
||||||
timestamp: data.timestamp,
|
timestamp: data.timestamp,
|
||||||
status: data.status,
|
status: data.status,
|
||||||
response_time: data.responseTime
|
response_time: data.responseTime
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
// Invalidate cache for this service
|
// 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));
|
keysToDelete.forEach(key => uptimeCache.delete(key));
|
||||||
|
|
||||||
console.log(`Uptime data recorded successfully with ID: ${record.id}`);
|
console.log(`Uptime data recorded successfully with ID: ${record.id}`);
|
||||||
@@ -116,12 +117,15 @@ export const uptimeService = {
|
|||||||
// Transform the response items to UptimeData format
|
// Transform the response items to UptimeData format
|
||||||
const uptimeData = response.items.map(item => ({
|
const uptimeData = response.items.map(item => ({
|
||||||
id: item.id,
|
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,
|
timestamp: item.timestamp,
|
||||||
status: item.status as "up" | "down" | "warning" | "paused",
|
status: item.status as "up" | "down" | "warning" | "paused",
|
||||||
responseTime: item.response_time || 0,
|
responseTime: item.response_time || 0,
|
||||||
date: item.timestamp,
|
date: item.timestamp,
|
||||||
uptime: 100
|
uptime: 100,
|
||||||
|
error_message: item.error_message,
|
||||||
|
details: item.details
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
|
|||||||
@@ -2,22 +2,36 @@
|
|||||||
export interface Service {
|
export interface Service {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url?: string;
|
||||||
host?: string; // Add host field for PING and TCP services
|
host?: string; // Make host optional since it's not always required
|
||||||
port?: number; // Add port field for TCP services
|
port?: number;
|
||||||
type: "HTTP" | "HTTPS" | "TCP" | "DNS" | "PING" | "HTTP" | "http" | "https" | "tcp" | "dns" | "ping" | "smtp" | "icmp";
|
domain?: string; // Add domain field for DNS services
|
||||||
status: "up" | "down" | "paused" | "pending" | "warning";
|
type: "http" | "https" | "tcp" | "ping" | "icmp" | "dns";
|
||||||
|
status: "up" | "down" | "paused" | "warning";
|
||||||
responseTime: number;
|
responseTime: number;
|
||||||
uptime: number;
|
uptime?: number;
|
||||||
lastChecked: string;
|
lastChecked: string;
|
||||||
interval: number;
|
interval: number;
|
||||||
|
timeout?: number;
|
||||||
retries: number;
|
retries: number;
|
||||||
notificationChannel?: string;
|
created?: string;
|
||||||
|
updated?: string;
|
||||||
|
notification_channel?: string;
|
||||||
|
notificationChannel?: string; // Keep for backward compatibility
|
||||||
alertTemplate?: string;
|
alertTemplate?: string;
|
||||||
muteAlerts?: boolean; // Keep this to avoid breaking existing code
|
|
||||||
alerts?: "muted" | "unmuted"; // Make sure alerts is properly typed as union
|
alerts?: "muted" | "unmuted"; // Make sure alerts is properly typed as union
|
||||||
|
muteAlerts?: boolean; // Keep this to avoid breaking existing code
|
||||||
muteChangedAt?: string;
|
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 {
|
export interface CreateServiceParams {
|
||||||
@@ -34,11 +48,54 @@ export interface CreateServiceParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UptimeData {
|
export interface UptimeData {
|
||||||
date?: string;
|
|
||||||
uptime?: number;
|
|
||||||
id?: string;
|
id?: string;
|
||||||
serviceId?: string;
|
service_id?: string; // Make service_id optional for backward compatibility
|
||||||
|
serviceId?: string; // Keep for backward compatibility
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
status: "up" | "down" | "paused" | "pending" | "warning";
|
status: "up" | "down" | "paused" | "warning";
|
||||||
responseTime: number;
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user