Add Ping_Monitor.ps1
This commit is contained in:
161
Ping_Monitor.ps1
Normal file
161
Ping_Monitor.ps1
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user