cancel
Showing results for 
Search instead for 
Did you mean: 
Create Post

Web Site (PowerShell) monitor template that allows customized healthy status codes

More than a few of us have run into a situation in which we need to monitor a web site that requires authentication, but cannot provide credentials for various reasons. In these cases, the monitored site returns a 401 (Unauthorized) status code, and Orion alerts that the site is down. I created this template because the built-in HTTP and HTTPS monitors do not provide a way to mark specific status codes as OK.

This template monitors a web site using PowerShell's Invoke-WebRequest cmdlet. It passes the node 'Caption' property to the script arguments, and this be modified to use another name-related property if necessary. The script body follows:

Web Site (PowerShell).png

Within the script, the statusCodesAllowed array is populated with 200 and 401. Any status code that you add to this array will be considered healthy by the monitor. Assuming a simple hostname-based URL and assuming HTTPS, the ${Node.Caption} argument is passed into the $serverName variable, and then used in the URI as https://$serverName. This can easily be customized to fit your needs.

In the Invoke-WebRequest cmdlet, the following optional parameters are also used:

  • -Method Head - Reduces bandwidth and processing by requesting only headers and not the full body of the web page.
  • -UseDefaultCredentials - Uses the credentials of the current user (Orion service) to send the web request.
  • -UseBasicParsing - uses the response object for HTML content without Document Object Model (DOM) parsing. This parameter is required when Internet Explorer is not installed on the computers, such as on a Server Core installation of a Windows Server operating system. This is the default behavior for PowerShell 6.

When the request is successful, the script is able to return the status code and description directly from the request results. When the web request fails (e.g. a 401 response), the Catch block takes over and processes the response. The status code is returned in the request's error message, and appears to always be written between parenthesis in a message that describes the status. The error message is parsed to get the 3-digit status code, and the code is then evaluated to see if the statusCodesAllowed array contains the current status code. This result of this evaluation is a Boolean that gets cast as an integer: 1 for true (OK) and 0 for false (NOT OK). Finally, the script cleans up its variables simply to be a good citizen and help prevent memory leaks.

Back in the template settings, the script output is returned as a statistic called "Status". I evaluate my status thresholds as follows:

  • Warning: not equal to 1 (OK) for a single poll
  • Critical: not equal to 1 (OK) for at least 3 polls

ScriptOutput.png

This template gets assigned to nodes that I usually create specifically for each web site. (This is usually because our sites are often load balanced and I might already be monitoring each server-specific URL on the server nodes themselves.)

And finally, we can now monitor web sites with a customizable list of HTTP status codes that we consider to be healthy! Happy monitoring. Ping me if you have any questions about customizing this monitor.

Inspired by: sbarger​, sage4man​, sans​, akhasheni​, irby​, and st.crispan​!

Labels (1)
Attachments
Comments

If you're interested in testing the PowerShell script yourself outside of Orion, here 'tis!

$serverName = $args[0] #Replace this value with a servername for your own manual testing.

$statusCodesAllowed = (200,401) #Update this array to include the HTTP status codes that you want to mark as OK.

$stat = 0

Try {

    $web = Invoke-WebRequest -Uri https://$serverName -Method Head -UseDefaultCredentials -UseBasicParsing -ErrorAction Stop

    $stat = [int]($statusCodesAllowed -contains $web.statusCode)

    Write-Host 'Statistic.Status: '$stat

    Write-Host 'Message.Status: ' $web.StatusCode $web.StatusDescription

}

Catch {

    $statusCode = ($_.Exception.Message.Substring(($_.Exception.Message.IndexOf('(')+1),3))

    $stat = [int]($statusCodesAllowed -contains $statusCode)

    Write-Host 'Statistic.Status: '$stat

    Write-Host 'Message.Status: '$_.Exception.Message

}

Finally { Remove-Variable serverName,statusCodesAllowed,stat,web,statusCode -ErrorAction SilentlyContinue }

Thanks for uploading this.

Hi sturdyerde

Need some help.. can u let me know where i need to pass the device name and the URL in this script? I have recently got requirement to monitor the URLs but credentials cannot be provided by the customer.. so hence when i came across this thread i thought this may work for me.. I have the URL detail with me and the device to which i can tag this to... so if u can assist me here it would be great..

pastedImage_0.png

There are a few different ways you could approach this, depending on how comfortable you are with customizing your Orion application monitor template and/or customizing PowerShell scripts. To get started, let's look just at the script.

When this script is part of an application monitor that is assigned to a node, the name of the device is passed through where you see ${Node.Caption}.

The node caption (node name) is passed to the PowerShell script as an argument (parameter). This is the first (and only) argument in the list, and the script saves the node name in the serverName variable ( $serverName = $args[0] ).

In the Try block, look at the first line that starts with $web = Invoke-WebRequest -Uri https://$serverName ... This is where you see the $serverName used, and where you can specify a custom URL.

If your URL is https://$serverName/application/testme, then this full line would look like:

$web = Invoke-WebRequest -Uri https://$serverName/application/testme -Method Head -UseDefaultCredentials -UseBasicParsing -ErrorAction Stop

And that's more or less it.

thanks.. let me try this..

i was able to work this out...

Just passed the URL as argument and assigned to an 'external node'... I had few URL which required authentication and since passing code was an option here it worked perfectly fine..i gave 200 and 401 as the code so that it will always identify the URL as UP. only if its completely not accessible then status should turn critical...

Just one more thing..incase i want to track the response time of the URL, then using the metric which the monitor generates by default, is safe to use?

pratikmehta003  wrote:

Just one more thing..incase i want to track the response time of the URL, then using the metric which the monitor generates by default, is safe to use?

Sorry, not sure I follow your question exactly...but this script doesn't measure response time. It only returns a boolean value when checking to see if the response code is listed in the script's "statusCodesAllowed" array.

That answers my question

Love it! Added authentication

$creds = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('USERNAME:UPASSWORD'))

and changed this to use it

$web = Invoke-WebRequest -Uri https://${Node.Caption} -Headers @{ 'Authorization' = 'Basic ' + $creds} -UseDefaultCredentials -UseBasicParsing -ErrorAction Stop

stevenstadel  wrote:

Love it! Added authentication

$creds = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('USERNAME:UPASSWORD'))

and changed this to use it

$web = Invoke-WebRequest -Uri https://${Node.Caption} -Headers @{ 'Authorization' = 'Basic ' + $creds} -UseDefaultCredentials -UseBasicParsing -ErrorAction Stop

This is great for when running the script manually, but how would you securely provide a username and password to an application monitor?

Version history
Revision #:
1 of 1
Last update:
‎03-06-2019 01:13 PM
Updated by: