I’ve been working on a script for our customers so we more accurately can measure the load on IIS Websites using Nagios.
Currently the script only gets the performance data and outputs an OK (exitcode 0). In the future I will implement WARNING and CRITICAL the performance values we need.
Example graph from a labserver.
Feel free to use and modify this script as you like.
Note: Script is tested on Windows Server 2008R2, 2012 and 2012R2 servers. Not tested on Windows Server 2008 but I suppose that it may work. Script is developed with Powershell 2.0 support. Don’t ask me why. 🙂
DISCLAIMER: This script is published on “As Is” basis. I will not take any responsibility for any damage this script might do to your production or test server environment. Please ensure that you test this properly in a non-production environment before running or scheduling the script in a production environment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
<# .SYNOPSIS Nagios script to monitor performance of IIS Web sites. .DESCRIPTION Script developed for Nagios(NSClient) use to monitor IIS performance for Web sites using Powershell module Microsoft.PowerShell.Commands.Diagnostics.dll As of this moment there are no WARNING och CRITICAL values for this script. Every output will be OK (0) as long as every Get/Set is OK. In the future I'll implement WARNING and CRITICAL values for the Performance values, beginning with Current Connections. Tested on Windows Server 2008R2, 2012 and 2012R2. .EXAMPLE 'This is an example of the string nsclient.ini.' check_iisperformance_state = cmd /c echo scripts\Check_IISPerformance_State.ps1 -WebSite $ARG1$; exit($lastexitcode) | powershell.exe -command - .EXAMPLE .\Check_IISPerformance_State.ps1 -OutPowershell If script is run in Powershell with the parameter $OutPowershell this is the last Output for the pipeline. ... Name Value ---- ----- ORDER10_Current Connections 17 ORDER11_Kilobytes Sent/sec 2 ORDER12_Kilobytes Received/sec 2 ORDER13_Kilobytes Total/sec 3 ORDER14_Connection Attempts... 1 ORDER15_Get Requests/sec 1 ORDER16_Head Requests/sec 0 ORDER17_Total Method Reques... 1 ORDER18_Post Requests/sec 0 ORDER19_Search Requests/sec 0 ORDER20_Files/sec 0 ORDER21_File Cache Hits % 0 ORDER22_Kernel: URI Cache F... 0 ORDER23_Kernel: URI Cache H... 0 ORDER24_Kernel: URI Cache M... 0 .NOTES Created on: 2016-02-04 10:13 Created by: Philip Haglund Organization: Omnicit AB Filename: Check_IISPerformance_State.ps1 Version: 1.0 Requirements: Powershell 2.0 Changelog: 2016-02-04 10:13 - Creation of script 2016-03-04 14:46 - Added missing Write-Output in catch blocks. Added Parameter help and other help messages. .LINK https://omnicit.se #> [CmdletBinding()] param( [Parameter( Position = 0, Mandatory = $false, HelpMessage = 'IIS Web Site name. Default "_Total"' )] [Alias('Site')] <# IIS Web Site name to get performance monitor data from. Default Web Site used is '_Total' which is all web sites on the host combined. #> [string]$WebSite = '_Total', [Parameter( Position = 1, Mandatory = $false, HelpMessage = 'Check interval for the performance counter. Default "1"' )] [Alias('SampleInterval')] [ValidateRange(1, 10)] <# Check interval for the performance counter. Specifies the time between samples in seconds. The minimum value and the default value are 1 second. If you set this value to '2' the Get-Counter cmdlet used in this script will double it's time. So If $Interval = 2 and $MaxSample = 10, the total time that Get-Counter will run is 20 seconds. #> [int]$Interval = 1, [Parameter( Position = 2, Mandatory = $false, HelpMessage = 'The number of samples to get from each counter. Default "10"' )] [Alias('Samples')] [ValidateRange(1, 20)] <# The number of samples to get from each counter. Specifies the number of samples to get from each counter. The default is 10 samples. If you set this value to '20' the Get-Counter cmdlet used in this script will collect 20 samples. So If $Interval = 2 and $MaxSample = 20, the total time that Get-Counter will run is 40 seconds. #> [int]$MaxSample = 10, [Parameter( Position = 3, Mandatory = $false, HelpMessage = 'Also displays the formated output to the powershell host' )] <# Display the collected performance data to powershell host. Parameter used for development and testing. #> [switch]$OutPowershell ) begin { #region Strings [int]$NagiosStatus = 0 [array]$OutputHash = @() [hashtable]$Connections = @{} [hashtable]$BReceived = @{} [hashtable]$BSent = @{} [hashtable]$BTotal = @{} [hashtable]$ConAttempts = @{} [hashtable]$Files = @{} [hashtable]$GRequests = @{} [hashtable]$HRequests = @{} [hashtable]$TMethod = @{} [hashtable]$PRequests = @{} [hashtable]$SRequests = @{} [hashtable]$CacheFileHits = @{} [hashtable]$CacheFlush = @{} [hashtable]$CacheHits = @{} [hashtable]$CacheMiss = @{} #endregion Strings #region Functions function Get-NagiosCode { [CmdletBinding()] param ( [Parameter( Position = 0, Mandatory = $true, ValueFromPipeLine = $true )] [ValidateNotNullOrEmpty()] [ValidateRange(0, 3)] [int]$NagiosStatus ) [hashtable]$NagiosHash = @{ 0 = 'OK: ' 1 = 'WARNING: ' 2 = 'CRITICAL: ' 3 = 'UNKNOWN: ' } $output = ($NagiosHash.GetEnumerator() | Where-Object -FilterScript { $_.Key -eq $NagiosStatus }) Write-Output -InputObject $output } function Stop-NagiosScript { [CmdletBinding( SupportsShouldProcess = $true )] param ( [Parameter( Position = 0, Mandatory = $true, ValueFromPipeLine = $true )] [ValidateNotNullOrEmpty()] [int]$NagiosStatus ) if ($PSCmdlet.ShouldProcess(('Using exit code {0}' -f $NagiosStatus), $MyInvocation.MyCommand.Name)) { exit $NagiosStatus } } function Format-StringToName { [CmdletBinding()] param ( [Parameter( Mandatory = $true, ValueFromPipeline = $true )] [AllowEmptyString()] [string]$string ) begin { $TextInfo = (Get-Culture).TextInfo } process { $lower = $string.ToLower() [string]$output = $TextInfo.ToTitleCase($lower) } end { $output } } #endregion Functions try { $VerifyCounter = Get-Counter -ListSet 'Web Service*' -ErrorAction Stop if (-not ($VerifyCounter)) { try { Write-Error -Message 'No Web Service performance counters found' -ErrorAction Stop } catch { #Should not happen } } } catch { $NagiosStatus = 1 $NagiosMessage = "$((Get-NagiosCode -NagiosStatus $NagiosStatus).Value)$($_.Exception.Message)" Write-Output -InputObject $NagiosMessage Stop-NagiosScript -NagiosStatus $NagiosStatus } $PreCounter = "\Web Service($($WebSite))\" $WebCounters = @("$($PreCounter)Current Connections", "$($PreCounter)Bytes Received/sec", "$($PreCounter)Bytes Sent/sec", "$($PreCounter)Bytes Total/sec", "$($PreCounter)Connection Attempts/sec", "$($PreCounter)Files/sec", "$($PreCounter)Get Requests/sec", "$($PreCounter)Head Requests/sec", "$($PreCounter)Total Method Requests/sec", "$($PreCounter)Post Requests/sec", "$($PreCounter)Search Requests/sec") $CacheCounters = @('\Web Service Cache\File Cache Hits %', '\Web Service Cache\Kernel: URI Cache Flushes', '\Web Service Cache\Kernel: URI Cache Hits %', '\Web Service Cache\Kernel: URI Cache Misses') } process { #region Get Counters try { $WebCounterStats = Get-Counter -Counter $WebCounters -SampleInterval $Interval -MaxSamples $MaxSample -ErrorAction Stop } catch { $NagiosStatus = 1 $NagiosMessage = "$((Get-NagiosCode -NagiosStatus $NagiosStatus).Value)$($_.Exception.Message)" Write-Output -InputObject $NagiosMessage Stop-NagiosScript -NagiosStatus $NagiosStatus } if ($CacheCounter) { try { $null = Get-Counter -Counter $CacheCounters -SampleInterval $Interval -MaxSamples $MaxSample -ErrorAction Stop } catch { $NagiosStatus = 1 $NagiosMessage = "$((Get-NagiosCode -NagiosStatus $NagiosStatus).Value)$($_.Exception.Message)" Write-Output -InputObject $NagiosMessage Stop-NagiosScript -NagiosStatus $NagiosStatus } } #endregion Get Counters #region Foreach loops (Counters) foreach ($WebCounterStat in $WebCounterStats) { foreach ($WebSample in $WebCounterStat.CounterSamples) { $Path = $WebSample.Path -replace '^.*\\' | Format-StringToName $CookedValue = $WebSample.CookedValue # Adds the performance value in each hashtable. switch ($Path) { 'Current Connections' { $Connections[0] += $CookedValue break } 'Bytes Received/sec' { $BReceived[0] += $CookedValue break } 'Bytes Sent/sec' { $BSent[0] += $CookedValue break } 'Bytes Total/sec' { $BTotal[0] += $CookedValue break } 'Connection Attempts/sec' { $ConAttempts[0] += $CookedValue break } 'Files/sec' { $Files[0] += $CookedValue break } 'Get Requests/sec' { $GRequests[0] += $CookedValue break } 'Head Requests/sec' { $HRequests[0] += $CookedValue break } 'Total Method Requests/sec' { $TMethod[0] += $CookedValue break } 'Post Requests/sec' { $PRequests[0] += $CookedValue break } 'Search Requests/sec' { $SRequests[0] += $CookedValue break } } } } foreach ($CacheSample in $CacheCounterStat.CounterSamples) { $Path = $CacheSample.Path -replace '^.*\\' | Format-StringToName $CookedValue = $CacheSample.CookedValue -replace ',', '.' # Adds the performance value in each hashtable. switch ($Path) { 'File Cache Hits %' { $CacheFileHits[0] += $CookedValue break } 'Kernel: URI Cache Flushes' { $CacheFlush[0] += $CookedValue break } 'Kernel: URI Cache Hits %' { $CacheHits[0] += $CookedValue break } 'Kernel: URI Cache Misses' { $CacheMiss[0] += $CookedValue break } } } #endregion Foreach loops (Counters) #region Hashtable for output. [hashtable]$OutputHash = @{ 'ORDER10_Current Connections' = ([math]::Round($Connections[0] / $MaxSample)) 'ORDER11_Kilobytes Sent/sec' = ([math]::Round(($BSent[0] / $MaxSample) / 1KB, 0)) 'ORDER12_Kilobytes Received/sec' = ([math]::Round(($BReceived[0] / $MaxSample) / 1KB, 0)) 'ORDER13_Kilobytes Total/sec' = ([math]::Round(($BTotal[0] / $MaxSample) / 1KB, 0)) 'ORDER14_Connection Attempts/sec' = ([math]::Round($ConAttempts[0] / $MaxSample, 0)) 'ORDER15_Get Requests/sec' = ([math]::Round($GRequests[0] / $MaxSample, 0)) 'ORDER16_Head Requests/sec' = ([math]::Round($HRequests[0] / $MaxSample, 0)) 'ORDER17_Total Method Requests/sec' = ([math]::Round($TMethod[0] / $MaxSample, 0)) 'ORDER18_Post Requests/sec' = ([math]::Round($PRequests[0] / $MaxSample, 0)) 'ORDER19_Search Requests/sec' = ([math]::Round($SRequests[0] / $MaxSample, 0)) 'ORDER20_Files/sec' = ([math]::Round($Files[0] / $MaxSample, 0)) 'ORDER21_File Cache Hits %' = ([math]::Round($CacheFileHits[0] / $MaxSample, 0)) 'ORDER22_Kernel: URI Cache Flushes' = ([math]::Round($CacheFlush[0] / $MaxSample, 0)) 'ORDER23_Kernel: URI Cache Hits %' = ([math]::Round($CacheHits[0] / $MaxSample, 0)) 'ORDER24_Kernel: URI Cache Misses' = ([math]::Round($CacheMiss[0] / $MaxSample, 0)) } #endregion Hashtable for output. # Generate an array from the hashtable $OutputHash. $HashOrder = ($OutputHash.GetEnumerator() | Sort-Object -Property Key) $n = 0 foreach ($Obj in $HashOrder) { # Removes anything before '_' and then removes the '_' sign. $Key = $Obj.Key -replace '.*_' if ($n -eq 0) { $NagiosMessage = "$((Get-NagiosCode -NagiosStatus $NagiosStatus).Value)$($Key): $($Obj.Value)" } else { $NagiosMessage = "$($Key): $($Obj.Value)" } $n++ # Write to Output Nagios Message (Status information and Extended information). Write-Output -InputObject $NagiosMessage } $n = 0 foreach ($Obj in $HashOrder) { # Removes anything before '_' and then removes the '_' sign. Replaces any whitespace $Key = $Key = $Obj.Key -replace '.*_' -replace '\s', '_' # Write to Output Nagios Performance Data. if ($n -eq 0) { Write-Output -InputObject "|$($Key)=$($Obj.Value)" } else { Write-Output -InputObject "$($Key)=$($Obj.Value)" } $n++ } } end { if ($PSBoundParameters.ContainsKey('OutPowershell')) { Write-Output -InputObject $HashOrder } else { # Exiting script with the last status code. Stop-NagiosScript -NagiosStatus $NagiosStatus } } |
Hello,
I really appreciate your sharing 🙂
I would like to ask how can i implement this script in my Nagios environment?
Thanks
Hello Amit,
You need to add a new Command in Nagios, example
Name: check_iisperformance_state
Commandline: $USER1$/check_nrpe -H $HOSTADDRESS$ -t 120 -c check_iisperformance_state -a ‘$ARG1$’
When that command is added you can either create a Service Template or a new custom Template added to a host. An argument is needed for the script to check a specific site or all sites. To check all sites the argument is “_Total”.
In the nsclient.ini / NSC.ini file add the following:
check_iisperformance_state = cmd /c echo scriptsCheck_IISPerformance_State.ps1 -WebSite $ARG1$; exit($lastexitcode) | powershell.exe -command –
/Philip
hi configured it in nagios but am getting all results as Zero in nagios . When chek with power shell in server I can get the status correctly
Hi Vinod!
The “check command” in Nagios how is it configured?
An example of the setup is:
$USER1$/check_nrpe -u -H $HOSTADDRESS$ -p 5666 -t 120 -c check_iisperformance_state -a ‘$ARG1$’
In the nsclient.ini file add the following:
check_iisperformance_state = cmd /c echo scriptsCheck_IISPerformance_State.ps1 -WebSite $ARG1$; exit($lastexitcode) | powershell.exe -command –
The default input in the Service Template should be “_Total” to monitor all IIS sites.
Regards
Philip
What is the service template look like for the host cfg. I know this is a little old, but am trying to get this to work.
I think i’m missing something.
Failed to parse arguments for command using old split string method: unknown escape sequence: cmd /c echo scriptsCheck_IISPerformance_State.ps1 -WebSite $ARG1$; exit($lastexitcode) | powershell.exe -command –
Hello David
The check command on your Nagios server (OP5, Centreon, XI etc) should look similar to:
$USER1$/check_nrpe -u -H $HOSTADDRESS$ -p 5666 -t 60 -c check_iisapplicationpool_state -a ‘$ARG1$’
The service template model in our environment uses the default “generic-service” with “Check Command” check_iisapplicationpool_state.
The arguments in the service template is named as “Excludes” and the value for the template is the string “empty”.
In the Check Command, have you specified any Argument Description (Excludes) or Argument Examples ‘!”empty”‘.
Hello Gonjer,
Thanks you for the script, working perfectly! Great work 🙂
But Im still searching how do you have the graph with all values because on my Nagios interface, i just have a graph on the current connection value and not on all the extended status values information. Do I Have to configure something else or should it be automatic ?
Regards from Paris
NB
Hello Gonjer,
I’m becoming crazy with this script, cause I have regularly followed your instructions, but it works perferctly when I start it with power shell on my server, whereas I’ve received blank graph on my Nagios dashboard.
Please can you help me?
Hi, philip.
Could you share the script mentioned in your post about NSclient?
it is named “Check_IISPerformance_State.ps1”
Thank you.
Hi OIG,
If you scroll down you’ll see the script in the pane.
Regards
Philip
Ah~~ I see, thank you. I thought the shell was just screen shot. 🙂
Hi, I have problem with ruuning this script in Nagiox XI
I have configured
command
$USER1$/check_nrpe -H $HOSTADDRESS$ -t 240 -c check_iisperformance_state -a $ARG1$
service
$USER1$/check_nrpe -H $HOSTADDRESS$ -t 240 -c check_iisperformance_state -a $ARG1$
in $ARG1$ field I have _Total
but when I test
[nagios@nagios ~]$ /usr/local/nagios/libexec/check_nrpe -H 192.168.0.102 -t 240 -c check_iisperformance_state -a _Total
Missing expression after unary operator ‘-‘.
At line:1 char:2
+ – <<<<
+ CategoryInfo : ParserError: (-:String) [], ParentContainsErrorR
ecordException
+ FullyQualifiedErrorId : MissingExpressionAfterOperator|
Where is the problem?
Hello Wojtek,
I have two questions.
1. Does i work when you run the PowerShell-script directly from the PowerShell host using: .\Check_IISPerformance_State.ps1 -OutPowershell ?
2. What if you try to omit the argument _Total with quotes? check_nrpe -H 192.168.0.102 -t 240 -c check_iisperformance_state -a “_Total”
Regards
Philip
Hi Philip,
I’ve changed monitored server and I have better results 🙂
Have you got a version with warning or critical alerts?
Your script is excellent.
.\Check_IISPerformance_State.ps1 -OutPowershell
PS C:\Program Files\NSClient++\scripts> .\Check_IISPerformance_State.ps1 -OutPowershell
OK: Current Connections: 13
Kilobytes Sent/sec: 0
Kilobytes Received/sec: 1
Kilobytes Total/sec: 1
Connection Attempts/sec: 0
Get Requests/sec: 0
Head Requests/sec: 0
Total Method Requests/sec: 0
Post Requests/sec: 0
Search Requests/sec: 0
Files/sec: 0
File Cache Hits %: 0
Kernel: URI Cache Flushes: 0
Kernel: URI Cache Hits %: 0
Kernel: URI Cache Misses: 0
|Current_Connections=13
Kilobytes_Sent/sec=0
Kilobytes_Received/sec=1
Kilobytes_Total/sec=1
Connection_Attempts/sec=0
Get_Requests/sec=0
Head_Requests/sec=0
Total_Method_Requests/sec=0
Post_Requests/sec=0
Search_Requests/sec=0
Files/sec=0
File_Cache_Hits_%=0
Kernel:_URI_Cache_Flushes=0
Kernel:_URI_Cache_Hits_%=0
Kernel:_URI_Cache_Misses=0
Name Value
—- —–
ORDER10_Current Connections 13
ORDER11_Kilobytes Sent/sec 0
ORDER12_Kilobytes Received/sec 1
ORDER13_Kilobytes Total/sec 1
ORDER14_Connection Attempts… 0
ORDER15_Get Requests/sec 0
ORDER16_Head Requests/sec 0
ORDER17_Total Method Reques… 0
ORDER18_Post Requests/sec 0
ORDER19_Search Requests/sec 0
ORDER20_Files/sec 0
ORDER21_File Cache Hits % 0
ORDER22_Kernel: URI Cache F… 0
ORDER23_Kernel: URI Cache H… 0
ORDER24_Kernel: URI Cache M… 0
PS C:\Program Files\NSClient++\scripts>
hi wojtek
i have the same problem, mm i dont understand that part “I’ve changed monitored server”, im testing in a windows server 2012 r2 datacenter but i dont catch the problem.
thanks in advance
Hi David,
I think he means that he monitors another Windows Server instead of his initial one which probably didn’t have any data to begin with.
What do you mean with “I don’t catch the problem”?
/Regards
Philip