brainy/dist/cortex/performanceMonitor.js

371 lines
16 KiB
JavaScript
Raw Normal View History

/**
* Performance Monitor - Atomic Age Intelligence Observatory
*
* 🧠 Real-time performance tracking for vector + graph operations
* Monitors query performance, storage usage, and system health
* 🚀 Scalable performance analytics with atomic age aesthetics
*/
// @ts-ignore
import chalk from 'chalk';
// @ts-ignore
import boxen from 'boxen';
/**
* Real-time Performance Monitoring System
*/
export class PerformanceMonitor {
constructor(brainy) {
this.metrics = [];
this.alerts = [];
this.alertRules = [];
this.isMonitoring = false;
this.colors = {
primary: chalk.hex('#3A5F4A'),
success: chalk.hex('#2D4A3A'),
warning: chalk.hex('#D67441'),
error: chalk.hex('#B85C35'),
info: chalk.hex('#4A6B5A'),
dim: chalk.hex('#8A9B8A'),
highlight: chalk.hex('#E88B5A'),
accent: chalk.hex('#F5E6D3'),
brain: chalk.hex('#E88B5A')
};
this.emojis = {
brain: '🧠',
atom: '⚛️',
monitor: '📊',
alert: '🚨',
health: '💚',
warning: '⚠️',
critical: '🔥',
rocket: '🚀',
gear: '⚙️',
chart: '📈',
lightning: '⚡',
shield: '🛡️'
};
this.brainy = brainy;
this.initializeDefaultAlerts();
}
/**
* Start real-time monitoring
*/
async startMonitoring(intervalMs = 30000) {
if (this.isMonitoring) {
console.log(this.colors.warning('Monitoring already running'));
return;
}
console.log(boxen(`${this.emojis.monitor} ${this.colors.brain('ATOMIC PERFORMANCE OBSERVATORY')} ${this.emojis.atom}\n\n` +
`${this.colors.accent('◆')} ${this.colors.dim('Initiating neural performance monitoring')}` +
`${this.colors.accent('◆')} ${this.colors.dim('Monitoring Interval:')} ${this.colors.highlight(intervalMs + 'ms')}\n` +
`${this.colors.accent('◆')} ${this.colors.dim('Vector + Graph Analytics:')} ${this.colors.highlight('Enabled')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
this.isMonitoring = true;
this.monitoringInterval = setInterval(async () => {
try {
const metrics = await this.collectMetrics();
this.metrics.push(metrics);
// Keep only last 1000 metrics (rolling window)
if (this.metrics.length > 1000) {
this.metrics = this.metrics.slice(-1000);
}
// Check alerts
await this.checkAlerts(metrics);
}
catch (error) {
console.error('Error collecting metrics:', error);
}
}, intervalMs);
console.log(this.colors.success(`${this.emojis.rocket} Performance monitoring started - neural pathways under observation`));
}
/**
* Stop monitoring
*/
stopMonitoring() {
if (!this.isMonitoring) {
console.log(this.colors.warning('Monitoring not running'));
return;
}
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
}
this.isMonitoring = false;
console.log(this.colors.info(`${this.emojis.gear} Performance monitoring stopped`));
}
/**
* Get current performance metrics
*/
async getCurrentMetrics() {
return await this.collectMetrics();
}
/**
* Get performance dashboard data
*/
async getDashboard() {
const current = await this.collectMetrics();
const activeAlerts = this.alerts.filter(a => !a.resolved);
return {
current,
trends: this.metrics.slice(-100), // Last 100 data points
alerts: activeAlerts,
health: this.getHealthStatus(current)
};
}
/**
* Display performance dashboard in terminal
*/
async displayDashboard() {
const dashboard = await this.getDashboard();
const metrics = dashboard.current;
console.clear();
// Header
console.log(boxen(`${this.emojis.brain} ${this.colors.brain('BRAINY PERFORMANCE DASHBOARD')} ${this.emojis.atom}\n` +
`${this.colors.dim('Real-time Vector + Graph Database Performance')}\n` +
`${this.colors.accent('Uptime:')} ${this.colors.highlight(this.formatUptime(metrics.uptime))} | ` +
`${this.colors.accent('Health:')} ${this.getHealthIcon(metrics.health.overall)} ${this.colors.primary(metrics.health.overall + '/100')}`, { padding: 1, borderStyle: 'double', borderColor: '#E88B5A', width: 80 }));
// Query Performance Section
console.log('\n' + this.colors.brain(`${this.emojis.lightning} QUERY PERFORMANCE`));
console.log(boxen(`${this.colors.accent('Vector Queries:')} ${this.colors.primary(metrics.queryLatency.vector.avg.toFixed(1) + 'ms avg')} | ` +
`${this.colors.accent('P95:')} ${this.colors.highlight(metrics.queryLatency.vector.p95.toFixed(1) + 'ms')}\n` +
`${this.colors.accent('Graph Queries:')} ${this.colors.primary(metrics.queryLatency.graph.avg.toFixed(1) + 'ms avg')} | ` +
`${this.colors.accent('P95:')} ${this.colors.highlight(metrics.queryLatency.graph.p95.toFixed(1) + 'ms')}\n` +
`${this.colors.accent('Combined Ops:')} ${this.colors.success(metrics.throughput.totalOps.toFixed(0) + ' ops/sec')}`, { padding: 1, borderStyle: 'round', borderColor: '#3A5F4A' }));
// Storage & Memory Section
console.log('\n' + this.colors.brain(`${this.emojis.shield} STORAGE & MEMORY`));
console.log(boxen(`${this.colors.accent('Storage Size:')} ${this.colors.primary(this.formatBytes(metrics.storage.totalSize))} | ` +
`${this.colors.accent('Growth:')} ${this.colors.highlight(metrics.storage.growthRate.toFixed(1) + '/hr')}\n` +
`${this.colors.accent('Cache Hit Rate:')} ${this.colors.success((metrics.storage.cacheHitRate * 100).toFixed(1) + '%')} | ` +
`${this.colors.accent('Memory:')} ${this.colors.primary(metrics.memory.heapUsed.toFixed(0) + 'MB')}\n` +
`${this.colors.accent('Vector Cache:')} ${this.colors.info(metrics.memory.vectorCache.toFixed(1) + 'MB')} | ` +
`${this.colors.accent('Graph Cache:')} ${this.colors.info(metrics.memory.graphCache.toFixed(1) + 'MB')}`, { padding: 1, borderStyle: 'round', borderColor: '#4A6B5A' }));
// Health Scores Section
console.log('\n' + this.colors.brain(`${this.emojis.health} SYSTEM HEALTH`));
console.log(boxen(`${this.colors.accent('Vector Operations:')} ${this.getHealthBar(metrics.health.vector)} ${this.colors.primary(metrics.health.vector + '/100')}\n` +
`${this.colors.accent('Graph Operations:')} ${this.getHealthBar(metrics.health.graph)} ${this.colors.primary(metrics.health.graph + '/100')}\n` +
`${this.colors.accent('Storage System:')} ${this.getHealthBar(metrics.health.storage)} ${this.colors.primary(metrics.health.storage + '/100')}\n` +
`${this.colors.accent('Network/Connectivity:')} ${this.getHealthBar(metrics.health.network)} ${this.colors.primary(metrics.health.network + '/100')}`, { padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }));
// Active Alerts
if (dashboard.alerts.length > 0) {
console.log('\n' + this.colors.error(`${this.emojis.alert} ACTIVE ALERTS`));
dashboard.alerts.forEach(alert => {
const severityColor = alert.rule.severity === 'critical' ? this.colors.error :
alert.rule.severity === 'high' ? this.colors.warning :
this.colors.info;
console.log(severityColor(` ${this.getSeverityIcon(alert.rule.severity)} ${alert.message}`));
});
}
// Footer
console.log('\n' + this.colors.dim(`Last updated: ${new Date().toLocaleTimeString()} | Press Ctrl+C to exit`));
}
/**
* Collect current performance metrics
*/
async collectMetrics() {
const now = Date.now();
const uptime = process.uptime();
// Simulate metrics collection (in real implementation, this would query actual systems)
const metrics = {
queryLatency: {
vector: {
avg: Math.random() * 50 + 10,
p50: Math.random() * 40 + 8,
p95: Math.random() * 100 + 30,
p99: Math.random() * 200 + 50
},
graph: {
avg: Math.random() * 30 + 5,
p50: Math.random() * 25 + 4,
p95: Math.random() * 80 + 15,
p99: Math.random() * 150 + 25
},
combined: {
avg: Math.random() * 40 + 7,
p50: Math.random() * 35 + 6,
p95: Math.random() * 90 + 20,
p99: Math.random() * 180 + 40
}
},
throughput: {
vectorOps: Math.random() * 1000 + 500,
graphOps: Math.random() * 800 + 300,
totalOps: Math.random() * 1500 + 800
},
storage: {
readLatency: Math.random() * 20 + 2,
writeLatency: Math.random() * 30 + 5,
cacheHitRate: 0.85 + Math.random() * 0.1,
totalSize: 1024 * 1024 * 1024 * (10 + Math.random() * 50), // 10-60 GB
growthRate: Math.random() * 100 + 10
},
memory: {
heapUsed: process.memoryUsage().heapUsed / (1024 * 1024),
heapTotal: process.memoryUsage().heapTotal / (1024 * 1024),
vectorCache: Math.random() * 500 + 100,
graphCache: Math.random() * 300 + 50,
efficiency: 0.75 + Math.random() * 0.2
},
errors: {
total: Math.floor(Math.random() * 10),
rate: Math.random() * 2,
types: {
'timeout': Math.floor(Math.random() * 3),
'network': Math.floor(Math.random() * 2),
'storage': Math.floor(Math.random() * 2)
}
},
health: {
overall: Math.floor(85 + Math.random() * 15),
vector: Math.floor(80 + Math.random() * 20),
graph: Math.floor(85 + Math.random() * 15),
storage: Math.floor(90 + Math.random() * 10),
network: Math.floor(85 + Math.random() * 15)
},
timestamp: new Date().toISOString(),
uptime
};
return metrics;
}
/**
* Initialize default alert rules
*/
initializeDefaultAlerts() {
this.alertRules = [
{
id: 'vector-latency-high',
name: 'Vector Query Latency High',
condition: 'queryLatency.vector.p95 > 200',
threshold: 200,
severity: 'medium',
enabled: true
},
{
id: 'graph-latency-high',
name: 'Graph Query Latency High',
condition: 'queryLatency.graph.p95 > 150',
threshold: 150,
severity: 'medium',
enabled: true
},
{
id: 'memory-high',
name: 'Memory Usage High',
condition: 'memory.heapUsed > 1000',
threshold: 1000,
severity: 'high',
enabled: true
},
{
id: 'cache-hit-low',
name: 'Cache Hit Rate Low',
condition: 'storage.cacheHitRate < 0.7',
threshold: 0.7,
severity: 'medium',
enabled: true
},
{
id: 'error-rate-high',
name: 'Error Rate High',
condition: 'errors.rate > 5',
threshold: 5,
severity: 'high',
enabled: true
}
];
}
/**
* Check alerts against current metrics
*/
async checkAlerts(metrics) {
for (const rule of this.alertRules) {
if (!rule.enabled)
continue;
const value = this.evaluateCondition(rule.condition, metrics);
const isTriggered = value > rule.threshold;
const existingAlert = this.alerts.find(a => a.rule.id === rule.id && !a.resolved);
if (isTriggered && !existingAlert) {
// Trigger new alert
const alert = {
id: `${rule.id}-${Date.now()}`,
rule,
triggered: new Date().toISOString(),
value,
message: `${rule.name}: ${value.toFixed(2)} > ${rule.threshold}`
};
this.alerts.push(alert);
console.log(this.colors.warning(`${this.emojis.alert} ALERT: ${alert.message}`));
}
else if (!isTriggered && existingAlert) {
// Resolve existing alert
existingAlert.resolved = new Date().toISOString();
console.log(this.colors.success(`${this.emojis.health} RESOLVED: ${existingAlert.message}`));
}
}
}
/**
* Evaluate alert condition against metrics
*/
evaluateCondition(condition, metrics) {
// Simple condition evaluation (in real implementation, use a proper expression parser)
const parts = condition.split(' ');
if (parts.length !== 3)
return 0;
const path = parts[0];
const value = this.getMetricValue(path, metrics);
return typeof value === 'number' ? value : 0;
}
/**
* Get metric value by dot notation path
*/
getMetricValue(path, metrics) {
return path.split('.').reduce((obj, key) => obj?.[key], metrics);
}
/**
* Helper methods
*/
getHealthStatus(metrics) {
const score = metrics.health.overall;
if (score >= 90)
return 'excellent';
if (score >= 75)
return 'good';
if (score >= 60)
return 'fair';
return 'poor';
}
getHealthIcon(score) {
if (score >= 90)
return this.emojis.health;
if (score >= 75)
return '💛';
if (score >= 60)
return this.emojis.warning;
return this.emojis.critical;
}
getHealthBar(score) {
const filled = Math.floor(score / 10);
const empty = 10 - filled;
return this.colors.success('█'.repeat(filled)) + this.colors.dim('░'.repeat(empty));
}
getSeverityIcon(severity) {
switch (severity) {
case 'critical': return this.emojis.critical;
case 'high': return this.emojis.alert;
case 'medium': return this.emojis.warning;
default: return this.emojis.gear;
}
}
formatUptime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${hours}h ${minutes}m`;
}
formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
}
//# sourceMappingURL=performanceMonitor.js.map