Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# These owners will be the default owners for everything in
* @tolaleng
15 changes: 15 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# These are supported funding model platforms

github: [tolaleng]
patreon: # Replace with a single Patreon username
open_collective: checkcle
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![CheckCle Platform](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/instance-server-monitoring.png)
![CheckCle Platform](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/server-detail-page.png)

# 🚀 What is CheckCle?

Expand Down
494 changes: 58 additions & 436 deletions application/src/components/servers/ServerHistoryCharts.tsx

Large diffs are not rendered by default.

19 changes: 11 additions & 8 deletions application/src/components/servers/ServerMetricsCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { serverService } from "@/services/serverService";
import { Loader2, Cpu, HardDrive, Network, MemoryStick } from "lucide-react";
import { formatChartData } from "./charts/dataUtils";
import { TimeRangeSelector } from "./charts/TimeRangeSelector";
import { CPUCharts } from "./charts/CPUCharts";
import { MemoryCharts } from "./charts/MemoryCharts";
import { DiskCharts } from "./charts/DiskCharts";
import { NetworkCharts } from "./charts/NetworkCharts";
import { CPUChart } from "./charts/CPUChart";
import { MemoryChart } from "./charts/MemoryChart";
import { DiskChart } from "./charts/DiskChart";
import { NetworkChart } from "./charts/NetworkChart";

interface ServerMetricsChartsProps {
serverId: string;
Expand Down Expand Up @@ -58,6 +58,9 @@ export const ServerMetricsCharts = ({ serverId }: ServerMetricsChartsProps) => {
);
}

// Calculate latest data for each chart
const latestData = chartData[chartData.length - 1];

