polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
348 lines • 12.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlertManager = void 0;
const events_1 = require("events");
const alert_history_manager_1 = require("./alert-history-manager");
const alert_rule_manager_1 = require("./alert-rule-manager");
class AlertManager extends events_1.EventEmitter {
constructor(config) {
super();
this.alerts = new Map();
this.isRunning = false;
this.config = {
maxAlertsInMemory: 1000,
maxHistoryEntries: 10000,
autoAckTimeout: 24 * 60 * 60 * 1000,
autoResolveTimeout: 7 * 24 * 60 * 60 * 1000,
persistenceEnabled: true,
persistenceFile: '.polyv-alerts/alerts.json',
notifications: {
soundEnabled: true,
visualEnabled: true,
desktopEnabled: false,
emailEnabled: false,
volume: 0.7,
minLevel: 'warning'
},
defaultCooldown: 5 * 60 * 1000,
performance: {
maxProcessingRate: 100,
batchSize: 10,
processingInterval: 1000
},
...config
};
this.historyManager = new alert_history_manager_1.AlertHistoryManager(this.config);
this.ruleManager = new alert_rule_manager_1.AlertRuleManager();
this.setupEventHandlers();
this.setupCleanupInterval();
}
setupEventHandlers() {
this.ruleManager.on('rule:triggered', (data) => {
if (data.result.alert) {
this.createAlert(data.result.alert);
}
this.emit('rule:triggered', data);
});
this.historyManager.on('entry:added', (data) => {
this.emit('alert:history-updated', data);
});
this.historyManager.on('action:recorded', (data) => {
this.emit('alert:action-recorded', data);
});
}
setupCleanupInterval() {
this.cleanupInterval = setInterval(() => {
this.performAutomaticCleanup();
}, 60 * 60 * 1000);
}
start() {
if (this.isRunning)
return;
this.isRunning = true;
this.ruleManager.start();
this.evaluationInterval = setInterval(() => {
this.evaluateAlerts();
}, this.config.performance.processingInterval);
this.emit('manager:started');
}
stop() {
if (!this.isRunning)
return;
this.isRunning = false;
this.ruleManager.stop();
if (this.evaluationInterval) {
clearInterval(this.evaluationInterval);
this.evaluationInterval = undefined;
}
this.emit('manager:stopped');
}
createAlert(alertData) {
const alert = {
id: this.generateAlertId(),
timestamp: Date.now(),
acknowledged: false,
status: 'active',
...alertData
};
this.alerts.set(alert.id, alert);
this.historyManager.addAlert(alert, 'created');
this.enforceMemoryLimits();
this.emit('alert:created', { alert });
this.emit('alert:new', { alert });
return alert;
}
acknowledgeAlert(alertId, user) {
const alert = this.alerts.get(alertId);
if (!alert || alert.acknowledged)
return false;
alert.acknowledged = true;
alert.acknowledgedAt = Date.now();
if (user) {
alert.acknowledgedBy = user;
}
if (alert.status === 'active') {
alert.status = 'acknowledged';
}
this.historyManager.recordAction(alertId, 'acknowledged', user);
this.emit('alert:acknowledged', { alertId, alert, user });
return true;
}
resolveAlert(alertId, user) {
const alert = this.alerts.get(alertId);
if (!alert || alert.status === 'resolved')
return false;
alert.status = 'resolved';
alert.resolvedAt = Date.now();
if (!alert.acknowledged) {
alert.acknowledged = true;
alert.acknowledgedAt = Date.now();
if (user) {
alert.acknowledgedBy = user;
}
}
this.historyManager.recordAction(alertId, 'resolved', user);
this.emit('alert:resolved', { alertId, alert, user });
return true;
}
ignoreAlert(alertId, user) {
const alert = this.alerts.get(alertId);
if (!alert)
return false;
alert.status = 'ignored';
alert.acknowledgedAt = Date.now();
if (user) {
alert.acknowledgedBy = user;
}
this.historyManager.recordAction(alertId, 'ignored', user);
this.emit('alert:ignored', { alertId, alert, user });
return true;
}
deleteAlert(alertId) {
const alert = this.alerts.get(alertId);
if (!alert)
return false;
this.alerts.delete(alertId);
this.historyManager.recordAction(alertId, 'deleted');
this.emit('alert:deleted', { alertId, alert });
return true;
}
addAlertNotes(alertId, notes, user) {
const alert = this.alerts.get(alertId);
if (!alert)
return false;
const timestamp = new Date().toISOString();
const noteEntry = user ? `[${timestamp}] ${user}: ${notes}` : `[${timestamp}] ${notes}`;
if (alert.notes) {
alert.notes += '\n' + noteEntry;
}
else {
alert.notes = noteEntry;
}
this.historyManager.recordAction(alertId, 'notes-added', user, { notes });
this.emit('alert:notes-added', { alertId, alert, notes, user });
return true;
}
getAlerts() {
return Array.from(this.alerts.values());
}
getAlert(alertId) {
return this.alerts.get(alertId);
}
getFilteredAlerts(filter) {
const alerts = this.getAlerts();
if (!filter)
return alerts;
return alerts.filter(alert => {
if (filter.levels?.length && !filter.levels.includes(alert.level)) {
return false;
}
if (filter.types?.length && !filter.types.includes(alert.type)) {
return false;
}
if (filter.statuses?.length && !filter.statuses.includes(alert.status)) {
return false;
}
if (filter.sources?.length && !filter.sources.includes(alert.source)) {
return false;
}
if (filter.channelIds?.length && !filter.channelIds.includes(alert.channelId || '')) {
return false;
}
if (filter.timeRange) {
if (alert.timestamp < filter.timeRange.start ||
alert.timestamp > filter.timeRange.end) {
return false;
}
}
if (filter.searchText) {
const searchText = filter.searchText.toLowerCase();
return alert.title.toLowerCase().includes(searchText) ||
alert.message.toLowerCase().includes(searchText) ||
alert.source.toLowerCase().includes(searchText);
}
if (filter.acknowledgedOnly && !alert.acknowledged) {
return false;
}
if (filter.unacknowledgedOnly && alert.acknowledged) {
return false;
}
return true;
});
}
acknowledgeBatch(alertIds, user) {
const result = { success: [], failed: [] };
alertIds.forEach(alertId => {
if (this.acknowledgeAlert(alertId, user)) {
result.success.push(alertId);
}
else {
result.failed.push(alertId);
}
});
this.emit('alert:batch-acknowledged', { success: result.success, failed: result.failed, user });
return result;
}
resolveBatch(alertIds, user) {
const result = { success: [], failed: [] };
alertIds.forEach(alertId => {
if (this.resolveAlert(alertId, user)) {
result.success.push(alertId);
}
else {
result.failed.push(alertId);
}
});
this.emit('alert:batch-resolved', { success: result.success, failed: result.failed, user });
return result;
}
clearAllAlerts() {
const count = this.alerts.size;
this.alerts.clear();
this.historyManager.recordAction('all', 'cleared');
this.emit('alert:all-cleared', { count });
return count;
}
evaluateAlerts(context) {
if (!context) {
context = {
timestamp: Date.now(),
alertHistory: this.getAlerts()
};
}
const results = this.ruleManager.evaluateRules(context);
results.forEach(result => {
if (result.triggered && result.alert) {
this.createAlert(result.alert);
}
});
}
getStatistics() {
return this.historyManager.getStatistics();
}
getRecentActivity(hours = 24) {
return this.historyManager.getRecentActivity(hours);
}
exportAlerts(format = 'json') {
return this.historyManager.exportHistory(format);
}
importAlerts(data, format = 'json', merge = true) {
return this.historyManager.importHistory(data, format, merge);
}
getAlertHistory(filter, limit, offset = 0) {
return this.historyManager.getHistory(filter, limit, offset);
}
searchAlertHistory(searchText, searchFields = ['title', 'message'], limit = 100) {
return this.historyManager.searchHistory(searchText, searchFields, limit);
}
getRuleManager() {
return this.ruleManager;
}
getHistoryManager() {
return this.historyManager;
}
performAutomaticCleanup() {
const now = Date.now();
if (this.config.autoAckTimeout) {
const autoAckCutoff = now - this.config.autoAckTimeout;
this.alerts.forEach(alert => {
if (!alert.acknowledged && alert.timestamp < autoAckCutoff) {
this.acknowledgeAlert(alert.id, 'system');
}
});
}
if (this.config.autoResolveTimeout) {
const autoResolveCutoff = now - this.config.autoResolveTimeout;
this.alerts.forEach(alert => {
if (alert.status !== 'resolved' && alert.timestamp < autoResolveCutoff) {
this.resolveAlert(alert.id, 'system');
}
});
}
const resolvedCutoff = now - (24 * 60 * 60 * 1000);
const alertsToRemove = [];
this.alerts.forEach((alert, id) => {
if (alert.status === 'resolved' && alert.resolvedAt && alert.resolvedAt < resolvedCutoff) {
alertsToRemove.push(id);
}
});
alertsToRemove.forEach(id => this.alerts.delete(id));
if (alertsToRemove.length > 0) {
this.emit('alert:cleanup', { removedCount: alertsToRemove.length });
}
}
enforceMemoryLimits() {
if (this.alerts.size <= this.config.maxAlertsInMemory)
return;
const sortedAlerts = Array.from(this.alerts.entries())
.sort((a, b) => {
if (a[1].status === 'resolved' && b[1].status !== 'resolved')
return -1;
if (a[1].status !== 'resolved' && b[1].status === 'resolved')
return 1;
return a[1].timestamp - b[1].timestamp;
});
const toRemove = sortedAlerts.slice(0, this.alerts.size - this.config.maxAlertsInMemory);
toRemove.forEach(([id]) => this.alerts.delete(id));
if (toRemove.length > 0) {
this.emit('alert:memory-cleanup', { removedCount: toRemove.length });
}
}
generateAlertId() {
return `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
async destroy() {
this.stop();
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = undefined;
}
await this.historyManager.destroy();
await this.ruleManager.destroy();
this.alerts.clear();
this.removeAllListeners();
this.emit('manager:destroyed');
}
}
exports.AlertManager = AlertManager;
//# sourceMappingURL=alert-manager.js.map