package alerting import ( "fmt" "sync" "time" ) // AlertLevel represents alert severity type AlertLevel string const ( AlertWarning AlertLevel = "warning" AlertError AlertLevel = "error" AlertCritical AlertLevel = "critical" ) // Alert represents an alert notification type Alert struct { ID string Level AlertLevel Title string Message string Timestamp time.Time Resolved bool Source string } // AlertRule represents a rule that triggers alerts type AlertRule struct { ID string Name string Threshold float64 Metric string Level AlertLevel } // AlertManager manages alert rules and notifications type AlertManager struct { mu sync.RWMutex rules map[string]*AlertRule alerts map[string]*Alert history []*Alert } // NewAlertManager creates a new alert manager func NewAlertManager() *AlertManager { return &AlertManager{ rules: make(map[string]*AlertRule), alerts: make(map[string]*Alert), history: make([]*Alert, 0), } } // AddRule adds an alert rule func (am *AlertManager) AddRule(rule *AlertRule) error { if rule.ID == "" || rule.Name == "" { return fmt.Errorf("rule ID and name required") } am.mu.Lock() defer am.mu.Unlock() am.rules[rule.ID] = rule return nil } // RemoveRule removes an alert rule func (am *AlertManager) RemoveRule(ruleID string) error { am.mu.Lock() defer am.mu.Unlock() if _, exists := am.rules[ruleID]; !exists { return fmt.Errorf("rule not found: %s", ruleID) } delete(am.rules, ruleID) return nil } // TriggerAlert triggers a new alert func (am *AlertManager) TriggerAlert(title, message string, level AlertLevel) (*Alert, error) { if title == "" { return nil, fmt.Errorf("alert title required") } am.mu.Lock() defer am.mu.Unlock() alert := &Alert{ ID: fmt.Sprintf("alert-%d", len(am.alerts)), Level: level, Title: title, Message: message, Timestamp: time.Now(), Resolved: false, } am.alerts[alert.ID] = alert am.history = append(am.history, alert) return alert, nil } // ResolveAlert marks an alert as resolved func (am *AlertManager) ResolveAlert(alertID string) error { am.mu.Lock() defer am.mu.Unlock() alert, exists := am.alerts[alertID] if !exists { return fmt.Errorf("alert not found: %s", alertID) } alert.Resolved = true return nil } // GetActiveAlerts returns all unresolved alerts func (am *AlertManager) GetActiveAlerts() []*Alert { am.mu.RLock() defer am.mu.RUnlock() result := make([]*Alert, 0) for _, alert := range am.alerts { if !alert.Resolved { result = append(result, alert) } } return result } // GetAlertsByLevel returns alerts by severity level func (am *AlertManager) GetAlertsByLevel(level AlertLevel) []*Alert { am.mu.RLock() defer am.mu.RUnlock() result := make([]*Alert, 0) for _, alert := range am.alerts { if alert.Level == level { result = append(result, alert) } } return result } // GetHistory returns alert history func (am *AlertManager) GetHistory() []*Alert { am.mu.RLock() defer am.mu.RUnlock() result := make([]*Alert, len(am.history)) copy(result, am.history) return result } // GetRules returns all alert rules func (am *AlertManager) GetRules() map[string]*AlertRule { am.mu.RLock() defer am.mu.RUnlock() result := make(map[string]*AlertRule) for id, rule := range am.rules { result[id] = rule } return result } // GetAlertCount returns total active alert count func (am *AlertManager) GetAlertCount() int { am.mu.RLock() defer am.mu.RUnlock() return len(am.alerts) } // Clear clears all alerts func (am *AlertManager) Clear() { am.mu.Lock() defer am.mu.Unlock() am.alerts = make(map[string]*Alert) } // EvaluateRule checks if a metric triggers an alert rule func (am *AlertManager) EvaluateRule(ruleID string, metricValue float64) (*Alert, error) { am.mu.Lock() defer am.mu.Unlock() rule, exists := am.rules[ruleID] if !exists { return nil, fmt.Errorf("rule not found: %s", ruleID) } if metricValue >= rule.Threshold { alert := &Alert{ ID: fmt.Sprintf("alert-%d", len(am.alerts)), Level: rule.Level, Title: rule.Name, Message: fmt.Sprintf("Threshold %.2f exceeded: %.2f", rule.Threshold, metricValue), Timestamp: time.Now(), Resolved: false, Source: ruleID, } am.alerts[alert.ID] = alert am.history = append(am.history, alert) return alert, nil } return nil, nil }