# end2end HTTP # # Einfaches Skript, welches immer wieder die gleiche HTML-Seite ausliest und den # # # 20121201 Version 1.0 FC Initale Version # 20121212 Version 1.1 FC Ausgsbe der Message auf erste 10 Zeichen beschränkt # 20180108 Version 1.2 FC Sehr viele Umbauten und erweiterungen # 20181212 Version 1.3 FC report2screeen addiert # 20180307 Version 1.4 FC httperrorcode numeric, small output changes # 20180328 Version 1.5 FC Parameterurls und report2screen=True # 20180426 Version 20180426 FC Versionnummer to yyymmdd # 2018058 Ausgabe optimiert, maxiteration entfernt und endlos laufen lassen, reportcsv auf export-csv, SendTo-PRTG # 20181123 Kosmetische Korrekturen # 20190115 $ProgressPreference silentlycontinue # 20190120 Colorcoding # 20190701 Fix: urltemplate auf "null" damit URL greift # 20190702 Kosmetik. Window Title update # 20191008 Timestamp in Ausgabe, Keydetected kuerzer # 20191009 Pause addiert und [System.Console]::ReadKey($true) addiert # 20191217 maxredirect =0, responsefactor addiert, Error handling, sharepoint/onedrive template, SummaryCSV, url/urltemplate # 20191218 SharePoint-Server Counter aus Header addiert mit template SP1, Frontend-Ausgabe, Testname addiert # 20200128 Fix bei IIS Latency und Ausgabe des lokalen PC als Spalte addiert # 20200204 Fix Index Array 0 bei SPHeader, wenn nicht da # 20200215 Added -Headers @{"Cache-Control"="no-cache"}, # 20200813 Fix prtg # 20200831 PRTG-Integration korrigiert # 20210225 Invoke-Webrequest changed from GET to HEAD only. Better latency and less traffic # 20210705 Fix hedaer conversion char to string to uint16 (X-SharePointHealthScore etc) [cmdletbinding()] param( [string]$url = "", # url to connect and load data from [ValidateSet("favicon","smime","health","opath","sharepoint","sp1","sp2","onedrive","",$null)] [String]$urltemplate = "favicon", # use predefined set [long]$slowabsms = 1000, # Absolute maximum time in msec to rate a request als Slow [long]$slowavgfactor = 5, # Factor for average slow calculation [string]$testname = "default", # Option to add a label to trace files [string]$debugcsv = "$PWD\end2end-http_$($testname)_$($env:COMPUTERNAME)-debug.csv", # Path to CSV File. Clear to disable CSV [string]$reportcsv = "$PWD\end2end-http_$($testname)_$($env:COMPUTERNAME)-report.csv", # Path to CSV File. Clear to disable CSV [switch]$report2pipe = $false, # enable to send output to stdout pipeline [switch]$report2screen = $false, # enable to send output to stdout pipeline [string]$smtpserver = "", # Enter Smarthost to send Alert Mail [string]$smtpto = "", # Recipient for Alert Mails [string]$smtpfrom = "", # SMTP Sender Adress [long]$sleeptime = 1000, # time between the requests [long]$maxiteration = 86400, # maximum number of checks, about 24h [int]$responsefactor = 1, [string]$prtgpushurl = "", #"http://prtg:5050/end2end-$($url)_$($env:COMPUTERNAME)", # url to PRTG server with sensor prefix [int]$reportinterval = 60 # time in seconds to send a summary ) # hide write-progress with invoke-webrequest $ProgressPreference="silentlycontinue" function checkexitorpause { if ([console]::KeyAvailable) { $keycode = [System.Console]::ReadKey($true) if ($keycode.key -eq "X") { write-host "X" -ForegroundColor Magenta -nonewline return $true } elseif ($keycode.key -eq "P") { write-host "P" -ForegroundColor Magenta -nonewline $keycode = [System.Console]::ReadKey($true) if ($keycode.key -eq "X") { write-host "X" -ForegroundColor Magenta -nonewline return $true } else { return $false } } else { return $false } } else { return $false } } # ----------------------------------------------------- # sendto-prtg helper to send data to PRTG # ----------------------------------------------------- function sendto-prtg ( [string]$prtgresult, # XML Structure [string]$prtgpushurl) # HTTP-PUSH-url { if ($prtgpushurl -ne "" ) { write-host "SendTo-PRTG: Post Result to PRTGProbe $prtgpushurl" try { $Answer=Invoke-RestMethod ` -method "GET" ` -URI ("$($prtgpushurl)?content=$($prtgresult)") } catch { write-Warning "SendTo-PRTG:Catch Request" } if ($answer."Matching Sensors" -eq "1") { write-host "SendTo-PRTG:Found 1 Sensors OK" } elseif ($answer."Matching Sensors" -eq "0") { write-warning "SendTo-PRTG:Found 0 matching sensors. Retry next run" } else { write-Warning "SendTo-PRTG:Invalid reply" $answer } } } $error.clear() write-host "End2End-HTTP: Start" write-host " Parameter sleeptime ms : $($sleeptime)" write-host " Parameter maxiteration : $($maxiteration)" write-host " Parameter reportinterval: $($reportinterval)" write-host " Parameter reportcsv : $($reportcsv)" write-host " Parameter debugcsv : $($debugcsv)" write-host " Parameter prtgpushurl : $($prtgpushurl)" [string]$hostname=[system.net.Dns]::GetHostEntry("localhost").hostname Write-Host " Local DNS-Hostname :$($hostname)" if ($url -ne "") { Write-host "Parameter url : $($url)" } else { Write-host "Parameter urltemplate: $($urltemplate)" switch ($urltemplate){ "favicon" {$url = "https://outlook.office365.com/owa/favicon.ico"} "smime" {$url = "https://outlook.office365.com/owa/smime/owasmime.msi"} "health" {$url = "https://outlook.office365.com/owa/healthcheck.htm"} "opath" {$url = "https://login.microsoftonline.com/common/oauth2/authorize"} "sharepoint" {$url = "https://netatwork.sharepoint.com/"} "sp1" {$url = "https://netatwork.sharepoint.com/_layouts/15/SPAndroidAppManifest.aspx"} "sp2" {$url = "https://netatwork.sharepoint.com/_layouts/15/images/spmobileandroidappicon.png"} "sp3" {$url = "https://netatwork.sharepoint.com/_layouts/15/blank.js"} "onedrive" {$url = "https://netatwork-my.sharepoint.com/"} default {} } } write-host "End2End-HTTP: URL = $($url)" $host.ui.RawUI.WindowTitle = "End2End-HTTP $($url)" $lastreporttime = get-date [long]$reportsuccesscount=0; # count all successful request [long]$reportslowcount=0; # count slow requests [long]$reportfailcount=0; # count all with hard failuer [long]$reportrequestsum=0; # sum of all received bytes [long]$prtgoverlimitcount=0; # number of request over average [long]$prtgaveragetime10=0; # maximum response time of last 10 checks [long]$prtgmintime=99999; # minimum respsonse time of last checks [long]$prtgmaxtime=0; # average resonse time of last checks [long]$prtgtotalbytes=0; # sum of all received bytes Write-host "Colorcode:" -nonewline Write-Host "<=20ms" -nonewline -backgroundcolor blue Write-Host "<=50ms" -nonewline -backgroundcolor green -foregroundcolor black Write-Host "<=100ms" -nonewline -backgroundcolor yellow -foregroundcolor black Write-Host "<=200ms." -nonewline -backgroundcolor magenta Write-Host ">200ms" -backgroundcolor red write-host "End2End-HTTP:Keyboard: X=Exit P=Pause" -BackgroundColor Blue $stopscript=$false write-host "$((get-date).ToUniversalTime().tostring("u")):" -nonewline while (!$stopscript) { $Error.Clear(); Write-verbose "End2End-HTTP: Initializing Result Object" $result = [pscustomobject][ordered]@{ Timestamp = ((get-date).ToUniversalTime().tostring("u")) Clientname = $hostname url = $url httpstatuscode = "" httpbytes = 0 Status = "" Message = "" totalduration = $null networkduration = $null avg10 = 0 SPIisLatency = 0 SPRequestDuration = 0 SPHealthScore = 0 SPClientServiceRequestDuration = 0 frontendserver = "" } try { write-verbose "End2End-HTTP: Downloading $url" [datetime]$TimeStart = [datetime]::Now; $webresult = invoke-webrequest ` -uri $url ` -Timeoutsec 2 ` -UseBasicParsing ` -Method HEAD ` -Headers @{"Cache-Control"="no-cache"} ` -MaximumRedirection 0 ` -ErrorAction SilentlyContinue $result.totalDuration = [long]([datetime]::Now - $TimeStart).TotalMilliseconds write-verbose "End2End-HTTP: TotalDuration: $($result.totalDuration)" $result.httpstatuscode = $webresult.statuscode write-verbose "End2End-HTTP: Statucode $($webresult.statuscode)" $result.httpbytes = $webresult.RawContentLength # parse SharePoint header Write-Verbose "webresult.Headers.SPIisLatency: $($webresult.Headers.SPIisLatency)" if ($webresult.Headers.SPIisLatency) { $result.SPIisLatency = [uint16]($webresult.Headers.SPIisLatency[0].tostring()) } write-verbose "webresult.Headers.SPRequestDuration $($webresult.Headers.SPRequestDuration)" if ($webresult.Headers.SPRequestDuration){ $result.SPRequestDuration = [uint16]($webresult.Headers.SPRequestDuration[0].tostring()) } Write-verbose "webresult.Headers.'X-SharePointHealthScore' $($webresult.Headers.'X-SharePointHealthScore')" if ($webresult.Headers.'X-SharePointHealthScore') { $result.SPHealthScore = [uint16](($webresult.Headers.'X-SharePointHealthScore')[0].tostring()) # convert char to string } Write-Verbose "webresult.Headers.SPClientServiceRequestDuration $($webresult.Headers.SPClientServiceRequestDuration))" $result.SPClientServiceRequestDuration = $webresult.Headers.SPClientServiceRequestDuration if ($webresult.Headers.'X-MSEdge-Ref') { $result.frontendserver = $webresult.Headers.'X-MSEdge-Ref'.split(" ")[5] } elseif ($webresult.Headers.'x-feserver') { $result.frontendserver = $webresult.Headers.'x-feserver'.split(",")[0] } else { $result.frontendserver = "" } if ($result.Sprequestduration -ne "") { $result.networkduration = $result.totalDuration - $result.SPIisLatency - $result.SPRequestDuration } else { $result.networkduration = $result.totalDuration } switch ($result.networkduration) { {$_ -le (20 * $responsefactor) } {Write-Host "." -nonewline -backgroundcolor blue;break;} {$_ -le (50 * $responsefactor)} {Write-Host "." -nonewline -backgroundcolor green -foregroundcolor black;break;} {$_ -le (100 * $responsefactor)} {Write-Host "." -nonewline -backgroundcolor yellow -foregroundcolor black;break;} {$_ -le (200 * $responsefactor)} {Write-Host "." -nonewline -backgroundcolor magenta ;break;} default {Write-Host "." -nonewline -backgroundcolor red} } $prtgtotalbytes+=$webresult.RawContentLength $result.Message = "" if ($result.networkduration -ge $slowabsms){ $result.status = "SLOWABS" $reportslowcount++ } else { $result.status = "OK" $reportsuccesscount++ } if ($result.networkduration -gt $prtgmaxtime) {$prtgmaxtime = $result.networkduration} if ($result.networkduration -lt $prtgmintime) {$prtgmintime = $result.networkduration} $reportrequestsum += $result.networkduration if ($prtgaveragetime10 -eq 0) { write-verbose "End2End-HTTP: Set initial Average to first result $($result.networkduration)" $prtgaveragetime10 = $result.networkduration } else { $prtgaveragetime10 = ((($prtgaveragetime10*9) + $result.networkduration)/10) } $result.avg10 = $prtgaveragetime10 if ($result.networkduration -gt ($prtgaveragetime10*$slowavgfactor)) { $prtgoverlimitcount++ $result.status = "SLOWAVG" } } catch { # $_ write-verbose "End2End-HTTP: Failed" write-host "E" -BackgroundColor red -nonewline $result.Message = $Error[0].tostring() $result.networkduration = -1 $result.status = "FAIL" $result.httpstatuscode = "Error" $result.httpbytes = 0 $reportfailcount++ $error.clear() } if (($result.status -ne "OK") -and ($smtpserver -ne "")){ send-mailmessage ` -from $smtpfrom ` -to $smtpto ` -subject "End2End-http: $url slower than $slowabsms msec" ` -body "End2End-http: $url slower than $slowabsms msec" ` -smtpServer $smtpserver } if ($result.httpstatuscode -eq "Error"){ $result.httpstatuscode = 600 } # $webresult.headers # Send results to file if ($debugcsv) { $result | export-csv -path $debugcsv -append -notypeinformation } if ($report2pipe){ # sending every single result to pipeline $result } if (((get-date) - $lastreporttime).totalseconds -ge $reportinterval) { $average=([long]($reportrequestsum/($reportsuccesscount+$reportslowcount+$reportfailcount+$prtgoverlimitcount))) #write-host " OK=$($reportsuccesscount) Slow=$($reportslowcount) Fail=$($reportfailcount) MIN=$($prtgmintime) AVG=$($average)ms MAX=$($prtgmaxtime) X=End" write-host " OK/Slow/Fail:$($reportsuccesscount)/$($reportslowcount)/$($reportfailcount) - Min/Avg/Max:$($prtgmintime)/$($average)/$($prtgmaxtime)" if ($result.networkduration -lt $prtgmintime) {$prtgmintime = $result.networkduration} if ($prtgmintime -eq 99999) {$prtgmintime=""}; # Send results to file if ($reportcsv) { $reportresult = [pscustomobject][ordered]@{ Timestamp =((get-date).ToUniversalTime().tostring("u")) url =$url Clientname =$hostname reportsuccesscount =$reportsuccesscount reportslowcount =$reportslowcount reportfailcount =$reportfailcount reportrequestsum =$reportrequestsum prtgoverlimitcount =$prtgoverlimitcount prtgaveragetime10 =$prtgaveragetime10 prtgmintime =$prtgmintime prtgmaxtime =$prtgmaxtime prtgtotalbytes =$prtgtotalbytes } $reportresult | export-csv -path $reportcsv -append -notypeinformation } if ($prtgpushurl -ne "") { write-verbose "End2End-HTTP: PRTG Push URL Found" Write-host "P" -nonewline [string]$prtgresult = ' Requests OK '+$reportsuccesscount+' Absolute Count Requests to slow '+$reportslowcount+' Absolute Count Requests failed '+$reportfailcount+' Absolute Count Request much slower than average '+$prtgoverlimitcount+' Absolute Count Total Received Bytes '+$prtgtotalbytes+' Bytes Absolute Average Request Time '+ $average +' ms Absolute Longest Request '+$prtgmaxtime +' ms Absolute Fastest Request '+$prtgmintime +' ms Absolute End2End HTTP Monitoring ' Sendto-prtg $prtgresult $prtgpushurl } else { write-verbose "End2End-HTTP:No PRTG Push URL Found - SKIP" } if ($report2screen){ write-host "" #Write-Host "Summaryreport to Screen" write-host " SuccessCount : $($reportsuccesscount)" Write-Host " Requests to slow : $($reportslowcount)" Write-Host " Requests failed : $($reportfailcount)" Write-Host " much slower than avg: $($prtgoverlimitcount)" Write-Host " Total Received Bytes: $($prtgtotalbytes)" Write-Host " Average Request Time: $($average) ms" Write-Host " Longest Request : $($prtgmaxtime ) ms" Write-Host " Fastest Request : $($prtgmintime) ms" } $lastreporttime = Get-Date [long]$reportsuccesscount=0; # count all successful request [long]$reportslowcount=0; # count slow requests [long]$reportfailcount=0; # count all with hard failuer [long]$reportrequestsum=0; # number of reqests to calculate the average [long]$prtgoverlimitcount=0; # number of request over average [long]$prtgmintime=99999; # minimum respsonse time of last checks [long]$prtgmaxtime=0; # average resonse time of last checks [long]$prtgtotalbytes=0; # sum of all received bytes write-host "$($result.Timestamp):" -nonewline } else { write-verbose "End2End-HTTP:Report generation Timeout not expired - SKIP" } start-sleep -milliseconds $sleeptime $stopscript = checkexitorpause } Write-host "End2End-HTTP: End"