diff --git a/application/src/components/dashboard/sidebar/SidebarHeader.tsx b/application/src/components/dashboard/sidebar/SidebarHeader.tsx index 4c0564b..4ba177c 100644 --- a/application/src/components/dashboard/sidebar/SidebarHeader.tsx +++ b/application/src/components/dashboard/sidebar/SidebarHeader.tsx @@ -11,8 +11,12 @@ export const SidebarHeader: React.FC = ({ collapsed }) => { return (
-
- C +
+ CheckCle
{!collapsed &&

CheckCle App

}
diff --git a/application/src/components/dashboard/sidebar/navigationData.ts b/application/src/components/dashboard/sidebar/navigationData.ts index 0e2685f..3fd768a 100644 --- a/application/src/components/dashboard/sidebar/navigationData.ts +++ b/application/src/components/dashboard/sidebar/navigationData.ts @@ -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 = [ { @@ -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 diff --git a/application/src/components/docker/table/DockerRowActions.tsx b/application/src/components/docker/table/DockerRowActions.tsx index 5ec429f..e85bb27 100644 --- a/application/src/components/docker/table/DockerRowActions.tsx +++ b/application/src/components/docker/table/DockerRowActions.tsx @@ -35,38 +35,6 @@ export const DockerRowActions = ({ container, containerStatus, onContainerAction View Details - - onContainerAction(containerStatus === 'running' ? 'stop' : 'start', container.id, container.name)} - className="cursor-pointer hover:bg-muted" - > - {containerStatus === 'running' ? ( - <> - - Stop Container - - ) : ( - <> - - Start Container - - )} - - onContainerAction('restart', container.id, container.name)} - className="cursor-pointer hover:bg-muted" - > - - Restart Container - - - onContainerAction('delete', container.id, container.name)} - className="cursor-pointer hover:bg-muted text-destructive focus:text-destructive" - > - - Remove Container - ); diff --git a/application/src/components/docker/table/DockerTableRow.tsx b/application/src/components/docker/table/DockerTableRow.tsx index 910d69a..119037a 100644 --- a/application/src/components/docker/table/DockerTableRow.tsx +++ b/application/src/components/docker/table/DockerTableRow.tsx @@ -46,7 +46,6 @@ export const DockerTableRow = ({ container, onRowClick, onContainerAction, onVie
{container.name}
{container.docker_id}
-
{container.hostname}
diff --git a/application/src/components/servers/ServerHistoryCharts.tsx b/application/src/components/servers/ServerHistoryCharts.tsx index b9b0cce..870b0ee 100644 --- a/application/src/components/servers/ServerHistoryCharts.tsx +++ b/application/src/components/servers/ServerHistoryCharts.tsx @@ -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, @@ -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'; diff --git a/application/src/components/servers/charts/dataUtils.ts b/application/src/components/servers/charts/dataUtils.ts index 5e0ef91..4e0ca53 100644 --- a/application/src/components/servers/charts/dataUtils.ts +++ b/application/src/components/servers/charts/dataUtils.ts @@ -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 => { @@ -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' ? diff --git a/application/src/services/serverService.ts b/application/src/services/serverService.ts index eb2b2d7..e259df5 100644 --- a/application/src/services/serverService.ts +++ b/application/src/services/serverService.ts @@ -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) { @@ -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); diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 17b40f6..6b4e68e 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -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 diff --git a/scripts/entrypoint_hide-admin.sh b/scripts/entrypoint_hide-admin.sh new file mode 100644 index 0000000..e2f4f32 --- /dev/null +++ b/scripts/entrypoint_hide-admin.sh @@ -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