Use Log Analytics With Azure Automation For Alerts
Description:
After setting up an automation account in Azure, the first thing you want to setup is Azure Monitor alerts so that you can be emailed when runbooks fail. This should be setup before you start moving runbooks to production. Follow this post if your organization is willing to pay for Log Analytics. If not, you can still get alerts on failed runbooks natively (free) following this document, but I don’t know how to set it up to get alerts on errors within the runbook. I believe that if you use throw
keyword in your powershell scripts, they can fail the runbook so that should be all you need.
In this guide, we will be able to get better ideas of alerts because my organization purchased Log Analytics for the Automation Account to forward its logs to so we can alert on failed jobs and failed lines within a job.
To Resolve:
-
From my previous post, make sure you have your automation account sending logs to your Log Analytics workspace:
1 2 3 4 5 6 7 8 9 10
Get-AzResource -ResourceType "Microsoft.OperationalInsights/workspaces" # copy output from previous command $l = '/subscriptions/longpath/log-analytics' Get-AzResource -ResourceType "Microsoft.Automation/automationAccounts" # copy output from previous command $a = '/subscriptions/longpath/automation' Set-AzDiagnosticSetting -ResourceId $a -WorkspaceId $l -Enabled 1 # Verify Get-AzDiagnosticSetting -ResourceId $automationAccountId
-
Setup an alert that will run every 5 minutes and email you once with all errors found within those 5 minutes for Azure Runbooks that have failed:
- Go to Azure Monitor => Alerts => Manage Alert Rules => New Alert Rule
- Resources: Your Log Analytics Workspace
- Condition: Signal => Custom Log Search
- Query:
1 2 3 4 5
AzureDiagnostics | where ResourceProvider == "MICROSOFT.AUTOMATION" and Category == "JobLogs" and (ResultType == "Failed" or ResultType == "Stopped" or ResultType == "Suspended") | project TimeGenerated , RunbookName_s , ResultType , Resource | extend LocalTimestamp = TimeGenerated - 5h | project LocalTimestamp , RunbookName_s , ResultType
- Change the
5h
to whatever time zone you are in, for me it is Central Time - Alert Logic:
Number of results
,greater than
,0
- Evaluation based on: Period in minutes
5
, Frequency in minutes5
- Action Groups: ‘email_automation_team’
- Alert Rule Name:
automation_joblog_failed
-
Setup an alert that will run every 5 minutes and email you once with all errors found within those 5 minutes for errors within Azure Runbooks that have failed:
- Go to Azure Monitor => Alerts => Manage Alert Rules => New Alert Rule
- Resources: Your Log Analytics Workspace
- Condition: Signal => Custom Log Search
- Query:
1 2 3 4 5
AzureDiagnostics | where ResourceProvider == "MICROSOFT.AUTOMATION" and Category == "JobStreams" and StreamType_s == "Error" | project TimeGenerated , RunbookName_s , StreamType_s , Resource , ResultDescription | extend LocalTimestamp = TimeGenerated - 5h | project LocalTimestamp , RunbookName_s , StreamType_s , ResultDescription
- Change the
5h
to whatever time zone you are in, for me it is Central Time - Alert Logic:
Number of results
,greater than
,0
- Evaluation based on: Period in minutes
5
, Frequency in minutes5
- Action Groups: ‘email_automation_team’
- Alert Rule Name:
automation_jobstream_failed
- So those alerts are really all you need if you want an overview of ALL runbooks in your account - they will run every 5 minutes and send you a list of errors.
- To be clear, the reason we created
jobstream
separate fromjoblog
is thatjobstream
will alert for runbooks that complete successfully but still throw errors. In powershell, you can use aTry{}Catch{}
withCatch{}
containing aWrite-Error "blah"
and the runbook will still complete successfully unless you explicitly set$ErrorPreference = "Stop"
.
- To be clear, the reason we created
-
What if you want to alert on error in a specific runbook? Well setup the same structure but put this in the query instead:
- Error specific runbooks, for example
My-Runbook-1
orMy-Runbook-2
:
1 2 3 4 5
AzureDiagnostics | where ResourceProvider == "MICROSOFT.AUTOMATION" and Category == "JobLogs" and (RunbookName_s == "My-Runbook-1" or RunbookName_s == "My-Runbook-2") and (ResultType == "Failed" or ResultType == "Stopped" or ResultType == "Suspended") | project TimeGenerated , RunbookName_s , ResultType , Resource | extend LocalTimestamp = TimeGenerated - 5h | project LocalTimestamp , RunbookName_s , ResultType
- Error specific runbooks, for example
-
What if you want to alert on success in a specific runbook? Well setup the same structure but put this in the query instead:
- Success specific runbooks, for example only
My-Runbook-2
:
1 2 3 4 5
AzureDiagnostics | where ResourceProvider == "MICROSOFT.AUTOMATION" and Category == "JobLogs" and (RunbookName_s == "My-Runbook-2") and (ResultType == "Completed") | project TimeGenerated , RunbookName_s , ResultType , Resource | extend LocalTimestamp = TimeGenerated - 5h | project LocalTimestamp , RunbookName_s , ResultType
- Success specific runbooks, for example only
-
If you don’t want to use this setup (i.e. not pay for Log Analytics), and what I had done initially, is you can just set your scripts to send emails using
Try{}Catch{}
blocks: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
Function Get-EmailAccountUser { $cred = Get-AutomationPSCredential -Name 'Office365 Email User' $val = $cred.UserName return $val } Function Get-EmailAccountPass { $cred = Get-AutomationPSCredential -Name 'Office365 Email User' $val = $cred.GetNetworkCredential().Password return $val } Function Send-Email { [CmdletBinding()] param ( [string]$Subject, [string]$Body, [string]$Username, [string]$Password ) $pw = ConvertTo-SecureString -String $Password -AsPlainText -Force $EmailCred = New-Object System.Management.Automation.PSCredential($userName, $pw) $Params = @{ 'UseSSL' = $True 'From' = 'user@domain.com' 'To' = 'user2@domain.com' 'Cc' = @('user3@domain.com') 'Subject' = $Subject 'BodyAsHTML' = $True 'Body' = $Body 'SmtpServer' = "smtp.office365.com" 'Port' = "587" } [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true } [Net.ServicePointManager]::SecurityProtocol = "Tls12, Tls11, Tls, Ssl3" Send-MailMessage @Params -Credential $EmailCred } # Some stuff in the runbook runs here Try { # generate some error } catch { $emailUser = Get-EmailAccountUser $emailPass = Get-EmailAccountPass $params = @{ Subject = "Runbook Failed: This Runbook Name" Body = "CSV file not created" Username = $emailUser Password = $emailPass } Send-Email @params Write-Error "CSV file not created" Exit 1 }
Comments