Jonathan's Blog
Deploying Proactive CPU Monitoring for an Azure Web App with Azure DevOps

Deploying Proactive CPU Monitoring for an Azure Web App with Azure DevOps

Published

I recently had a requirement to enable Proactive CPU Monitoring for an Azure Web App as part of our deployment process.

Often the easiest way to discover how to deploy something to Azure is to build it in the portal and then export the ARM template (hopefully someday export to bicep). When I set up a test app, enabled these settings, and exported the template, these settings were disappointingly missing.

I reached out to some folks on Twitter and Puneet Gupta was kind enough to reply and post this article .

What Puneet shared worked well to enable the setting; however, it is only part of the solution. The App Service requires WEBSITE_DAAS_STORAGE_SASURI configuration setting to exist. This setting is a Shared Access Signature URI to a storage account. The portal can generate this for you, but much like the monitoring settings, this will be wiped away with a new deployment.

For the rest of this post, I will assume you have an App Service and a storage account setup. Both of those are easy enough to deploy, so I won't take the time to go over that.

The complete solution is to generate this token with Azure PowerShell tasks in Azure DevOps.

$webApp = "App Name"
$resourceGroup = "Resource Group"
$storageAccount = "Storage Account"
$container = "memorydumps"

$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroup -Name $storageAccount).Value[0]
$context = New-AzStorageContext -StorageAccountName $storageAccount -StorageAccountKey $storageAccountKey
$containerUri = (Get-AzStorageContainer -Container $container -Context $context).CloudBlobContainer.Uri.AbsoluteUri
$startTime = (Get-Date).AddMinutes(-15)
$endTime = $startTime.AddDays(7)
$sasToken = New-AzStorageAccountSASToken -Permission acdlpruw -StartTime $startTime -ExpiryTime $endTime -Context $context -Protocol HttpsOrHttp -ResourceType Container,Object -Service Blob,Queue,Table
$sasUrl = "$containerUri$sasToken"

$settings=(Get-AzWebApp -Name '$webApp' -ResourceGroupName $resourceGroup).SiteConfig.AppSettings

$newsettings = @{ }
$settings | ForEach-Object { $newsettings[$_.Name] = $_.Value }

$newsettings["WEBSITE_DAAS_STORAGE_SASURI"] = $sasUrl

Set-AzWebApp -AppSettings $newsettings -Name '$webApp' -ResourceGroupName $resourceGroup 

You can provide webApp, resourceGroup and storageAccount via a library or variable group. The container name should remain the same, however, as the CPU monitoring will create and use this container for memory dumps.

Line 6 gets a storage account access key. We get a storage context on line 7 which we use to get the container URI and the SAS token on 8 and 11.

The token requires a lifetime it's valid for. If you often deploy, you can set this to be short-lived.

Line 12 combines the storage URI and the SAS token to give use the complete URL.

The next part shows how to update the web app configuration setting with this URL. Annoyingly, there doesn't seem to be a way to just add a new setting to the web app. You have to collect the existing settings first, make your change and push the whole thing back up. An additional annoyance is that the AppSettings returns an IList<NameValuePair> but Set-AzWebApp requires a hashtable. This means that you need line 16-19 to loop over the existing settings, add that to a new hashtable and THEN add or set a new setting.

This code comes from Puneet's post above.

$subscriptionId = "Your_Subscription_Id"    # Your App's SubscriptionId
$webapp = "App Name"                        # Your App's Name
$rg = "Resource Group"                      # Your App's Resource Group

$path =  "/subscriptions/$subscriptionId/resourceGroups/$rg/providers/Microsoft.Web/sites/$webapp/extensions/daas/api/cpumonitoring?api-Version=2015-08-01"
$monitoringSettings = @{
    #Configure Action - An action that you want to take when the above condition is met
    Mode="CollectAndKill";

    #Monitor Frequency - This is how frequently the rule will be evaluated
    MonitorDuration=15;

    #Threshold Seconds - For the rule to trigger, CPU should exceed % for this many seconds
    ThresholdSeconds=30;

    #CPU Threshold% - This is the CPU threshold at which the rule will be triggered
    CpuThreshold=75;

    #Monitor Web job processes
    MonitorScmProcesses=$true;

    #Maximum Actions - Maximum number of memory dumps to be collected by this rule
    MaxActions=2;

    #Maximum Duration - Rule will be deactivated after this duration even if no data is collected
    MaximumNumberOfHours=336;
}

$payload = $monitoringSettings | ConvertTo-Json
Invoke-AzRestMethod -Path $path -Method "POST" -Payload $payload

Here's what this looks like in the Azure portal.

portal settings
Proactive CPU Monitoring settings in the Azure Portal

Obviously, these settings need to be adjusted for your particular requirements.

It's odd to me that Azure does not provide this as part of the ARM templates.

There was basically no documentation on these either.

I hope that helps you in your Azure journey. Thanks again to Puneet for pointing me in the right direction.

azureazure devopsProactive CPU monitoringWEBSITE_DAAS_STORAGE_SASURI

Remember to share this post!

X LinkedIn

Jonathan Peterson

Fifteen years of web development experience on the Microsoft tech stack creating both internal enterprise applications and public-facing websites.