Fix jwt-token
This commit is contained in:
@@ -128,33 +128,83 @@ router.get('/system-info', async (req, res) => {
|
||||
const tenantCount = await Tenant.count();
|
||||
const userCount = await User.count();
|
||||
|
||||
// Get container metrics using Docker stats
|
||||
// Get container metrics using internal health endpoints
|
||||
let containerMetrics = {};
|
||||
|
||||
const containerEndpoints = [
|
||||
{ name: 'drone-detection-backend', url: 'http://drone-detection-backend:3000/health/metrics' },
|
||||
{ name: 'drone-detection-frontend', url: 'http://drone-detection-frontend:80/health/metrics' },
|
||||
{ name: 'drone-detection-management', url: 'http://drone-detection-management:3001/health/metrics' }
|
||||
];
|
||||
|
||||
// Try internal container health endpoints first
|
||||
try {
|
||||
const { stdout } = await execAsync('docker stats --no-stream --format "table {{.Container}}\\t{{.CPUPerc}}\\t{{.MemUsage}}\\t{{.MemPerc}}\\t{{.NetIO}}\\t{{.BlockIO}}"');
|
||||
const lines = stdout.trim().split('\n').slice(1); // Remove header
|
||||
const fetch = require('node-fetch');
|
||||
const healthChecks = await Promise.allSettled(
|
||||
containerEndpoints.map(async ({ name, url }) => {
|
||||
const response = await fetch(url, { timeout: 3000 });
|
||||
const metrics = await response.json();
|
||||
return { name, metrics };
|
||||
})
|
||||
);
|
||||
|
||||
containerMetrics = lines.reduce((acc, line) => {
|
||||
const [container, cpu, memUsage, memPerc, netIO, blockIO] = line.split('\t');
|
||||
if (container.includes('drone-detection') || container.includes('uamils')) {
|
||||
acc[container] = {
|
||||
cpu: cpu,
|
||||
memory: {
|
||||
usage: memUsage,
|
||||
percentage: memPerc
|
||||
},
|
||||
network: netIO,
|
||||
disk: blockIO
|
||||
healthChecks.forEach((result, index) => {
|
||||
const containerName = containerEndpoints[index].name;
|
||||
if (result.status === 'fulfilled') {
|
||||
containerMetrics[containerName] = result.value.metrics;
|
||||
} else {
|
||||
containerMetrics[containerName] = {
|
||||
status: 'health_check_failed',
|
||||
error: result.reason?.message || 'Health endpoint unavailable'
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
} catch (dockerError) {
|
||||
console.log('Docker stats not available:', dockerError.message);
|
||||
containerMetrics = {
|
||||
error: 'Docker not available or containers not running',
|
||||
message: dockerError.message
|
||||
};
|
||||
});
|
||||
} catch (healthError) {
|
||||
console.log('Container health checks failed, trying Docker stats...');
|
||||
|
||||
// Fallback to Docker stats if health endpoints fail
|
||||
try {
|
||||
const { stdout } = await execAsync('docker stats --no-stream --format "table {{.Container}}\\t{{.CPUPerc}}\\t{{.MemUsage}}\\t{{.MemPerc}}\\t{{.NetIO}}\\t{{.BlockIO}}"');
|
||||
const lines = stdout.trim().split('\n').slice(1);
|
||||
|
||||
containerMetrics = lines.reduce((acc, line) => {
|
||||
const [container, cpu, memUsage, memPerc, netIO, blockIO] = line.split('\t');
|
||||
if (container.includes('drone-detection') || container.includes('uamils')) {
|
||||
acc[container] = {
|
||||
cpu: cpu,
|
||||
memory: { usage: memUsage, percentage: memPerc },
|
||||
network: netIO,
|
||||
disk: blockIO,
|
||||
source: 'docker_stats'
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
} catch (dockerError) {
|
||||
// Try container inspection via docker compose
|
||||
try {
|
||||
const { stdout: composeStatus } = await execAsync('docker-compose ps --format json');
|
||||
const containers = JSON.parse(`[${composeStatus.split('\n').filter(line => line.trim()).join(',')}]`);
|
||||
|
||||
containerMetrics = containers.reduce((acc, container) => {
|
||||
if (container.Name && (container.Name.includes('drone-detection') || container.Name.includes('uamils'))) {
|
||||
acc[container.Name] = {
|
||||
status: container.State,
|
||||
health: container.Health || 'unknown',
|
||||
ports: container.Ports,
|
||||
source: 'docker_compose'
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
} catch (composeError) {
|
||||
containerMetrics = {
|
||||
error: 'All container monitoring methods failed',
|
||||
attempts: ['health_endpoints', 'docker_stats', 'docker_compose'],
|
||||
lastError: composeError.message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get system memory and CPU info
|
||||
|
||||
170
server/utils/health-endpoint.js
Normal file
170
server/utils/health-endpoint.js
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Container Health & Metrics Endpoint
|
||||
* Add this to your main application containers for self-reporting
|
||||
*/
|
||||
|
||||
const express = require('express');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const { exec } = require('child_process');
|
||||
const { promisify } = require('util');
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
/**
|
||||
* Health & Metrics endpoint implementation
|
||||
* Add this to your Express app in each container
|
||||
*/
|
||||
const createHealthEndpoint = (app) => {
|
||||
app.get('/health/metrics', async (req, res) => {
|
||||
try {
|
||||
const containerName = process.env.CONTAINER_NAME || 'unknown-container';
|
||||
const memUsage = process.memoryUsage();
|
||||
const cpuUsage = process.cpuUsage();
|
||||
|
||||
// Get system load average
|
||||
const loadAvg = os.loadavg();
|
||||
|
||||
// Get network connections (if available)
|
||||
let networkConnections = 'N/A';
|
||||
try {
|
||||
const { stdout } = await execAsync('netstat -an | grep ESTABLISHED | wc -l');
|
||||
networkConnections = parseInt(stdout.trim());
|
||||
} catch (e) {
|
||||
// Network info not available
|
||||
}
|
||||
|
||||
// Get disk usage for common paths
|
||||
let diskUsage = {};
|
||||
try {
|
||||
const paths = ['/tmp', '/var/log', '/app'];
|
||||
for (const path of paths) {
|
||||
if (fs.existsSync(path)) {
|
||||
const stats = fs.statSync(path);
|
||||
diskUsage[path] = `${Math.round(stats.size / 1024 / 1024)}MB`;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
diskUsage = { error: 'Disk info unavailable' };
|
||||
}
|
||||
|
||||
// Calculate CPU percentage (approximate)
|
||||
const cpuPercent = ((cpuUsage.user + cpuUsage.system) / 1000000 / process.uptime() * 100).toFixed(1);
|
||||
|
||||
const metrics = {
|
||||
container: containerName,
|
||||
timestamp: new Date().toISOString(),
|
||||
uptime: Math.round(process.uptime()),
|
||||
health: 'healthy',
|
||||
version: process.env.APP_VERSION || '1.0.0',
|
||||
|
||||
// Memory metrics
|
||||
memory: {
|
||||
usage: `${Math.round(memUsage.heapUsed / 1024 / 1024)}MB / ${Math.round(memUsage.heapTotal / 1024 / 1024)}MB`,
|
||||
percentage: `${Math.round((memUsage.heapUsed / memUsage.heapTotal) * 100)}%`,
|
||||
rss: `${Math.round(memUsage.rss / 1024 / 1024)}MB`,
|
||||
external: `${Math.round(memUsage.external / 1024 / 1024)}MB`
|
||||
},
|
||||
|
||||
// CPU metrics
|
||||
cpu: `${cpuPercent}%`,
|
||||
|
||||
// System metrics
|
||||
system: {
|
||||
platform: os.platform(),
|
||||
arch: os.arch(),
|
||||
nodeVersion: process.version,
|
||||
loadAverage: loadAvg[0].toFixed(2)
|
||||
},
|
||||
|
||||
// Network metrics
|
||||
network: {
|
||||
connections: networkConnections,
|
||||
requests_handled: global.requestCounter || 0
|
||||
},
|
||||
|
||||
// Disk metrics
|
||||
disk: diskUsage,
|
||||
|
||||
// Additional app-specific metrics
|
||||
application: {
|
||||
environment: process.env.NODE_ENV || 'development',
|
||||
pid: process.pid,
|
||||
ppid: process.ppid
|
||||
}
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: metrics,
|
||||
source: 'internal_health_endpoint'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to collect metrics',
|
||||
message: error.message,
|
||||
container: process.env.CONTAINER_NAME || 'unknown-container'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Simple health check endpoint
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'healthy',
|
||||
timestamp: new Date().toISOString(),
|
||||
uptime: process.uptime(),
|
||||
container: process.env.CONTAINER_NAME || 'unknown-container'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Middleware to count requests (for metrics)
|
||||
*/
|
||||
const requestCounter = (req, res, next) => {
|
||||
global.requestCounter = (global.requestCounter || 0) + 1;
|
||||
next();
|
||||
};
|
||||
|
||||
/**
|
||||
* Enhanced logging for metrics
|
||||
*/
|
||||
const logMetrics = () => {
|
||||
const memUsage = process.memoryUsage();
|
||||
const metrics = {
|
||||
timestamp: new Date().toISOString(),
|
||||
container: process.env.CONTAINER_NAME || 'unknown-container',
|
||||
memory_mb: Math.round(memUsage.heapUsed / 1024 / 1024),
|
||||
uptime_seconds: Math.round(process.uptime()),
|
||||
requests_handled: global.requestCounter || 0
|
||||
};
|
||||
|
||||
console.log(`METRICS: ${JSON.stringify(metrics)}`);
|
||||
};
|
||||
|
||||
// Example usage in your main app:
|
||||
/*
|
||||
const app = express();
|
||||
|
||||
// Add request counter middleware
|
||||
app.use(requestCounter);
|
||||
|
||||
// Add health endpoints
|
||||
createHealthEndpoint(app);
|
||||
|
||||
// Log metrics every 30 seconds
|
||||
setInterval(logMetrics, 30000);
|
||||
|
||||
// Your other routes...
|
||||
app.listen(3000, () => {
|
||||
console.log('Server started with health endpoints');
|
||||
});
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
createHealthEndpoint,
|
||||
requestCounter,
|
||||
logMetrics
|
||||
};
|
||||
Reference in New Issue
Block a user