return (
<div className="space-y-6">
<div className="flex items-center justify-between">
Expand Down Expand Up @@ -89,19 +92,19 @@ export const ServerMetricsCharts = ({ serverId }: ServerMetricsChartsProps) => {
</TabsList>

<TabsContent value="cpu" className="space-y-4 mt-6">
<CPUCharts data={chartData} />
<CPUChart data={chartData} latestData={latestData} />
</TabsContent>

<TabsContent value="memory" className="space-y-4 mt-6">
<MemoryCharts data={chartData} />
<MemoryChart data={chartData} latestData={latestData} />
</TabsContent>

<TabsContent value="disk" className="space-y-4 mt-6">
<DiskCharts data={chartData} />
<DiskChart data={chartData} latestData={latestData} />
</TabsContent>

<TabsContent value="network" className="space-y-4 mt-6">
<NetworkCharts data={chartData} />
<NetworkChart data={chartData} latestData={latestData} />
</TabsContent>
</Tabs>
</div>
Expand Down
169 changes: 110 additions & 59 deletions application/src/components/servers/ServerMetricsOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,74 +36,77 @@ export const ServerMetricsOverview = ({ server }: ServerMetricsOverviewProps) =>
const ramUsagePercent = server.ram_total > 0 ? (server.ram_used / server.ram_total) * 100 : 0;
const diskUsagePercent = server.disk_total > 0 ? (server.disk_used / server.disk_total) * 100 : 0;

const MetricCard = ({ title, used, total, free, percentage, icon: Icon, color, additionalInfo }: {
const MetricCard = ({ title, used, total, free, percentage, icon: Icon, color, gradient, additionalInfo }: {
title: string;
used: string;
total: string;
free: string;
percentage: number;
icon: any;
color: string;
gradient: string;
additionalInfo?: string;
}) => (
<Card className="relative overflow-hidden bg-gradient-to-br from-card/80 via-card to-card/60 border border-border/60 shadow-lg hover:shadow-xl hover:border-border/80 transition-all duration-300 backdrop-blur-sm group">
<div className="absolute inset-0 bg-gradient-to-br from-transparent via-white/[0.02] to-white/[0.05] opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<CardHeader className="pb-3 relative">
<Card
className="border-none rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl transform hover:-translate-y-1 relative"
style={{ background: gradient }}
>
{/* Grid Pattern Overlay */}
<div className="absolute inset-0 z-0 opacity-10">
<div
className="w-full h-full"
style={{
backgroundImage: `linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px)`,
backgroundSize: '20px 20px'
}}
/>
</div>

<CardHeader className="pb-3 relative z-10">
<CardTitle className="flex items-center justify-between text-sm font-semibold">
<div className="flex items-center gap-3">
<div
className="p-2.5 rounded-xl shadow-sm ring-1 ring-white/10 transition-all duration-300 group-hover:scale-110"
style={{
backgroundColor: `${color}15`,
boxShadow: `0 4px 12px ${color}20`
}}
>
<Icon className="h-4 w-4" style={{ color }} />
<div className="p-2.5 rounded-xl bg-white/20 backdrop-blur-sm shadow-sm transition-all duration-300 group-hover:scale-110">
<Icon className="h-4 w-4 text-white" />
</div>
<span className="text-foreground/90">{title}</span>
<span className="text-white">{title}</span>
</div>
<div className="text-xs font-mono font-bold px-2 py-1 rounded-md" style={{
color,
backgroundColor: `${color}10`,
border: `1px solid ${color}30`
}}>
<div className="text-xs font-mono font-bold px-2 py-1 rounded-md bg-white/20 backdrop-blur-sm text-white border border-white/30">
{percentage.toFixed(1)}%
</div>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4 relative">

<CardContent className="space-y-4 relative z-10">
<div className="grid grid-cols-2 gap-4 text-xs">
<div className="space-y-1">
<div className="flex justify-between">
<span className="text-muted-foreground">Used:</span>
<span className="font-mono font-semibold text-foreground">{used}</span>
<span className="text-white/70">Used:</span>
<span className="font-mono font-semibold text-white">{used}</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Free:</span>
<span className="font-mono font-semibold text-foreground">{free}</span>
<span className="text-white/70">Free:</span>
<span className="font-mono font-semibold text-white">{free}</span>
</div>
</div>
<div className="space-y-1">
<div className="flex justify-between">
<span className="text-muted-foreground">Total:</span>
<span className="font-mono font-semibold text-foreground">{total}</span>
<span className="text-white/70">Total:</span>
<span className="font-mono font-semibold text-white">{total}</span>
</div>
{additionalInfo && (
<div className="flex justify-between">
<span className="text-muted-foreground">Cores:</span>
<span className="font-mono font-semibold text-foreground">{additionalInfo}</span>
<span className="text-white/70">Cores:</span>
<span className="font-mono font-semibold text-white">{additionalInfo}</span>
</div>
)}
</div>
</div>
<div className="w-full bg-muted/40 rounded-full h-3 overflow-hidden shadow-inner">

<div className="w-full bg-white/20 rounded-full h-3 overflow-hidden shadow-inner backdrop-blur-sm">
<div
className="h-3 rounded-full transition-all duration-700 ease-out relative overflow-hidden"
style={{
width: `${Math.min(percentage, 100)}%`,
backgroundColor: color,
boxShadow: `0 0 12px ${color}50, inset 0 1px 0 rgba(255,255,255,0.2)`
}}
className="h-3 rounded-full transition-all duration-700 ease-out relative overflow-hidden bg-white/80"
style={{ width: `${Math.min(percentage, 100)}%` }}
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-pulse" />
<div className="absolute inset-0 bg-gradient-to-t from-black/10 to-white/10" />
Expand All @@ -116,54 +119,90 @@ export const ServerMetricsOverview = ({ server }: ServerMetricsOverviewProps) =>
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-6">
{/* Status Card */}
<Card className="relative overflow-hidden bg-gradient-to-br from-card/80 via-card to-card/60 border border-border/60 shadow-lg hover:shadow-xl hover:border-border/80 transition-all duration-300 backdrop-blur-sm group">
<div className="absolute inset-0 bg-gradient-to-br from-transparent via-white/[0.02] to-white/[0.05] opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<CardHeader className="pb-3 relative">
<Card
className="border-none rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl transform hover:-translate-y-1 relative"
style={{
background: theme === 'dark'
? "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, rgba(59, 130, 246, 0.6) 100%)"
: "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, #3b82f6 100%)"
}}
>
{/* Grid Pattern Overlay */}
<div className="absolute inset-0 z-0 opacity-10">
<div
className="w-full h-full"
style={{
backgroundImage: `linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px)`,
backgroundSize: '20px 20px'
}}
/>
</div>

<CardHeader className="pb-3 relative z-10">
<CardTitle className="flex items-center gap-3 text-sm font-semibold">
<div className="p-2.5 rounded-xl bg-primary/15 shadow-sm ring-1 ring-white/10 transition-all duration-300 group-hover:scale-110" style={{ boxShadow: '0 4px 12px rgba(59, 130, 246, 0.2)' }}>
<Activity className="h-4 w-4 text-primary" />
<div className="p-2.5 rounded-xl bg-white/20 backdrop-blur-sm shadow-sm transition-all duration-300 group-hover:scale-110">
<Activity className="h-4 w-4 text-white" />
</div>
<span className="text-foreground/90">Status</span>
<span className="text-white">Status</span>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4 relative">
<div className={`text-lg font-bold capitalize ${getStatusColor(server.status)} flex items-center gap-3`}>
<div className={`w-3 h-3 rounded-full ${server.status === 'up' ? 'bg-green-500' : server.status === 'down' ? 'bg-red-500' : 'bg-yellow-500'} animate-pulse shadow-sm`} style={{
boxShadow: `0 0 8px ${server.status === 'up' ? '#10b981' : server.status === 'down' ? '#ef4444' : '#f59e0b'}`
}} />

<CardContent className="space-y-4 relative z-10">
<div className={`text-lg font-bold capitalize flex items-center gap-3 text-white`}>
<div className={`w-3 h-3 rounded-full ${server.status === 'up' ? 'bg-green-400' : server.status === 'down' ? 'bg-red-400' : 'bg-yellow-400'} animate-pulse shadow-sm`} />
{server.status}
</div>
<div className="space-y-2 text-xs">
<div className="flex justify-between py-1">
<span className="text-muted-foreground">Agent:</span>
<span className="font-semibold text-foreground">{server.agent_status}</span>
<span className="text-white/70">Agent:</span>
<span className="font-semibold text-white">{server.agent_status}</span>
</div>
<div className="flex justify-between py-1">
<span className="text-muted-foreground">Connection:</span>
<span className="font-semibold text-foreground">{server.connection}</span>
<span className="text-white/70">Connection:</span>
<span className="font-semibold text-white">{server.connection}</span>
</div>
</div>
</CardContent>
</Card>

{/* Uptime Card */}
<Card className="relative overflow-hidden bg-gradient-to-br from-card/80 via-card to-card/60 border border-border/60 shadow-lg hover:shadow-xl hover:border-border/80 transition-all duration-300 backdrop-blur-sm group">
<div className="absolute inset-0 bg-gradient-to-br from-transparent via-white/[0.02] to-white/[0.05] opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<CardHeader className="pb-3 relative">
<Card
className="border-none rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl transform hover:-translate-y-1 relative"
style={{
background: theme === 'dark'
? "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, rgba(34, 197, 94, 0.6) 100%)"
: "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, #22c55e 100%)"
}}
>
{/* Grid Pattern Overlay */}
<div className="absolute inset-0 z-0 opacity-10">
<div
className="w-full h-full"
style={{
backgroundImage: `linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px)`,
backgroundSize: '20px 20px'
}}
/>
</div>

<CardHeader className="pb-3 relative z-10">
<CardTitle className="flex items-center gap-3 text-sm font-semibold">
<div className="p-2.5 rounded-xl bg-blue-500/15 shadow-sm ring-1 ring-white/10 transition-all duration-300 group-hover:scale-110" style={{ boxShadow: '0 4px 12px rgba(59, 130, 246, 0.2)' }}>
<Clock className="h-4 w-4 text-blue-500" />
<div className="p-2.5 rounded-xl bg-white/20 backdrop-blur-sm shadow-sm transition-all duration-300 group-hover:scale-110">
<Clock className="h-4 w-4 text-white" />
</div>
<span className="text-foreground/90">Uptime</span>
<span className="text-white">Uptime</span>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4 relative">
<div className="text-lg font-bold text-blue-500">

<CardContent className="space-y-4 relative z-10">
<div className="text-lg font-bold text-white">
{server.uptime}
</div>
<div className="text-xs text-muted-foreground space-y-1">
<div className="text-xs text-white/70 space-y-1">
<div>Last Check:</div>
<div className="font-mono text-[10px] text-foreground/80 bg-muted/30 px-2 py-1 rounded">
<div className="font-mono text-[10px] text-white/90 bg-white/10 px-2 py-1 rounded backdrop-blur-sm">
{new Date(server.last_checked).toLocaleString()}
</div>
</div>
Expand All @@ -179,6 +218,10 @@ export const ServerMetricsOverview = ({ server }: ServerMetricsOverviewProps) =>
percentage={cpuUsagePercent}
icon={Cpu}
color={theme === 'dark' ? "#3b82f6" : "#2563eb"}
gradient={theme === 'dark'
? "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, rgba(59, 130, 246, 0.6) 100%)"
: "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, #3b82f6 100%)"
}
additionalInfo={server.cpu_cores?.toString()}
/>

Expand All @@ -191,6 +234,10 @@ export const ServerMetricsOverview = ({ server }: ServerMetricsOverviewProps) =>
percentage={ramUsagePercent}
icon={MemoryStick}
color={theme === 'dark' ? "#10b981" : "#059669"}
gradient={theme === 'dark'
? "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, rgba(16, 185, 129, 0.6) 100%)"
: "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, #10b981 100%)"
}
/>

{/* Disk Metric */}
Expand All @@ -202,6 +249,10 @@ export const ServerMetricsOverview = ({ server }: ServerMetricsOverviewProps) =>
percentage={diskUsagePercent}
icon={HardDrive}
color={theme === 'dark' ? "#f59e0b" : "#d97706"}
gradient={theme === 'dark'
? "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, rgba(245, 158, 11, 0.6) 100%)"
: "linear-gradient(135deg, rgba(65, 59, 55, 0.8) 0%, #f59e0b 100%)"
}
/>
</div>
);
Expand Down
Loading