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
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ export const SidebarHeader: React.FC<SidebarHeaderProps> = ({ collapsed }) => {

return (
<div className={`p-4 ${theme === 'dark' ? 'border-[#1e1e1e]' : 'border-sidebar-border'} border-b flex items-center ${collapsed ? 'justify-center' : ''}`}>
<div className="h-8 w-8 bg-green-500 rounded flex items-center justify-center mr-2">
<span className="text-white font-bold">C</span>
<div className="h-8 w-8 bg-gray-600 rounded flex items-center justify-center mr-2">
<img
src="/favicon.ico"
alt="CheckCle"
className="h-6 w-6"
/>
</div>
{!collapsed && <h1 className="text-xl font-semibold">CheckCle App</h1>}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { Globe, Boxes, Radar, Calendar, BarChart2, LineChart, MapPin, Settings, User, Bell, Database, Info, BookOpen } from "lucide-react";
import { Globe, Boxes, Layers, Calendar, BarChart2, LineChart, MapPin, Settings, User, Bell, Database, Info, BookOpen } from "lucide-react";

export const mainMenuItems = [
{
Expand All @@ -21,7 +21,7 @@ export const mainMenuItems = [
{
id: 'ssl-domain',
path: '/ssl-domain',
icon: Radar,
icon: Layers,
translationKey: 'sslDomain',
color: 'text-cyan-400',
hasNavigation: true
Expand Down
32 changes: 0 additions & 32 deletions application/src/components/docker/table/DockerRowActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,6 @@ export const DockerRowActions = ({ container, containerStatus, onContainerAction
<Eye className="mr-2 h-4 w-4" />
View Details
</DropdownMenuItem>
<DropdownMenuSeparator className="bg-border" />
<DropdownMenuItem
onClick={() => onContainerAction(containerStatus === 'running' ? 'stop' : 'start', container.id, container.name)}
className="cursor-pointer hover:bg-muted"
>
{containerStatus === 'running' ? (
<>
<Square className="mr-2 h-4 w-4" />
Stop Container
</>
) : (
<>
<Play className="mr-2 h-4 w-4" />
Start Container
</>
)}
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => onContainerAction('restart', container.id, container.name)}
className="cursor-pointer hover:bg-muted"
>
<RefreshCw className="mr-2 h-4 w-4" />
Restart Container
</DropdownMenuItem>
<DropdownMenuSeparator className="bg-border" />
<DropdownMenuItem
onClick={() => onContainerAction('delete', container.id, container.name)}
className="cursor-pointer hover:bg-muted text-destructive focus:text-destructive"
>
<Trash2 className="mr-2 h-4 w-4" />
Remove Container
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const DockerTableRow = ({ container, onRowClick, onContainerAction, onVie
<div className="font-semibold text-sm sm:text-base text-foreground">{container.name}</div>
<div className="text-xs sm:text-sm text-muted-foreground">
<div className="font-mono">{container.docker_id}</div>
<div className="font-mono">{container.hostname}</div>
</div>
</div>
</TableCell>
Expand Down
7 changes: 5 additions & 2 deletions application/src/components/servers/ServerHistoryCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ export const ServerHistoryCharts = ({ serverId }: ServerHistoryChartsProps) => {
} = useQuery({
queryKey: ['server-metrics-history', serverId, timeRange],
queryFn: async () => {
console.log('ServerHistoryCharts: Fetching metrics for serverId:', serverId);
console.log('ServerHistoryCharts: Fetching metrics for serverId:', serverId, 'timeRange:', timeRange);
const result = await serverService.getServerMetrics(serverId, timeRange);
console.log('ServerHistoryCharts: Raw metrics result:', result);
console.log('ServerHistoryCharts: Raw metrics result for timeRange', timeRange, ':', result?.length || 0, 'records');
console.log('ServerHistoryCharts: First 3 records:', result?.slice(0, 3));
return result;
},
enabled: !!serverId,
Expand All @@ -47,7 +48,9 @@ export const ServerHistoryCharts = ({ serverId }: ServerHistoryChartsProps) => {
timeRange
});

console.log('ServerHistoryCharts: About to format chart data with', metrics?.length || 0, 'metrics for timeRange:', timeRange);
const chartData = formatChartData(metrics, timeRange);
console.log('ServerHistoryCharts: After formatting, got', chartData?.length || 0, 'chart data points');

const getGridColor = () => theme === 'dark' ? '#374151' : '#e5e7eb';
const getAxisColor = () => theme === 'dark' ? '#9ca3af' : '#6b7280';
Expand Down
29 changes: 27 additions & 2 deletions application/src/components/servers/charts/dataUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,24 @@ export const filterMetricsByTimeRange = (metrics: any[], timeRange: TimeRange):
if (!selectedRange) return metrics;

const cutoffTime = new Date(now.getTime() - (selectedRange.hours * 60 * 60 * 1000));
console.log('filterMetricsByTimeRange: timeRange:', timeRange, 'cutoffTime:', cutoffTime.toISOString(), 'now:', now.toISOString());

return metrics.filter(metric => {
const filtered = metrics.filter(metric => {
const metricTime = new Date(metric.created || metric.timestamp);
return metricTime >= cutoffTime;
const isValid = metricTime >= cutoffTime;
if (!isValid && metrics.indexOf(metric) < 3) {
console.log('filterMetricsByTimeRange: Filtered out metric:', {
metricTime: metricTime.toISOString(),
cutoffTime: cutoffTime.toISOString(),
created: metric.created,
timestamp: metric.timestamp
});
}
return isValid;
});

console.log('filterMetricsByTimeRange: Filtered', metrics.length, 'to', filtered.length, 'metrics');
return filtered;
};

const formatTimestamp = (timestamp: string, timeRange: TimeRange): string => {
Expand Down Expand Up @@ -95,7 +108,19 @@ const formatTimestamp = (timestamp: string, timeRange: TimeRange): string => {
};

export const formatChartData = (metrics: any[], timeRange: TimeRange) => {
console.log('formatChartData: Input metrics count:', metrics?.length || 0, 'timeRange:', timeRange);

const filteredMetrics = filterMetricsByTimeRange(metrics, timeRange);
console.log('formatChartData: After time filtering:', filteredMetrics?.length || 0, 'metrics');

if (filteredMetrics.length > 0) {
console.log('formatChartData: First filtered metric:', filteredMetrics[0]);
console.log('formatChartData: Sample timestamps:', filteredMetrics.slice(0, 3).map(m => ({
created: m.created,
timestamp: m.timestamp,
both: new Date(m.created || m.timestamp).toISOString()
})));
}

return filteredMetrics.slice(0, 100).reverse().map((metric, index) => {
const cpuUsage = typeof metric.cpu_usage === 'string' ?
Expand Down
123 changes: 115 additions & 8 deletions application/src/services/serverService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,20 @@ export const serverService = {
console.log('serverService.getServerMetrics: Could not fetch server details:', error);
}

// Use the server's server_id field if available, otherwise use the serverId
// Try multiple filter strategies to find data
let filter = '';
let metricsServerId = serverId;

// Strategy 1: Use server.server_id if available
if (server && server.server_id) {
metricsServerId = server.server_id;
console.log('serverService.getServerMetrics: Using server.server_id for metrics:', metricsServerId);
filter = `server_id = "${metricsServerId}"`;
console.log('serverService.getServerMetrics: Strategy 1 - Using server.server_id for metrics:', metricsServerId);
} else {
// Strategy 2: Use the serverId directly
filter = `server_id = "${serverId}"`;
console.log('serverService.getServerMetrics: Strategy 2 - Using serverId directly for metrics:', serverId);
}

// Build filter for server_id and time range
let filter = `server_id = "${metricsServerId}"`;

// Add agent_id filter if available in server data
if (server && server.agent_id) {
Expand Down Expand Up @@ -78,19 +83,121 @@ export const serverService = {

const cutoffISO = cutoffTime.toISOString();
filter += ` && created >= "${cutoffISO}"`;
console.log('serverService.getServerMetrics: Using time filter:', cutoffISO);
console.log('serverService.getServerMetrics: Using time filter from:', cutoffISO, 'to now');
}

console.log('serverService.getServerMetrics: Final filter:', filter);

// Fetch filtered records with proper sorting
const records = await pb.collection('server_metrics').getFullList({
let records = await pb.collection('server_metrics').getFullList({
filter: filter,
sort: '-created',
requestKey: null
});

console.log('serverService.getServerMetrics: Found', records.length, 'records with filter');
console.log('serverService.getServerMetrics: Found', records.length, 'records with primary filter');

// If no records found with primary strategy, try fallback strategies
if (records.length === 0) {
console.log('serverService.getServerMetrics: No records found, trying fallback strategies...');

// Fallback 1: Try without agent_id filter
let fallbackFilter = `server_id = "${metricsServerId}"`;
if (timeRange) {
const now = new Date();
let cutoffTime;

switch (timeRange) {
case '60m':
cutoffTime = new Date(now.getTime() - (60 * 60 * 1000));
break;
case '1d':
cutoffTime = new Date(now.getTime() - (24 * 60 * 60 * 1000));
break;
case '7d':
cutoffTime = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));
break;
case '1m':
cutoffTime = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));
break;
case '3m':
cutoffTime = new Date(now.getTime() - (90 * 24 * 60 * 60 * 1000));
break;
default:
cutoffTime = new Date(now.getTime() - (24 * 60 * 60 * 1000));
}

const cutoffISO = cutoffTime.toISOString();
fallbackFilter += ` && created >= "${cutoffISO}"`;
}

console.log('serverService.getServerMetrics: Trying fallback filter without agent_id:', fallbackFilter);
records = await pb.collection('server_metrics').getFullList({
filter: fallbackFilter,
sort: '-created',
requestKey: null
});

console.log('serverService.getServerMetrics: Fallback found', records.length, 'records');

// Fallback 2: Try with different server_id strategies
if (records.length === 0) {
const alternativeIds = [serverId, server?.server_id, server?.id].filter(Boolean);
console.log('serverService.getServerMetrics: Trying alternative server IDs:', alternativeIds);

for (const altId of alternativeIds) {
if (altId && altId !== metricsServerId) {
let altFilter = `server_id = "${altId}"`;
if (timeRange) {
const now = new Date();
let cutoffTime;

switch (timeRange) {
case '60m':
cutoffTime = new Date(now.getTime() - (60 * 60 * 1000));
break;
case '1d':
cutoffTime = new Date(now.getTime() - (24 * 60 * 60 * 1000));
break;
case '7d':
cutoffTime = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));
break;
case '1m':
cutoffTime = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));
break;
case '3m':
cutoffTime = new Date(now.getTime() - (90 * 24 * 60 * 60 * 1000));
break;
default:
cutoffTime = new Date(now.getTime() - (24 * 60 * 60 * 1000));
}

const cutoffISO = cutoffTime.toISOString();
altFilter += ` && created >= "${cutoffISO}"`;
}

console.log('serverService.getServerMetrics: Trying alternative ID filter:', altFilter);
const altRecords = await pb.collection('server_metrics').getFullList({
filter: altFilter,
sort: '-created',
requestKey: null
});

if (altRecords.length > 0) {
console.log('serverService.getServerMetrics: Alternative ID found', altRecords.length, 'records');
records = altRecords;
break;
}
}
}
}
}

console.log('serverService.getServerMetrics: Final result:', records.length, 'records found');
if (records.length > 0) {
console.log('serverService.getServerMetrics: Sample record:', records[0]);
}

return records;
} catch (error) {
console.error('Error fetching server metrics:', error);
Expand Down
9 changes: 5 additions & 4 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@ if [ ! -f /mnt/pb_data/data.db ] && [ -d /app/pb_data ] && [ "$(ls -A /app/pb_da
fi

# Start PocketBase in the background
echo "Starting PocketBase..."
echo "Starting CheckCle Application..."
/app/pocketbase serve --http=0.0.0.0:8090 --dir /mnt/pb_data 2>&1 | grep -vE 'REST API|Dashboard' &

# Wait for PocketBase to become available
echo "Waiting for PocketBase to become available..."
echo "Waiting for Backend Server to become available..."
until curl -s http://localhost:8090/api/health >/dev/null; do
echo "Waiting on http://localhost:8090..."
sleep 1
done

echo "PocketBase is up!"
echo "Backend Server is up!"

# Start Go service
echo "Starting Go service..."
echo "Starting Go Operational service..."
/app/service-operation &

echo "Default Access: admin@example.com/Admin123456"
# Keep container alive
wait
36 changes: 36 additions & 0 deletions scripts/entrypoint_hide-admin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/sh

echo "Running on architecture: $(uname -m)"

# Copy PocketBase data if empty
if [ ! -f /mnt/pb_data/data.db ] && [ -d /app/pb_data ] && [ "$(ls -A /app/pb_data)" ]; then
cp -a /app/pb_data/. /mnt/pb_data/
fi

# Start PocketBase in the background with no admin UI and filtered logs
echo "Starting CheckCle Application..."
(
/app/pocketbase serve \
--http=0.0.0.0:8090 \
--dir /mnt/pb_data \
--no-admin \
2>&1 | grep -vE 'REST API|Dashboard'
) &

# Wait for PocketBase to become available
echo "Waiting for Backend Server to become available..."
until curl -s http://localhost:8090/api/health >/dev/null; do
echo "Waiting on http://localhost:8090..."
sleep 1
done

echo "Backend Server is up!"

# Start Go service
echo "Starting Go Operational service..."
/app/service-operation &

echo "Default Access: admin@example.com/Admin123456"

# Keep container alive
wait