# Define the IP addresses to monitor $addresses = @() $addressDefinitions = @( "1.1.1.1", "1.0.0.1", "8.8.8.8-9" # Using range notation for cleaner definition ) foreach ($addr in $addressDefinitions) { if ($addr -match "(\d+\.\d+\.\d+\.)(\d+)-(\d+)") { $prefix = $matches[1] $start = [int]$matches[2] $end = [int]$matches[3] for ($i = $start; $i -le $end; $i++) { $addresses += "$prefix$i" } } else { $addresses += $addr } } # Initialize hashtables to store statistics $stats = @{} foreach ($addr in $addresses) { $stats[$addr] = @{ MinTime = [int]::MaxValue MaxTime = 0 TotalTime = 0 SuccessCount = 0 FailCount = 0 Samples = [System.Collections.Queue]::new(60) # Fixed-size queue for better memory management LastStatus = $null StatusChanged = $false } } # Function to calculate mean function Get-Mean { param($Numbers) if ($Numbers.Count -eq 0) { return 0 } $array = [array]($Numbers) return ($array | Measure-Object -Average).Average } # Function to clear the console and position cursor function Reset-Display { Clear-Host $host.UI.RawUI.CursorPosition = @{X=0; Y=0} } # Function to format number with fixed width function Format-Number { param( [Parameter(Mandatory=$true)] [double]$Number, [int]$Width = 6, [int]$Decimals = 1 ) if ($Number -eq [int]::MaxValue) { return "".PadLeft($Width) } return $Number.ToString("F$Decimals").PadLeft($Width) } # Function to log status changes function Write-StatusLog { param( [string]$Address, [string]$OldStatus, [string]$NewStatus ) $logMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'): $Address status changed from $OldStatus to $NewStatus" Add-Content -Path "network_monitor.log" -Value $logMessage Write-Host "`n$logMessage" -ForegroundColor Yellow } # Main monitoring loop try { while ($true) { Reset-Display $currentTime = Get-Date -Format "HH:mm:ss" Write-Host "Network Monitor - Last Updated: $currentTime" -ForegroundColor Cyan Write-Host "Press Ctrl+C to exit`n" -ForegroundColor DarkGray # Header with fixed widths Write-Host "IP Address Status Min Max Mean Success% Fails Trend" -ForegroundColor Yellow Write-Host "--------------- -------- ----- ----- ----- -------- ------ -------" -ForegroundColor Yellow foreach ($addr in $addresses) { $ping = New-Object System.Net.NetworkInformation.Ping try { $result = $ping.Send($addr, 1000) # 1 second timeout $status = $result.Status -eq 'Success' } catch { $status = $false } if ($status) { $responseTime = $result.RoundtripTime $stats[$addr].TotalTime += $responseTime $stats[$addr].SuccessCount++ # Update rolling queue of samples - suppress output if ($stats[$addr].Samples.Count -eq 60) { [void]$stats[$addr].Samples.Dequeue() } [void]$stats[$addr].Samples.Enqueue($responseTime) # Update min/max $stats[$addr].MinTime = [Math]::Min($stats[$addr].MinTime, $responseTime) $stats[$addr].MaxTime = [Math]::Max($stats[$addr].MaxTime, $responseTime) $statusText = "UP" $color = "Green" } else { $stats[$addr].FailCount++ $statusText = "DOWN" $color = "Red" } # Check for status changes and log them if ($stats[$addr].LastStatus -ne $null -and $stats[$addr].LastStatus -ne $status) { Write-StatusLog -Address $addr -OldStatus $stats[$addr].LastStatus -NewStatus $status } $stats[$addr].LastStatus = $status # Calculate statistics $totalRequests = $stats[$addr].SuccessCount + $stats[$addr].FailCount $successRate = if ($totalRequests -gt 0) { [math]::Round(($stats[$addr].SuccessCount / $totalRequests) * 100, 1) } else { 0 } $meanTime = if ($stats[$addr].Samples.Count -gt 0) { [math]::Round((Get-Mean $stats[$addr].Samples), 1) } else { 0 } # Calculate trend based on last 5 samples - suppress output $trend = if ($stats[$addr].Samples.Count -ge 5) { $recent = @([array]($stats[$addr].Samples)) $lastFive = $recent[-[Math]::Min(5, $recent.Count)..-1] if ($lastFive.Count -ge 2) { $slope = ($lastFive[-1] - $lastFive[0]) / [Math]::Max(1, ($lastFive.Count - 1)) if ([Math]::Abs($slope) -lt 1) { "━" } elseif ($slope -lt 0) { "↓" } else { "↑" } } else { "━" } } else { "━" } # Format output fields $ipField = $addr.PadRight(15) $statusField = $statusText.PadRight(8) $minField = Format-Number -Number $stats[$addr].MinTime -Width 5 -Decimals 0 $maxField = Format-Number -Number $stats[$addr].MaxTime -Width 5 -Decimals 0 $meanField = Format-Number -Number $meanTime -Width 5 -Decimals 1 $successField = Format-Number -Number $successRate -Width 8 -Decimals 1 $failsField = $stats[$addr].FailCount.ToString().PadLeft(6) # Display the line Write-Host $ipField -NoNewline Write-Host $statusField -NoNewline -ForegroundColor $color Write-Host "$minField $maxField $meanField $successField $failsField $trend" } Start-Sleep -Seconds 1 } } finally { # Cleanup when script is interrupted Write-Host "`nMonitoring stopped at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Cyan }