# end2end-ping # # Ping a given Endpoint every second # measure roundtrip time and generate summaries # avg, min, max, lost (<1Sek) # # 20181114 initial Version based on end2end-pathping and end2end-udp3478 # 20190117 Fix bei IP-Adresse # 20190119 Ausgabe schöner # 20190702 Fix AVG berechnung ohne Loss Pakete, Farbausgabe, # Convert DNS to net class and remote [ordered] to support PS2 Clients # 20200217 Timestamp addiert # 20200224 Errorhandling # 20200226 DestinationNetworkUnreachable, Div/0 abgefangen # 20210204 Added PRTGPush function, TTL based on 128, Repeatcount to stop after given number of Pings # 20210205 Zusammenfassung nach Zeit statt Durchläufen. Pause zwischen zwei Ping mit Stoppuhr, CSV-File mit Ziel # 20210206 PRTG Ausgabetext mit Hostname erweitert, "toslow" addiert # 20210707 Fix mit backspacecount = 0 DIV0 # # Pending # TTL HopCount # Currently IPv4 DNS only # Umstellen von statischen Werten auf dynmische. Vorgabe des "erwartung" und dann +20%+50*+100% # # System.Net.NetworkInformation PingSend-Method # https://docs.microsoft.com/de-de/dotnet/api/system.net.networkinformation.ping.send?view=netframework-4.7.2 # System.Net.NetworkInformation PingReply Class # https://docs.microsoft.com/de-de/dotnet/api/system.net.networkinformation.pingreply?view=netframework-4.7.2 # IPStatus Enum # https://docs.microsoft.com/de-de/dotnet/api/system.net.networkinformation.ipstatus # param ( [string]$hostname = "internetbeacon.msedge.net", # samples google = 8.8.8.8 SfBOnlineEdge = 13.107.8.2, outlook.office365.com, internetbeacon.msedge.net [long]$pingidletimems = 1000, # ms to wait for the next ping (start to start) Defaut 1 Sec [long]$reporttimes = 60, # Time to wait for a summary [long]$buffersize = 160, # PING Buffersize [long]$repeatcount = -1, # stop after this number of runs. -1 = endless [long]$pingtimeoutms = 500, # ms timeout to wait for a reply. anything longer will be treated as loss/to slow [long]$slowlimitms = 200, # every pakeet slower that that is handled as to slow. muss be lower than pingtimeoutms [switch]$ipv4, # Use IPV4 [string]$csvfilename = "$PWD\end2end-ping_$($env:COMPUTERNAME)-$($hostname).csv", # Path to CSV File. Clear to disable CSV [switch]$sendtopipeline = $false, # send the summary to the pipeline for further processing [string]$prtgpushurl="" # specify PRTG-Push Url if required like http://prtg:5050/sensorid ) set-psdebug -strict Write-Host "end2end-ping: Start" Write-Host " Param Hostname : $($hostname)" Write-Host " Param pingidletimems : $($pingidletimems)" Write-Host " Param reporttimes : $($reporttimes)" Write-Host " Param Buffersize : $($buffersize)" Write-Host " Param repeatcount : $($repeatcount)" Write-Host " Param PingTimeout : $($pingtimeoutms)" Write-Host " Param slowlimitms : $($slowlimitms)" Write-Host " Param ipv4 : $($ipv4)" Write-Host " Param CSVFile : $($csvfilename)" Write-Host " Param sendtopipeline : $($sendtopipeline)" Write-host " prtgpushurl : $($prtgpushurl)" $host.ui.RawUI.WindowTitle = "End2End-PING to $($hostname)" Write-Host "Check IP-Address:" -NoNewline $remoteip = $null if ($hostname -as [ipaddress]) { write-host " Use given IP-Address $($hostname)" $remoteip = $hostname } else { Write-Host " Try DNS-Lookup $($hostname) " -NoNewline $error.clear() try { #$remoteip = ((resolve-DnsName $hostname -type A -ErrorAction SilentlyContinue)| where-object {$_.ipaddress})[0].ipaddress if ($ipv4) { $remoteip = ([System.Net.Dns]::GetHostAddresses($hostname) | Where-Object {$_.AddressFamily -eq "InterNetwork"})[0].IPAddressToString } else { $remoteip = ([system.net.dns]::GetHostAddresses($hostname))[0].ipaddresstostring } write-host "Using IP-Addresse $($remoteip)" } catch{ write-host "Unable to Resolve name. Use IP-Adresse" exit } } if ($null -ne $remoteip) { Write-Host "End2End-Ping:Initialize ICMP Object" $ping = new-object System.Net.NetworkInformation.Ping #$pingoptions = new-object System.Net.NetworkInformation.PingOptions #$pingoptions.DontFragment =$true; #$pingoptions.Ttl=10 Write-Verbose "End2End-Ping:Fill ICMP Buffer with Size:$($buffersize)" $asciiencoder = [system.Text.Encoding]::ASCII $buffer = $asciiencoder.GetBytes([string]("www.msxfaq.de end2end-ping").padright(($buffersize),"x")) if ($slowlimitms -gt $pingtimeoutms) { write-warning "slowlimitms $($slowlimitms) greater that pingtimeoutms $($pingtimeoutms). Adjusting" $slowlimitms = $pingtimeoutms } if ($csvfilename -ne "") { Write-Host "End2End-Ping:Initialize CSV-File"$csvfilename if (!(test-path $csvfilename -pathtype leaf)){ Write-Host "End2End-Ping:Adding CSV-Header" "Timestamp,RemoteIP,Min,Avg,Max,Total,Lost,statuspacketloss,statusavg2min,statusmax2avg" | out-file $csvfilename -append } } Write-Verbose "Initialize Result Property" $result = [pscustomobject]@{ timestamp = ((get-date).ToUniversalTime().tostring("u")) remoteip = [string]$($remoteip) max = [long]0 min = [long]9999999 avg = [long]0 total = [long]0 loss = [long]0 error = [long]0 toslow = [long]0 #ttl = [long]0 statuspacketloss=0 statusavg2min=0 statusmax2avg=0 } Write-Host "Start Endless ICMP Ping to $($remoteip) - press CTRL-C to Stop" Write-host "Textcode: .=Succesful T=Timeout($($pingtimeoutms)ms X=ExpiredTTL U=Unreachable S=SizeExceeded N=Neterror E=Error ?=Unknown " Write-host "Colorcode:" -nonewline Write-Host "<=5ms" -nonewline -backgroundcolor blue Write-Host "<=10ms" -nonewline -backgroundcolor green -foregroundcolor black Write-Host "<=50ms" -nonewline -backgroundcolor yellow -foregroundcolor black Write-Host "<=100ms" -nonewline -backgroundcolor magenta Write-Host ">100ms" -nonewline -backgroundcolor red Write-host " Starting test... Min/Avg/Max/Total/Loss" [long]$backspacecount = [math]::max((1000/$pingidletimems) / (60/$reporttimes),1) # used to reduce write-host outputs [long]$lastmaxms = 0 [long]$Avgsum = 0 $pingrepeattimewatch = [system.diagnostics.stopwatch]::new() $reportwatch = [system.diagnostics.stopwatch]::new() $reportwatch.Restart() while ($repeatcount -ne 0) { # stop if repeatcount is 1 if ($result.total -eq 0) {write-host "$((get-date).ToUniversalTime().tostring("u")):$($repeatcount):" -nonewline} $result.total++ if ($repeatcount -gt 0) {$repeatcount--} # ping remote host try { #$pingresult=$ping.send($remoteip,$pingtimeoutms,$buffer,$pingoptions) $pingrepeattimewatch.Restart() $pingresult=$ping.send($remoteip,$pingtimeoutms,$buffer) $pingresultstatus=$pingresult.Status.ToString() } catch { $pingresult="CatchError" $pingresultstatus="Error" } switch ($pingresultstatus) { "Error" { Write-Host "E" -nonewline -backgroundcolor red $result.error++ } "Success" { #switch ($pingresult.roundtriptime) { # {$_ -le 5} {Write-Host "." -nonewline -backgroundcolor blue;break;} # {$_ -le 10} {Write-Host "." -nonewline -backgroundcolor green -foregroundcolor black;break;} # {$_ -le 50} {Write-Host "." -nonewline -backgroundcolor yellow -foregroundcolor black;break;} # {$_ -le 100} {Write-Host "." -nonewline -backgroundcolor magenta ;break;} # default {Write-Host "." -nonewline -backgroundcolor red} #} $lastmaxms = [math]::Max($lastmaxms,$pingresult.roundtriptime) if ($result.total%$backspacecount -eq 0) { switch ($lastmaxms) { {$_ -le 5} {Write-Host "." -nonewline -backgroundcolor blue;break;} {$_ -le 10} {Write-Host "." -nonewline -backgroundcolor green -foregroundcolor black;break;} {$_ -le 50} {Write-Host "." -nonewline -backgroundcolor yellow -foregroundcolor black;break;} {$_ -le 100} {Write-Host "." -nonewline -backgroundcolor magenta ;break;} default {Write-Host "." -nonewline -backgroundcolor red} } [long]$lastmaxms = 0 } if ($pingresult.roundtriptime -le $result.min) {$result.min = $pingresult.roundtriptime} if ($pingresult.roundtriptime -ge $result.max) {$result.max = $pingresult.roundtriptime} if ($pingresult.roundtriptime -gt$slowlimitms ) {$result.toslow++} $Avgsum+=$pingresult.roundtriptime #$result.ttl = $pingresult.options.ttl } "TimedOut" { Write-Host "T" -nonewline -backgroundcolor red $result.loss++ } "TtlExpired" { Write-Host "X" -nonewline -backgroundcolor red $result.loss++ } "DestinationPortUnreachable" { Write-Host "U" -nonewline -backgroundcolor red $result.loss++ } "DestinationHostUnreachable" { Write-Host "U" -nonewline -backgroundcolor red $result.loss++ } "DestinationNetworkUnreachable" { Write-Host "N" -nonewline -backgroundcolor red $result.loss++ } "PacketTooBig" { Write-Host "S" -nonewline -backgroundcolor red $result.loss++ } default { Write-Host "?" -nonewline Write-Host $pingresult.Status $result.loss++ } } if ($reportwatch.Elapsed.TotalSeconds -gt $reporttimes) { $reportwatch.restart() # reset Time for next report # calculating Average if (($result.total-$result.loss) -ne 0) { $result.avg = [long]($Avgsum/($result.total-$result.loss)) } [long]$Avgsum = 0 Write-Host "$($result.min)" -NoNewline write-host "/" -nonewline if ($result.avg -gt (($result.min+1)*10)) { #ignore 0 as min write-host "$($result.avg)" -foregroundcolor yellow -nonewline $result.statusavg2min="1" } else { write-host "$($result.avg)" -nonewline } write-host "/" -nonewline if (($result.max) -gt (($result.avg+1)*10)) { write-host "$($result.max)" -foregroundcolor yellow -NoNewline #write-warning "Max 10 Times higher than Avg" $result.statusmax2avg="1" } else { write-host "$($result.max)" -NoNewline } write-host "/" -nonewline write-host "$($result.total)" -NoNewline write-host "/" -nonewline if (($result.loss*10) -gt $result.total) { write-host "$($result.loss)" -BackgroundColor Yellow -ForegroundColor black -NoNewline $result.statuspacketloss="1" } else { write-host "$($result.loss)" -NoNewline } #write-host "/" -nonewline #write-host "$($result.ttl/$result.total)" -NoNewline if ($csvfilename -ne "") { "$($result.timestamp),$($result.RemoteIP),$($result.min),$($result.avg),$($result.max),$($result.total),$($result.loss),$($result.statuspacketloss),$($result.statusavg2min),$($result.statusmax2avg)" | out-file $csvfilename -append } if ($sendtopipeline) { Write-Verbose "Sending result to Pipeline" $result } #region Send data to PRTG if enabled if ($env:cPRTGPUSHURL) { write-verbose "SendTo-PRTG: Post Result to PRTGProbe $($env:prtgpushurl)" Write-host "Pipe" -Nonewline $Scriptname = (split-path $MyInvocation.ScriptName -Leaf).replace(".ps1","") $prtgpushurl = "$($env:PRTGPUSHURL)/$($scriptname)_$($env:COMPUTERNAME)" } if ($prtgpushurl -ne "") { write-verbose "end2end-ping: Build PRTG XML" $prtgresult = "" if ($result.total -ge 1) { $prtgresult+= "" $prtgresult+= " " $prtgresult+= " Max" $prtgresult+= " $($result.max)" $prtgresult+= " Custom" $prtgresult+= " ms" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Min" $prtgresult+= " $($result.main)" $prtgresult+= " Custom" $prtgresult+= " ms" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Avg" $prtgresult+= " $($result.avg)" $prtgresult+= " Custom" $prtgresult+= " ms" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Packets total" $prtgresult+= " $($result.Total)" $prtgresult+= " Custom" $prtgresult+= " Pakets" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Packets lost" $prtgresult+= " $($result.loss)" $prtgresult+= " Custom" $prtgresult+= " Pakets" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Errors" $prtgresult+= " $($result.error)" $prtgresult+= " Custom" $prtgresult+= " Count" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Status packetloss" $prtgresult+= " $($result.statuspacketloss)" $prtgresult+= " Custom" $prtgresult+= " Status" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Status toslow" $prtgresult+= " $($result.toslow)" $prtgresult+= " Custom" $prtgresult+= " Status" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Status avg2min" $prtgresult+= " $($result.statusavg2min)" $prtgresult+= " Custom" $prtgresult+= " Status" $prtgresult+= " 1" $prtgresult+= " 0" $prtgresult+= " " $prtgresult+= " " $prtgresult+= " Status max2avg" $prtgresult+= " $($result.statusmax2avg)" $prtgresult+= " Custom" $prtgresult+= " Status" $prtgresult+= " 1" $prtgresult+= " 0" $prtgresult+= " " #$prtgresult+= " " #$prtgresult+= " statusmax2avg" #$prtgresult+= " $(128-$result.ttl)" #$prtgresult+= " Custom" #$prtgresult+= " TTL" #$prtgresult+= " 1" #$prtgresult+= " 0" #$prtgresult+= " " $prtgresult+= " 0" $prtgresult+= " Reply got from host $($hostname) IP:$($remoteip)" $prtgresult+= "" } else { $prtgresult+= "" $prtgresult+= " 1" $prtgresult+= " Unabled to Connect to host $($hostname) IP:$($remoteip)" $prtgresult+= "" } Write-Verbose "PRTG: $($prtgpushurl)" try { $Answer=Invoke-RestMethod ` -method "GET" ` -timeout 5 ` -URI ("$($prtgpushurl)?content=$($prtgresult)") if ($answer."Matching Sensors" -eq "1") { write-verbose "SendTo-PRTG:Found 1 Sensors OK" Write-host "PRTG" -ForegroundColor green -nonewline } elseif ($answer."Matching Sensors" -eq "0") { write-verbose "SendTo-PRTG:Found 0 matching sensors. Retry next run" Write-host "PRTG" -ForegroundColor Yellow -nonewline } else { write-Verbose "SendTo-PRTG:Invalid reply" Write-host "PRTG" -ForegroundColor Magenta -nonewline $answer } } catch { Write-verbose " Unable to Send PRTG-Data" Write-host "PRTG" -ForegroundColor red -nonewline Write-host "Exception: $($_.Exception.Message)" } } #endregion Send data to PRTG if enabled #Clear Result $result.timestamp = get-date -Format u $result.remoteip = $($remoteip) $result.max=0 $result.min=9999999 $result.avg = 0 $result.total = 0 $result.loss = 0 $result.error = 0 $result.toslow = 0 #$result.ttl = 0 $result.statuspacketloss=0 $result.statusavg2min=0 $result.statusmax2avg=0 write-host "" } # Wait for next interval $waittime = $pingidletimems - $pingrepeattimewatch.Elapsed.Milliseconds if ($waittime -ge 0) { start-sleep -milliseconds $waittime } } } else { Write-warning "end2end-ping: Stop - no IP-Address found" } Write-Host "end2end-ping: End"