Fix iOS Safari auth loops and simplify admin dashboard
All checks were successful
Build And Push Image / docker (push) Successful in 3m4s
All checks were successful
Build And Push Image / docker (push) Successful in 3m4s
- Add session check throttling in useAuth to prevent iOS Safari authentication loops - Simplify admin dashboard by removing complex system metrics and stats - Remove system-metrics utility and streamline stats API endpoint - Update admin interface to focus on core user and role management
This commit is contained in:
@@ -1,190 +0,0 @@
|
||||
import si from 'systeminformation';
|
||||
|
||||
interface SystemMetrics {
|
||||
cpu: {
|
||||
usage: number;
|
||||
cores: number;
|
||||
model: string;
|
||||
};
|
||||
memory: {
|
||||
total: number;
|
||||
used: number;
|
||||
free: number;
|
||||
usagePercent: number;
|
||||
};
|
||||
disk: {
|
||||
total: number;
|
||||
used: number;
|
||||
free: number;
|
||||
usagePercent: number;
|
||||
};
|
||||
uptime: string;
|
||||
processes: {
|
||||
total: number;
|
||||
running: number;
|
||||
sleeping: number;
|
||||
};
|
||||
}
|
||||
|
||||
// Cache system metrics to avoid excessive system calls
|
||||
let metricsCache: SystemMetrics | null = null;
|
||||
let lastCacheTime = 0;
|
||||
const CACHE_DURATION = 30000; // 30 seconds
|
||||
|
||||
export async function getSystemMetrics(): Promise<SystemMetrics> {
|
||||
const now = Date.now();
|
||||
|
||||
// Return cached data if still valid
|
||||
if (metricsCache && (now - lastCacheTime) < CACHE_DURATION) {
|
||||
console.log('📊 Returning cached system metrics');
|
||||
return metricsCache;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🔄 Fetching fresh system metrics...');
|
||||
|
||||
// Get all metrics in parallel with individual error handling
|
||||
const results = await Promise.allSettled([
|
||||
si.cpu(),
|
||||
si.mem(),
|
||||
si.fsSize(),
|
||||
si.currentLoad(),
|
||||
si.processes(),
|
||||
si.time()
|
||||
]);
|
||||
|
||||
// Extract data with fallbacks for failed promises
|
||||
const cpuData = results[0].status === 'fulfilled' ? results[0].value : { cores: 0, brand: 'Unknown' };
|
||||
const memData = results[1].status === 'fulfilled' ? results[1].value : { total: 0, used: 0, free: 0 };
|
||||
const fsData = results[2].status === 'fulfilled' ? results[2].value : [];
|
||||
const currentLoad = results[3].status === 'fulfilled' ? results[3].value : { currentLoad: 0 };
|
||||
const processData = results[4].status === 'fulfilled' ? results[4].value : { all: 0, running: 0, sleeping: 0 };
|
||||
const uptimeData = results[5].status === 'fulfilled' ? results[5].value : { uptime: 0 };
|
||||
|
||||
// Log any failures
|
||||
results.forEach((result, index) => {
|
||||
if (result.status === 'rejected') {
|
||||
const names = ['CPU', 'Memory', 'Filesystem', 'CPU Load', 'Processes', 'Uptime'];
|
||||
console.warn(`⚠️ ${names[index]} data failed:`, result.reason?.message || result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate disk totals across all mounted filesystems
|
||||
const diskTotals = (fsData as any[]).reduce((acc: { total: number; used: number }, fs: any) => {
|
||||
// Skip special filesystems and focus on main storage
|
||||
if (fs.type && !['tmpfs', 'devtmpfs', 'proc', 'sysfs'].includes(fs.type.toLowerCase())) {
|
||||
acc.total += fs.size || 0;
|
||||
acc.used += fs.used || 0;
|
||||
}
|
||||
return acc;
|
||||
}, { total: 0, used: 0 });
|
||||
|
||||
const diskFree = diskTotals.total - diskTotals.used;
|
||||
const diskUsagePercent = diskTotals.total > 0 ? Math.round((diskTotals.used / diskTotals.total) * 100) : 0;
|
||||
|
||||
// Format uptime
|
||||
const formatUptime = (seconds: number): string => {
|
||||
const days = Math.floor(seconds / 86400);
|
||||
const hours = Math.floor((seconds % 86400) / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
|
||||
if (days > 0) {
|
||||
return `${days}d ${hours}h ${minutes}m`;
|
||||
} else if (hours > 0) {
|
||||
return `${hours}h ${minutes}m`;
|
||||
} else {
|
||||
return `${minutes}m`;
|
||||
}
|
||||
};
|
||||
|
||||
// Build metrics object
|
||||
const metrics: SystemMetrics = {
|
||||
cpu: {
|
||||
usage: Math.round(currentLoad.currentLoad || 0),
|
||||
cores: cpuData.cores || 0,
|
||||
model: cpuData.brand || 'Unknown'
|
||||
},
|
||||
memory: {
|
||||
total: memData.total || 0,
|
||||
used: memData.used || 0,
|
||||
free: memData.free || 0,
|
||||
usagePercent: memData.total > 0 ? Math.round((memData.used / memData.total) * 100) : 0
|
||||
},
|
||||
disk: {
|
||||
total: diskTotals.total,
|
||||
used: diskTotals.used,
|
||||
free: diskFree,
|
||||
usagePercent: diskUsagePercent
|
||||
},
|
||||
uptime: formatUptime(uptimeData.uptime || 0),
|
||||
processes: {
|
||||
total: processData.all || 0,
|
||||
running: processData.running || 0,
|
||||
sleeping: processData.sleeping || 0
|
||||
}
|
||||
};
|
||||
|
||||
// Cache the results
|
||||
metricsCache = metrics;
|
||||
lastCacheTime = now;
|
||||
|
||||
console.log('✅ System metrics fetched successfully:', {
|
||||
cpu: `${metrics.cpu.usage}%`,
|
||||
memory: `${metrics.memory.usagePercent}%`,
|
||||
disk: `${metrics.disk.usagePercent}%`,
|
||||
uptime: metrics.uptime
|
||||
});
|
||||
|
||||
return metrics;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to fetch system metrics:', error);
|
||||
|
||||
// Return fallback metrics on error
|
||||
const fallbackMetrics: SystemMetrics = {
|
||||
cpu: { usage: 0, cores: 0, model: 'Unknown' },
|
||||
memory: { total: 0, used: 0, free: 0, usagePercent: 0 },
|
||||
disk: { total: 0, used: 0, free: 0, usagePercent: 0 },
|
||||
uptime: '0m',
|
||||
processes: { total: 0, running: 0, sleeping: 0 }
|
||||
};
|
||||
|
||||
return fallbackMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to format bytes to human readable format
|
||||
export function formatBytes(bytes: number): string {
|
||||
if (bytes === 0) return '0 B';
|
||||
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
// Helper function to get system health status
|
||||
export function getSystemHealthStatus(metrics: SystemMetrics): 'healthy' | 'degraded' | 'unhealthy' {
|
||||
const { cpu, memory, disk } = metrics;
|
||||
|
||||
// Define thresholds
|
||||
const criticalThresholds = { cpu: 90, memory: 95, disk: 95 };
|
||||
const warningThresholds = { cpu: 70, memory: 80, disk: 85 };
|
||||
|
||||
// Check for critical issues
|
||||
if (cpu.usage > criticalThresholds.cpu ||
|
||||
memory.usagePercent > criticalThresholds.memory ||
|
||||
disk.usagePercent > criticalThresholds.disk) {
|
||||
return 'unhealthy';
|
||||
}
|
||||
|
||||
// Check for warning issues
|
||||
if (cpu.usage > warningThresholds.cpu ||
|
||||
memory.usagePercent > warningThresholds.memory ||
|
||||
disk.usagePercent > warningThresholds.disk) {
|
||||
return 'degraded';
|
||||
}
|
||||
|
||||
return 'healthy';
|
||||
}
|
||||
Reference in New Issue
Block a user