From 1736a32044d9060fc59aa3f7a2a495acf8424060 Mon Sep 17 00:00:00 2001 From: JBg Date: Wed, 12 Feb 2025 08:19:27 +0100 Subject: [PATCH] Add Ping_Monitor.ps1 --- Ping_Monitor.ps1 | 161 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Ping_Monitor.ps1 diff --git a/Ping_Monitor.ps1 b/Ping_Monitor.ps1 new file mode 100644 index 0000000..337346e --- /dev/null +++ b/Ping_Monitor.ps1 @@ -0,0 +1,161 @@ +# Define the IP addresses to monitor +$addresses = @( + "1.1.1.1", + "1.0.0.1", + "8.8.8.8-9" # Using range notation for cleaner definition +) | ForEach-Object { + if ($_ -match "(\d+\.\d+\.\d+\.)(\d+)-(\d+)") { + $prefix = $matches[1] + $start = [int]$matches[2] + $end = [int]$matches[3] + $start..$end | ForEach-Object { "$prefix$_" } + } else { + $_ + } +} + +# 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 + if ($stats[$addr].Samples.Count -eq 60) { + $stats[$addr].Samples.Dequeue() + } + $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 + $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 +} \ No newline at end of file