External monitoring of Azure web apps with Statuscake

2017, Jul 07    

The problem with monitoring from within the platform your app lives in, is that you’re unaware of any connectivity problems that exists outside of your environment. True, you’re not wanting to be monitor Internet weather either but in reality having both monitoring systems is a must.

Statuscake, is an endpoint monitoring service that offers a bunch of features around web endpoint monitoring – but i’ll just be looking at the most basic http check which will look for a 200 response.
There are many other services available that perform this function – including Pingdom which I’ve used for years (and actually monitors this blog).
When I first found Statuscake, years ago – it offered more monitoring servers in the UK than any other provider so provided the USP. What I liked about it was the API and the service it provides as part of its free tier.

statuscake monitoring

I’ve written several automation scripts against it’s API and have one blog post here.

Now that we’re happy with Endpoint monitoring through Statuscake, here’s the powershell functions I’ve written to perform a bunch of standard tasks.

#Gordon.byers@microsoft.com
#Powershell script is provided as-is and without any warranty of any kind

function Delete-StatusCakeTests() {
    param (
        [string] $statuscakeUsername,
        [string] $stauscakeApiKey,
        $testIds
    )

    $baseurl = "https://www.statuscake.com/API"
    $testurl = "$baseurl/Tests"
    $authHeaders = @{"Username"="$statuscakeUsername";"API"="$stauscakeApiKey"}

    $testIds | % {
        $url = $testurl +"/Details/?TestID=$_"
        Write-Output $url
        $tResponse = Invoke-WebRequest $url -Headers $authHeaders -Method Delete
    }
    return $tResponse
}

function Get-StatusCakeTests() {
    param (
        [string] $statuscakeUsername,
        [string] $stauscakeApiKey
    )

    $baseurl = "https://www.statuscake.com/API"
    $testurl = "$baseurl/Tests"
    $authHeaders = @{"Username"="$statuscakeUsername";"API"="$stauscakeApiKey"}

    $tResponse = Invoke-WebRequest $testurl  -Headers $authHeaders
    $definedUrlTests = $tResponse.Content | ConvertFrom-Json

    return $definedUrlTests
}

function Get-StatusCakeDetailedTest() {
    param (
        [string] $statuscakeUsername,
        [string] $stauscakeApiKey,
        $testId
    )

    $baseurl = "https://www.statuscake.com/API"
    $testurl = "$baseurl/Tests"
    $authHeaders = @{"Username"="$statuscakeUsername";"API"="$stauscakeApiKey"}

    $tResponse = Invoke-WebRequest "$testurl/Details/?TestID=$testId"  -Headers $authHeaders
    $testData = $tResponse.Content | ConvertFrom-Json

    return $testData
}

function Add-StatusCakeTestUrl() {
    param (
        [string] $statuscakeUsername,
        [string] $stauscakeApiKey,
        [string] $websiteName,
        [string] $websiteUrl
    )

    $baseurl = "https://www.statuscake.com/API"
    $testurl = "$baseurl/Tests/"
    $authHeaders = @{"Username"="$statuscakeUsername";"API"="$stauscakeApiKey"}

    $testParams = @{WebsiteName="$websiteName"  ;
                    WebsiteURL=$websiteUrl;
                    WebsiteHost="Microsoft Azure";
                    CheckRate="300";
                    TestType="HTTP";
                    ContactGroup="0";
                    Confirmation=3;
                    }
    $tResponse = Invoke-WebRequest "$testurl/Update" -Headers $authHeaders -Method Put -Body $testParams
    $tResult = $tResponse.content | ConvertFrom-Json

    return $tRestult
}

So how can we get some monitoring action happening from Azure? Let’s stick to powershell and start using the Azure cmdlets to query all the Web App endpoints. Once we have the list of Azure addresses, we can then query Statuscake to see which one’s do not yet have a monitor set up – then add it. In this way we can host the powershell in Azure Automation to run on a scheduled basis.

#Gordon.byers@microsoft.com
#Powershell script is provided as-is and without any warranty of any kind

param (
    $statuscakeUsername="GordonbMsft",
    $stauscakeApiKey="Gd2plF9ffJ5xTzv7LFWH"
)

#Get list of urls that are currently being tested.
$definedUrlTestNames = Get-StatusCakeTests $statuscakeUsername $stauscakeApiKey | Select-Object WebsiteName | % {$_.WebsiteName}

#Use in the event you want to reset Status Cake.
#$definedUrlTestIds =Get-StatusCakeTests $statuscakeUsername $stauscakeApiKey | Select-Object TestID | % {$_.TestId}
#Delete-StatusCakeTests $statuscakeUsername $stauscakeApiKey 2325596 $definedUrlTestIds

#Get detailed test information - if needed
#Get-StatusCakeDetailedTest $statuscakeUsername $stauscakeApiKey


#Login to Azure
Login-AzureRmAccount 

#Grab a list of all the web apps
$allwebapps = Get-AzureRmWebApp 
$webAppNames = $allwebapps | Select-Object Name | % {$_.Name}

#Filter down to just the unmonitored webapps
$webAppsNamesToAdd = Compare-Object $webAppNames $definedUrlTestNames -PassThru
Write-Output "Azure has $($allwebapps.Count) web apps defined.  $($webAppsNamesToAdd.count) of them do not have a Url test set up in Statuscake."

$webAppsToAdd = $allwebapps | Where-Object {$webAppsNamesToAdd -contains $_.Name } | Select-Object Name, ResourceGroup, Hostnames

$webAppsToAdd | % {
    $hostnames = $_.hostnames.split(",")
    $hostname = if($hostnames -isnot [system.array]) {$hostnames} else {$hostnames[0]}

    Write-Output "Setting up url test for $($_.Name) on hostname $($hostname)"
            
    Add-StatusCakeTestUrl $statuscakeUsername $stauscakeApiKey $_.Name $hostname
}

What this will give you for free, is a record of availability and performance metrics. It can be extended to alert you upon detected downtime. In short, you’ve got nothing to lose by monitoring all your Azure App Services automatically. In fact a side benefit of the monitoring will be that in the event your Web Application app pools go to sleep, monitoring will keep them alive.

Powershell scripts available on GitHub.