@aerocorp/cli
Version:
AeroCorp CLI 5.1.0 - Future-Proofed Enterprise Infrastructure with Live Preview, Tunneling & Advanced DevOps
279 lines (234 loc) ⢠9.82 kB
text/typescript
/**
* AeroCorp CLI 4.0.0 - Monitoring Service
* Advanced monitoring and observability for hybrid infrastructure
*/
import axios from 'axios';
import chalk from 'chalk';
import { ConfigService } from './config';
import { AuthService } from './auth';
export interface SystemMetrics {
timestamp: string;
cpu: number;
memory: number;
disk: number;
network: number;
services: ServiceMetric[];
alerts: Alert[];
}
export interface ServiceMetric {
name: string;
status: 'healthy' | 'degraded' | 'down';
responseTime: number;
uptime: string;
cpu?: number;
memory?: number;
}
export interface Alert {
id: number;
type: 'info' | 'warning' | 'error' | 'critical';
severity: 'low' | 'medium' | 'high' | 'critical';
message: string;
service?: string;
timestamp: string;
acknowledged: boolean;
}
export class MonitoringService {
private configService: ConfigService;
private authService: AuthService;
constructor() {
this.configService = new ConfigService();
this.authService = new AuthService();
}
async getMetrics(): Promise<SystemMetrics> {
try {
const config = await this.configService.getConfig();
const auth = await this.authService.getAuth();
const response = await axios.get(`${config.apiUrl}/api/monitoring/metrics`, {
headers: {
'Authorization': `Bearer ${auth.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
});
return response.data;
} catch (error) {
throw new Error(`Failed to get metrics: ${error.message}`);
}
}
async getAlerts(options: { acknowledged?: boolean; severity?: string } = {}): Promise<Alert[]> {
try {
const config = await this.configService.getConfig();
const auth = await this.authService.getAuth();
const params = new URLSearchParams();
if (options.acknowledged !== undefined) {
params.append('acknowledged', options.acknowledged.toString());
}
if (options.severity) {
params.append('severity', options.severity);
}
const response = await axios.get(`${config.apiUrl}/api/monitoring/alerts?${params}`, {
headers: {
'Authorization': `Bearer ${auth.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
});
return response.data.alerts;
} catch (error) {
throw new Error(`Failed to get alerts: ${error.message}`);
}
}
async acknowledgeAlert(alertId: number): Promise<void> {
try {
const config = await this.configService.getConfig();
const auth = await this.authService.getAuth();
await axios.post(`${config.apiUrl}/api/monitoring/alerts/${alertId}/acknowledge`, {}, {
headers: {
'Authorization': `Bearer ${auth.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
});
console.log(chalk.green(`ā Alert ${alertId} acknowledged`));
} catch (error) {
throw new Error(`Failed to acknowledge alert: ${error.message}`);
}
}
async getLogs(options: { service?: string; level?: string; limit?: number } = {}): Promise<any> {
try {
const config = await this.configService.getConfig();
const auth = await this.authService.getAuth();
const params = new URLSearchParams();
if (options.service) params.append('service', options.service);
if (options.level) params.append('level', options.level);
if (options.limit) params.append('limit', options.limit.toString());
const response = await axios.get(`${config.apiUrl}/api/monitoring/logs?${params}`, {
headers: {
'Authorization': `Bearer ${auth.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
});
return response.data;
} catch (error) {
throw new Error(`Failed to get logs: ${error.message}`);
}
}
async getUptime(): Promise<any> {
try {
const config = await this.configService.getConfig();
const auth = await this.authService.getAuth();
const response = await axios.get(`${config.apiUrl}/api/monitoring/uptime`, {
headers: {
'Authorization': `Bearer ${auth.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
});
return response.data;
} catch (error) {
throw new Error(`Failed to get uptime: ${error.message}`);
}
}
displayMetrics(metrics: SystemMetrics): void {
console.log(chalk.cyan.bold('\nš System Metrics'));
console.log(chalk.gray(`Last updated: ${new Date(metrics.timestamp).toLocaleString()}`));
console.log(chalk.white('\nš„ļø System Resources:'));
console.log(` CPU: ${this.getProgressBar(metrics.cpu)} ${metrics.cpu.toFixed(1)}%`);
console.log(` Memory: ${this.getProgressBar(metrics.memory)} ${metrics.memory.toFixed(1)}%`);
console.log(` Disk: ${this.getProgressBar(metrics.disk)} ${metrics.disk.toFixed(1)}%`);
console.log(` Network: ${this.getProgressBar(metrics.network)} ${metrics.network.toFixed(1)}%`);
console.log(chalk.white('\nš§ Services Status:'));
metrics.services.forEach(service => {
const statusIcon = service.status === 'healthy' ? 'ā
' :
service.status === 'degraded' ? 'ā ļø' : 'ā';
const statusColor = service.status === 'healthy' ? chalk.green :
service.status === 'degraded' ? chalk.yellow : chalk.red;
console.log(` ${statusIcon} ${chalk.white(service.name.padEnd(20))} ${statusColor(service.status.padEnd(10))} ${service.responseTime}ms`);
});
if (metrics.alerts.length > 0) {
console.log(chalk.white('\nšØ Active Alerts:'));
metrics.alerts.forEach(alert => {
const alertIcon = alert.type === 'critical' ? 'š“' :
alert.type === 'warning' ? 'š”' :
alert.type === 'error' ? 'š ' : 'šµ';
console.log(` ${alertIcon} ${chalk.white(alert.message)}`);
});
}
}
displayAlerts(alerts: Alert[]): void {
console.log(chalk.cyan.bold('\nšØ System Alerts'));
if (alerts.length === 0) {
console.log(chalk.green('ā
No active alerts'));
return;
}
alerts.forEach(alert => {
const alertIcon = alert.type === 'critical' ? 'š“' :
alert.type === 'warning' ? 'š”' :
alert.type === 'error' ? 'š ' : 'šµ';
const severityColor = alert.severity === 'critical' ? chalk.red :
alert.severity === 'high' ? chalk.red :
alert.severity === 'medium' ? chalk.yellow : chalk.blue;
console.log(`\n${alertIcon} ${severityColor.bold(alert.type.toUpperCase())} - ${alert.message}`);
if (alert.service) {
console.log(` Service: ${chalk.cyan(alert.service)}`);
}
console.log(` Time: ${chalk.gray(new Date(alert.timestamp).toLocaleString())}`);
console.log(` Acknowledged: ${alert.acknowledged ? chalk.green('Yes') : chalk.red('No')}`);
});
}
displayLogs(logs: any): void {
console.log(chalk.cyan.bold('\nš System Logs'));
console.log(chalk.gray(`Showing ${logs.logs.length} of ${logs.total} logs`));
logs.logs.forEach((log: any) => {
const levelColor = log.level === 'error' ? chalk.red :
log.level === 'warn' ? chalk.yellow :
log.level === 'info' ? chalk.blue : chalk.white;
const timestamp = new Date(log.timestamp).toLocaleTimeString();
console.log(`${chalk.gray(timestamp)} ${levelColor(log.level.toUpperCase().padEnd(5))} ${chalk.cyan(log.service.padEnd(15))} ${log.message}`);
});
}
displayUptime(uptime: any): void {
console.log(chalk.cyan.bold('\nā±ļø System Uptime'));
console.log(`Overall: ${chalk.green(uptime.overall.percentage + '%')} (${uptime.overall.downtime} downtime)`);
console.log(chalk.white('\nš§ Service Uptime:'));
uptime.services.forEach((service: any) => {
const statusIcon = service.status === 'operational' ? 'ā
' :
service.status === 'degraded' ? 'ā ļø' : 'ā';
console.log(` ${statusIcon} ${chalk.white(service.name.padEnd(20))} ${chalk.green(service.uptime + '%')}`);
});
if (uptime.incidents.length > 0) {
console.log(chalk.white('\nšØ Active Incidents:'));
uptime.incidents.forEach((incident: any) => {
console.log(` š“ ${chalk.white(incident.title)} - ${chalk.yellow(incident.status)}`);
});
}
}
private getProgressBar(percentage: number, width: number = 20): string {
const filled = Math.round((percentage / 100) * width);
const empty = width - filled;
const color = percentage > 80 ? chalk.red : percentage > 60 ? chalk.yellow : chalk.green;
return color('ā'.repeat(filled)) + chalk.gray('ā'.repeat(empty));
}
async startRealTimeMonitoring(interval: number = 5000): Promise<void> {
console.log(chalk.cyan.bold('š Starting real-time monitoring...'));
console.log(chalk.gray(`Refresh interval: ${interval / 1000}s`));
console.log(chalk.gray('Press Ctrl+C to stop\n'));
const monitor = setInterval(async () => {
try {
// Clear screen
process.stdout.write('\x1Bc');
const metrics = await this.getMetrics();
this.displayMetrics(metrics);
} catch (error) {
console.error(chalk.red('ā Monitoring error:'), error.message);
}
}, interval);
// Handle graceful shutdown
process.on('SIGINT', () => {
clearInterval(monitor);
console.log(chalk.yellow('\nā¹ļø Monitoring stopped'));
process.exit(0);
});
}
}