package ai import ( "context" "encoding/json" "fmt" "log" "time" ) // AutoHealer sistema de auto-correção inteligente type AutoHealer struct { engine *AIEngine enabled bool dryRun bool maxActions int cooldown time.Duration lastActions map[string]time.Time } // HealingAction ação de correção type HealingAction struct { ID string `json:"id"` Type string `json:"type"` Target string `json:"target"` Command string `json:"command"` Description string `json:"description"` Risk string `json:"risk"` Executed bool `json:"executed"` ExecutedAt time.Time `json:"executed_at,omitempty"` Result string `json:"result,omitempty"` Error string `json:"error,omitempty"` } // HealingPlan plano de correção gerado pela IA type HealingPlan struct { Issue string `json:"issue"` Severity string `json:"severity"` Analysis string `json:"analysis"` Actions []HealingAction `json:"actions"` Confidence float64 `json:"confidence"` RequiresApproval bool `json:"requires_approval"` } // AutoHealConfig configuração do auto-healer type AutoHealConfig struct { Enabled bool DryRun bool // Se true, não executa, só sugere MaxActionsPerHour int Cooldown time.Duration // Tempo mínimo entre ações no mesmo recurso AllowedActions []string // Tipos de ações permitidas ApprovalRequired []string // Ações que precisam de aprovação humana } // NewAutoHealer cria novo auto-healer func NewAutoHealer(engine *AIEngine, config AutoHealConfig) *AutoHealer { return &AutoHealer{ engine: engine, enabled: config.Enabled, dryRun: config.DryRun, maxActions: config.MaxActionsPerHour, cooldown: config.Cooldown, lastActions: make(map[string]time.Time), } } // Analyze analisa um problema e gera plano de correção func (h *AutoHealer) Analyze(ctx context.Context, incident Incident) (*HealingPlan, error) { if !h.enabled { return nil, fmt.Errorf("auto-healer is disabled") } prompt := fmt.Sprintf(`Analise o seguinte incidente e gere um plano de correção automática: INCIDENTE: - Tipo: %s - Severidade: %s - Host: %s - Descrição: %s - Início: %s - Duração: %s MÉTRICAS DO HOST: %s LOGS RECENTES: %s AÇÕES ANTERIORES (últimas 24h): %s REGRAS: 1. Priorize ações de baixo risco 2. Reinício de serviço só como último recurso 3. Escalonamento horizontal antes de vertical 4. Sempre tenha rollback em mente Responda em JSON: { "issue": "descrição concisa do problema", "severity": "low|medium|high|critical", "analysis": "análise detalhada da causa raiz", "actions": [ { "id": "action_1", "type": "restart_service|scale_up|clear_cache|rotate_logs|kill_process|run_script|config_change", "target": "nome do serviço ou recurso", "command": "comando a executar", "description": "o que essa ação faz", "risk": "low|medium|high" } ], "confidence": 0.0-1.0, "requires_approval": boolean }`, incident.Type, incident.Severity, incident.Host, incident.Description, incident.StartTime.Format(time.RFC3339), time.Since(incident.StartTime).String(), incident.Metrics, incident.RecentLogs, h.getRecentActionsForHost(incident.Host), ) response, err := h.engine.chat(ctx, prompt) if err != nil { return nil, err } var plan HealingPlan if err := json.Unmarshal([]byte(response), &plan); err != nil { return nil, fmt.Errorf("failed to parse healing plan: %w", err) } return &plan, nil } // Execute executa um plano de correção func (h *AutoHealer) Execute(ctx context.Context, plan *HealingPlan) (*HealingResult, error) { if h.dryRun { return &HealingResult{ Plan: plan, DryRun: true, Message: "Dry run - ações não executadas", }, nil } result := &HealingResult{ Plan: plan, StartedAt: time.Now(), Actions: make([]ActionResult, 0), } for _, action := range plan.Actions { // Verificar cooldown if !h.canExecute(action.Target) { result.Actions = append(result.Actions, ActionResult{ ActionID: action.ID, Skipped: true, Reason: "Cooldown period active", }) continue } // Executar ação actionResult := h.executeAction(ctx, action) result.Actions = append(result.Actions, actionResult) // Registrar execução h.lastActions[action.Target] = time.Now() // Se falhou, parar if !actionResult.Success { result.Success = false result.Error = actionResult.Error break } } result.CompletedAt = time.Now() result.Success = result.Error == "" return result, nil } // executeAction executa uma ação individual func (h *AutoHealer) executeAction(ctx context.Context, action HealingAction) ActionResult { result := ActionResult{ ActionID: action.ID, StartedAt: time.Now(), } log.Printf("[AutoHealer] Executing action: %s on %s", action.Type, action.Target) // Aqui seria a execução real via SSH, API, etc. // Por segurança, implementar com cuidado switch action.Type { case "restart_service": // Exemplo: systemctl restart result.Command = action.Command // result = executeSSHCommand(action.Target, action.Command) case "scale_up": // Exemplo: kubectl scale deployment... result.Command = action.Command case "clear_cache": // Exemplo: redis-cli flushdb result.Command = action.Command case "rotate_logs": // Exemplo: logrotate -f result.Command = action.Command default: result.Error = fmt.Sprintf("Unknown action type: %s", action.Type) return result } // Simular execução bem-sucedida (implementar execução real) result.Success = true result.CompletedAt = time.Now() result.Output = "Action executed successfully (simulated)" return result } func (h *AutoHealer) canExecute(target string) bool { lastAction, exists := h.lastActions[target] if !exists { return true } return time.Since(lastAction) > h.cooldown } func (h *AutoHealer) getRecentActionsForHost(host string) string { // Buscar histórico de ações recentes return "Nenhuma ação recente" } // Incident representa um incidente type Incident struct { ID string Type string Severity string Host string Description string StartTime time.Time Metrics string RecentLogs string } // HealingResult resultado da execução do plano type HealingResult struct { Plan *HealingPlan Success bool DryRun bool Message string Error string StartedAt time.Time CompletedAt time.Time Actions []ActionResult } // ActionResult resultado de uma ação type ActionResult struct { ActionID string Success bool Skipped bool Reason string Command string Output string Error string StartedAt time.Time CompletedAt time.Time }