Situatie
Verificarea zilnică a Event Viewer pe mai multe servere este consumatoare de timp, iar codurile de eroare Windows sunt greu de interpretat rapid. Multe probleme sunt observate abia după ce devin incidente.
Această soluție colectează evenimentele critice și de eroare din ultimele 24 de ore de pe mai multe servere, le trimite unui model AI local care le explică în limbaj uman (ce înseamnă eroarea, ce ar trebui verificat, cât de urgentă e), grupează problemele similare și trimite un raport HTML pe email — automat, în fiecare dimineață.
Backup
Soluția este read-only asupra Event Log-urilor. Necesită doar drepturi de citire remote. Nu modifică nicio configurație de server.
Solutie
Pasi de urmat
Pasul 1 — Pregătire și verificare acces remote la Event Log
# Lista serverelor de monitorizat
$Servers = @("SRV-DC01", "SRV-FILE01", "SRV-SQL01", "SRV-APP01")
# Verifica accesul la Event Log pe fiecare server
foreach ($Server in $Servers) {
try {
Get-WinEvent -ComputerName $Server -LogName System -MaxEvents 1 -ErrorAction Stop | Out-Null
Write-Host "[OK] $Server - acces confirmat" -ForegroundColor Green
}
catch {
Write-Host "[EROARE] $Server - $_" -ForegroundColor Red
}
}
Pasul 2 — Funcție de colectare evenimente critice
function Get-CriticalEvents {
param(
[string]$ComputerName,
[int]$Hours = 24
)
$StartTime = (Get-Date).AddHours(-$Hours)
try {
$Events = Get-WinEvent -ComputerName $ComputerName -FilterHashtable @{
LogName = 'System', 'Application'
Level = 1, 2 # 1 = Critical, 2 = Error
StartTime = $StartTime
} -ErrorAction Stop -MaxEvents 100
return $Events | Select-Object `
@{N='Server'; E={$ComputerName}},
@{N='Time'; E={$_.TimeCreated}},
@{N='Level'; E={$_.LevelDisplayName}},
@{N='EventID'; E={$_.Id}},
@{N='Source'; E={$_.ProviderName}},
@{N='Message'; E={($_.Message -split "`n")[0]}}
}
catch {
Write-Warning "Nu s-au putut extrage evenimente de pe $ComputerName : $_"
return @()
}
}
Pasul 3 — Funcție de interpretare AI
function Get-AIHealthAnalysis {
param(
[array]$Events,
[string]$Model = "llama3"
)
# Grupeaza evenimentele pentru a reduce volumul trimis
$Summary = $Events | Group-Object Server, EventID, Source |
ForEach-Object {
$first = $_.Group[0]
"[$($first.Server)] EventID $($first.EventID) | $($first.Source) | " +
"apariti: $($_.Count) | $($first.Message)"
}
$EventsText = $Summary -join "`n"
$Prompt = @"
Esti un administrator de sistem Windows Server senior.
Analizeaza evenimentele critice si de eroare de mai jos, colectate din ultimele 24 ore.
Pentru fiecare problema semnificativa, raspunde in formatul:
PROBLEMA: <descriere in limbaj uman, ce inseamna eroarea>
SERVER: <serverul/serverele afectate>
URGENTA: <Critica/Ridicata/Medie/Informativa>
CAUZA_PROBABILA: <cea mai probabila cauza>
VERIFICARI: <ce ar trebui verificat concret>
Grupeaza erorile similare. Prioritizeaza in raspuns problemele urgente.
Ignora zgomotul de rutina (ex. erori tranzitorii de retea izolate).
Raspunde DOAR in limba romana, concis si tehnic.
EVENIMENTE:
$EventsText
"@
$Body = @{
model = $Model
prompt = $Prompt
stream = $false
} | ConvertTo-Json -Depth 3
try {
$Response = Invoke-RestMethod `
-Uri "http://localhost:11434/api/generate" `
-Method POST -ContentType "application/json" `
-Body $Body -TimeoutSec 180
return $Response.response
}
catch {
return "EROARE la analiza AI: $_"
}
}
Pasul 4 — Generare raport HTML
function New-HealthReportHTML {
param(
[string]$Analysis,
[array]$Events,
[array]$Servers
)
$Date = Get-Date -Format "dd.MM.yyyy HH:mm"
$AnalysisHTML = $Analysis -replace "`n", "<br/>"
$EventCount = $Events.Count
$ServerStats = $Events | Group-Object Server |
ForEach-Object { "<li><b>$($_.Name)</b>: $($_.Count) evenimente</li>" }
return @"
<html>
<head><meta charset="UTF-8"><style>
body { font-family: Segoe UI, Arial, sans-serif; font-size: 14px; color: #333; }
h2 { color: #1a5490; border-bottom: 2px solid #1a5490; padding-bottom: 5px; }
.summary { background: #f4f6f8; padding: 12px; border-left: 4px solid #1a5490; }
.analysis { background: #fff; padding: 12px; border: 1px solid #ddd; margin-top: 15px; }
</style></head>
<body>
<h2>Raport zilnic sanatate servere - $Date</h2>
<div class="summary">
<b>Servere monitorizate:</b> $($Servers -join ", ")<br/>
<b>Total evenimente critice/eroare (24h):</b> $EventCount
<ul>$($ServerStats -join "")</ul>
</div>
<div class="analysis">
<h3>Analiza AI</h3>
$AnalysisHTML
</div>
<p style="color:#888;font-size:12px;margin-top:20px;">
Raport generat automat cu model AI local. Verdictele sunt orientative
si necesita confirmare de catre administrator.
</p>
</body></html>
"@
}
Pasul 5 — Script principal
# ============================================================
# AI Server Health Report
# Autor: Claudiu Ceausescu
# ============================================================
$Servers = @("SRV-DC01", "SRV-FILE01", "SRV-SQL01", "SRV-APP01")
$ReportPath = "C:\HealthReports"
$Model = "llama3"
# Setari email
$SmtpServer = "smtp.companie.local"
$MailFrom = "monitorizare@companie.ro"
$MailTo = "it-team@companie.ro"
New-Item -ItemType Directory -Force -Path $ReportPath | Out-Null
# Verifica Ollama
try {
Invoke-RestMethod -Uri "http://localhost:11434/api/tags" -TimeoutSec 5 | Out-Null
Write-Host "[OK] Ollama activ." -ForegroundColor Green
}
catch {
Write-Host "[EROARE] Ollama nu raspunde." -ForegroundColor Red
exit 1
}
# Colectare evenimente de pe toate serverele
$AllEvents = @()
foreach ($Server in $Servers) {
Write-Host "Colectez evenimente de pe $Server..." -ForegroundColor Cyan
$AllEvents += Get-CriticalEvents -ComputerName $Server -Hours 24
}
if ($AllEvents.Count -eq 0) {
Write-Host "Nu exista evenimente critice in ultimele 24 ore." -ForegroundColor Green
$Analysis = "Nu s-au inregistrat evenimente critice sau de eroare in ultimele 24 de ore pe serverele monitorizate."
}
else {
Write-Host "Gasit $($AllEvents.Count) evenimente. Trimit spre analiza AI..." -ForegroundColor Cyan
$Analysis = Get-AIHealthAnalysis -Events $AllEvents -Model $Model
}
# Generare si salvare raport
$HTML = New-HealthReportHTML -Analysis $Analysis -Events $AllEvents -Servers $Servers
$ReportFile = Join-Path $ReportPath "Health_$(Get-Date -Format 'yyyy-MM-dd').html"
$HTML | Out-File -FilePath $ReportFile -Encoding UTF8
Write-Host "[OK] Raport salvat: $ReportFile" -ForegroundColor Green
# Trimitere pe email
try {
Send-MailMessage -SmtpServer $SmtpServer -From $MailFrom -To $MailTo `
-Subject "Raport sanatate servere - $(Get-Date -Format 'dd.MM.yyyy')" `
-Body $HTML -BodyAsHtml -Encoding UTF8
Write-Host "[OK] Raport trimis pe email." -ForegroundColor Green
}
catch {
Write-Host "[EROARE] Trimitere email eșuata: $_" -ForegroundColor Red
}
Pasul 6 — Programare rulare zilnică
$Action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-ExecutionPolicy Bypass -File C:\Scripts\AI_Health_Report.ps1"
$Trigger = New-ScheduledTaskTrigger -Daily -At "07:00"
Register-ScheduledTask -TaskName "AI_ServerHealthReport" `
-Action $Action -Trigger $Trigger -RunLevel Highest `
-Description "Raport zilnic de sanatate servere generat cu AI local"
# Testeaza task-ul imediat
Start-ScheduledTask -TaskName "AI_ServerHealthReport"
Exemplu secțiune din raport:
PROBLEMA: Serviciul de replicare Active Directory nu a reusit sa
sincronizeze cu un partener de replicare
SERVER: SRV-DC01
URGENTA: Ridicata
CAUZA_PROBABILA: Probleme de conectivitate de retea sau DNS catre
controllerul partener
VERIFICARI: Ruleaza repadmin /showrepl, verifica rezolvarea DNS a
numelui partenerului, testeaza porturile RPC (135, 49152-65535)
Leave A Comment?