One of the many things an Azure Monitor Alert can do is trigger Azure Functions. As I mentioned in my alerting post, every alert contains an underlying schema. I will once again be using the Common Alert Schema for Azure Monitor, however, this will still work with the old schema. You’ll need an alert if you want to follow along. I have made a repo here, where you can download real world alerts. Or you can read my previous post where I showed how you can extract them with Logic Apps.
Another prereq. I’ll be using the new Powershell Core Azure Functions. Which are no longer experimental and are officially supported, albeit still in preview. You can read more about them here. https://azure.microsoft.com/en-us/blog/serverless-automation-using-powershell-preview-in-azure-functions/
That said some of my favorite new features:
- Az PowerShell Modules
- Az modules and any Module you add from PSGallery will be updated automatically
- Using Managed Identity you can authenticate to Azure services
I will be skipping creating the Azure Function because its really very easy to do and there are plenty of other posts out there detailing how to do it. My Azure Function will have two functions in it, LogSearch and MetricAlert. I’ve also put it on Github here.
Azure Monitor Action Group
To trigger any type of alert with Azure Monitor, whether its an Azure Function or an email, you need an Action Group.
Under Azure Monitor select Alerts -> Manage Actions -> Add Action Group
Give your Action Group an Name, Short Name, select your Subscription and Resource Group. Then give it an Action Name and select Azure Function. Note the Resource Group here is where the Action Group will be stored.
On the right hand blade, the resource group is the resource group location of your Azure Function. Notice that the creation process has detected that I have 2 functions. MetricAlert and LogSearch. Click ok and save your Action Group. Make Sure “Use Common Alert Schema” is checked. Again this will work fine with the other schema, however my examples are using the Common Alert Schema.
Add to Alert
Under Azure Monitor, select Manage Alerts -> Your alert
Select “Select Action Group” then select your Action Group we created from the previous step.
Now for the fun part.
Log Search Alert with Azure Function
So armed with the Alert JSON Payload, you can copy it into the request body and hit run and the function will process your alert.
using namespace System.Net # Input bindings are passed in via param block. param($Request, $TriggerMetadata) # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." $alert = $request.body #extract Affected cI $affectedCI = $alert.body.data.alertContext.AffectedConfigurationItems write-host "Affected CI" $affectedCI #Extract projected fields from Log Search Alert $computer = $alert.body.data.alertContext.SearchResults.tables.rows $svcname = $alert.body.data.alertContext.SearchResults.tables.rows $svcstate = $alert.body.data.alertContext.SearchResults.tables.rows $svcdisplayname = $alert.body.data.alertContext.SearchResults.tables.rows $TimeGenerated = $alert.body.data.alertContext.SearchResults.tables.rows write-host "Computer" $computer "svc name" $svcname "svcstate" $svcstate "svc displayname" $svcdisplayname "TimeGenerated" $timegenerated
Metric Alert with Azure Function
using namespace System.Net # Input bindings are passed in via param block. param($Request, $TriggerMetadata) # Write to the Azure Functions log stream. Write-Host "PowerShell HTTP trigger function processed a request." # Interact with query parameters or the body of the request. $alert = $request.body # get alert rull, severity and time $alertrule = $alert.body.data.essentials.alertRule $severity = $alert.body.data.essentials.severity $firedDateTime = $alert.body.data.essentials.firedDateTime #get metric type and value $metric = $alert.body.data.alertContext.condition.allOf.metricName $metricValue = $alert.body.data.alertContext.condition.allOf.metricValue #get affected CI $affectedCI = $alert.body.data.alertContext.condition.allOf.dimensions.value write-host "Rule" $alertRule "Severity" $severity "Time" $fireddateTime "metric" $metric "value" $metricvalue "Affected CI" $affectedCI
Interestingly $request comes in with JSON already converted to a PowerShell object. So you don’t need to use ConvertFrom-Json like you do in Azure Automation runbooks. Secondly, you can easily parse the tables and rows for Log Search alerts or dimensions of metric alerts by referencing the array position for instance  is the first value and  is the second and so on.
One of the other keys to processing the alert data in PowerShell Core is that reading the alert data, the properties are case sensitive. This took me longer than I would like to admit to figure out. However, I’m pretty used to Windows Powershell where very few things in my experience are case sensitive.
will send you a null value, but
will correctly bring you back data.
Keep that in mind when working with your own alerts and if you are trying to grab any fields I haven’t included.
From here you can process the alert in the same function or you could send the data to a new function for remediation. The possibilities are vast. If you missed it above, the github link is here https://github.com/scautomation/AzureMontior-Alert-AzureFunctions