$LogDir = "C:\RedLogs" $IntervaloSeg = 1 $TimeoutMs = 1000 $UmbralLatencia = 100 $MaxIntentos = 3 $ResumenCadaSeg = 60 $AlertaActiva = $true $AlertaCooldownSeg = 60 $AlertaSoloCaidas = $false $Targets = @( [PSCustomObject]@{ Nombre = "Gateway"; IP = "192.168.1.1" }, [PSCustomObject]@{ Nombre = "TotalPlay"; IP = "1.1.1.1" }, [PSCustomObject]@{ Nombre = "Infinitum"; IP = "8.8.8.8" }, [PSCustomObject]@{ Nombre = "CastrMX"; IP = "121.127.43.49" }, [PSCustomObject]@{ Nombre = "CastrDallas"; IP = "37.19.200.193" } ) if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir -Force | Out-Null } function Get-LogPath { Join-Path $LogDir ("monitor_red_{0}.log" -f (Get-Date -Format "yyyy-MM-dd")) } function Write-Log { param([string]$Linea) try { Add-Content -Path (Get-LogPath) -Value $Linea -Encoding UTF8 -ErrorAction Stop } catch { Start-Sleep -Milliseconds 200; try { Add-Content -Path (Get-LogPath) -Value $Linea -Encoding UTF8 } catch { } } } $AlertaScript = Join-Path $LogDir "alerta_red.ps1" $script:UltimaAlerta = @{} if ($AlertaActiva -and -not (Test-Path $AlertaScript)) { $AlertaActiva = $false } function Show-Alerta { param([string]$Destino, [string]$Titulo, [string]$Mensaje, [string]$Color = "Red") if (-not $AlertaActiva) { return } $ahora = Get-Date if ($script:UltimaAlerta.ContainsKey($Destino)) { if (($ahora - $script:UltimaAlerta[$Destino]).TotalSeconds -lt $AlertaCooldownSeg) { return } } $script:UltimaAlerta[$Destino] = $ahora try { $lista = @("-NoProfile","-ExecutionPolicy","Bypass","-File","`"$AlertaScript`"","-Titulo","`"$Titulo`"","-Mensaje","`"$Mensaje`"","-Color",$Color) Start-Process -FilePath "powershell.exe" -ArgumentList $lista -WindowStyle Hidden | Out-Null } catch { } } $ping = New-Object System.Net.NetworkInformation.Ping $stats = @{} foreach ($t in $Targets) { $stats[$t.Nombre] = [PSCustomObject]@{ Envios=0; Perdidos=0; SumaLat=0; ConLat=0; MaxLat=0 } } $destinos = ($Targets | ForEach-Object { "$($_.Nombre)=$($_.IP)" }) -join ", " Write-Log ("{0} | INICIO | monitor_red v2 | {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $destinos) Write-Host "Monitor de red v2 corriendo. Ctrl+C para detener." -ForegroundColor Cyan $ultimoResumen = Get-Date while ($true) { foreach ($t in $Targets) { $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $ok = $false; $lat = -1; $intentosUsados = 0 for ($intento = 1; $intento -le $MaxIntentos; $intento++) { $intentosUsados = $intento $exito = $false try { $r = $ping.Send($t.IP, $TimeoutMs) if ($r.Status -eq "Success") { $exito = $true; $lat = [int]$r.RoundtripTime } } catch { } if ($exito) { $ok = $true; break } Write-Log ("{0} | {1} | {2} | FAIL | intento={3}" -f $ts, $t.Nombre, $t.IP, $intento) } $s = $stats[$t.Nombre] $s.Envios += $intentosUsados if ($ok) { $s.Perdidos += ($intentosUsados - 1) $s.SumaLat += $lat; $s.ConLat++ if ($lat -gt $s.MaxLat) { $s.MaxLat = $lat } if ($lat -ge $UmbralLatencia) { Write-Log ("{0} | {1} | {2} | ALTA_LATENCIA | {3}ms" -f $ts, $t.Nombre, $t.IP, $lat) } else { Write-Log ("{0} | {1} | {2} | OK | {3}ms" -f $ts, $t.Nombre, $t.IP, $lat) } } else { $s.Perdidos += $intentosUsados Write-Log ("{0} | {1} | {2} | CAIDO | sin respuesta tras {3} intentos" -f $ts, $t.Nombre, $t.IP, $MaxIntentos) if ($t.Nombre -eq "Gateway") { Show-Alerta -Destino $t.Nombre -Color "Red" -Titulo "ALERTA DE RED LOCAL" -Mensaje "Fallo el gateway 192.168.1.1 - El router no responde. Revisar Client List." } else { Show-Alerta -Destino $t.Nombre -Color "Red" -Titulo ("ALERTA - " + $t.Nombre.ToUpper()) -Mensaje ("Sin respuesta por {0}. Hora: {1}. Anotar y avisar." -f $t.Nombre, $ts) } } } if (((Get-Date) - $ultimoResumen).TotalSeconds -ge $ResumenCadaSeg) { $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" foreach ($t in $Targets) { $s = $stats[$t.Nombre] if ($s.Envios -gt 0) { $pct = [math]::Round(($s.Perdidos / $s.Envios) * 100, 1) $prom = if ($s.ConLat -gt 0) { [math]::Round($s.SumaLat / $s.ConLat, 0) } else { 0 } Write-Log ("{0} | RESUMEN | {1} | pings={2} | perdidos={3} | perdida={4}% | lat_prom={5}ms | lat_max={6}ms" -f $ts, $t.Nombre, $s.Envios, $s.Perdidos, $pct, $prom, $s.MaxLat) if ((-not $AlertaSoloCaidas) -and ($pct -ge 5)) { Show-Alerta -Destino $t.Nombre -Color "DarkOrange" -Titulo ("PERDIDA DE PAQUETES - " + $t.Nombre.ToUpper()) -Mensaje ("{0}: {1}% de perdida en el ultimo minuto. Lat max {2}ms. Hora: {3}" -f $t.Nombre, $pct, $s.MaxLat, $ts) } } $s.Envios=0; $s.Perdidos=0; $s.SumaLat=0; $s.ConLat=0; $s.MaxLat=0 } $ultimoResumen = Get-Date } Start-Sleep -Seconds $IntervaloSeg }