Enable Application Insights on Azure Web App with Powershell
So its been a busy couple of months… A couple of weeks ago i ran into an interesting problem. I have a group of Azure web apps that require some monitoring to be configured and for various reasons I was not able to achieve this though the ARM template. This setup is however possible to be solved though ARM templates (ill leave some references to this below) however this was not an option in my case.
The requirement was that I need to have 10 Azure Web Apps in a resource group send their telemetry data to an Application Insights instance in the same resource group. Below I will go through the process I followed to get there and will supply the script I wrote to perform this action.
I set about to find a solution to this problem and thought to myself, surely there must be a powershell cmdlet out there that can be used to perform this task. After searching for this illusive cmdlet for a few hours I gave up. I did however found enough information to spark some ideas on how this problem could be solved. So there are 3 parts to getting this working.
Enabling the application insights on the web app through the portal does this in the back ground for you.
- Applications insights extension need to be enable
- App settings need to be updated with some settings that configures your web app to send its telemetry data to Application Insights.
- Restart the web app.
Enable the extension
I found that this extension is also accessible through the kudu portal of the web app but can also be enabled by the following powerhell.
$resourceName = "<name of web app resource>"
$resourceNameString = $resourceName + "/Microsoft.ApplicationInsights.AzureWebSites"
New-AzResource -ResourceType "Microsoft.Web/sites/siteextensions" -ResourceGroupName $resourceGroupName -Name $resourceNameString -ApiVersion "2018-02-01" -Force -ErrorAction Stop
Set app settings
This is a bit harder to figure out. Because of the some specifics with your web app and options of your environment you might need to taylor this to your situation. I followed the following process to determine my settings.
- Create a new Web App in Azure portal.
- Ensure that the app settings are empty
- Enable the Application Insights Extension in Portal and setup the settings.
- Get the app settings.
- Use these app settings when configuring your app settings through powerhell.
- Delete this webapp.
The web app I was targeting already has some app settings configured through the pipeline that deploy’s it so i needed a way to amend the app settings rather than replace it. So the following code will achieve that.
#Get instrumentation key from ENV application insights resource
$appInsightsInstrumentationKey = (Get-AzApplicationInsights -Name $appinsightsResource -ResourceGroupName $resourceGroupName).InstrumentationKey
#Set the appseting to send telemetry to common applicaiton insights.
$webAppSettings = $webApp.SiteConfig.AppSettings
$hash = @{ }
Write-Host "Clearing hash table" -ForegroundColor Green
foreach ($setting in $webAppSettings) {
$hash[$setting.Name] = $setting.Value
}
$hash['APPINSIGHTS_INSTRUMENTATIONKEY'] = "$($appInsightsInstrumentationKey)" #its important to include the syntax around the variable eg. "$($var)"" if not supplied like this it will change the hash table's object type.$hash['ApplicationInsightsAgent_EXTENSION_VERSION'] = "~2"$hash['XDT_MicrosoftApplicationInsights_Mode'] = "recommended"$hash['APPINSIGHTS_PROFILERFEATURE_VERSION'] = "1.0.0"$hash['DiagnosticServices_EXTENSION_VERSION'] = "~3"$hash['APPINSIGHTS_SNAPSHOTFEATURE_VERSION'] = "1.0.0"$hash['SnapshotDebugger_EXTENSION_VERSION'] = "disabled"$hash['InstrumentationEngine_EXTENSION_VERSION'] = "disabled"$hash['XDT_MicrosoftApplicationInsights_BaseExtensions'] = "disabled"
#Write back app settings into web app
Write-Host "Writing back updated appsettings to app service" $resourceName -ForegroundColor Green
Set-AzWebApp -AppSettings $hash -Name $resourceName -ResourceGroupName $resourceGroupName -verbose
Restart the web app
And then the only thing that remains is to restart the web app. This code does exactly that.
Restart-AzWebApp -ResourceGroupName $resourceGroupName -Name $resourceName
With all the functional bits done and working I needed to get a way to perform this to 10 web apps in the shortest amount possible I introduced some Start-Jobs cmdlets in combination with a for each statement, and some outputs for debugging and the result….
https://github.com/Dries-Venter/PowershellScripts/blob/master/configureAppInsightsParallelJob.ps1
<#
.SYNOPSIS
Configures App services in ENV resource group to send telemitry to the Application Insights instance in the ENV RG
.DESCRIPTION
The script retrieves the ENV app insights instrumentation key from the ENV application instance and then add app settings to all the
app service instances in the ENV (application environment) resource group.
I have included Start-Job to allow for jobs to be executed in paralel if you have more than one webapp in the resourcegroup
I have included a section with logic to check that jobs completed before main scripts closes down. And also a debug section to
receive the completed job and dump a output log that can be used for troubleshooting. The debug section and the "check jobs status"
sections can be commemnted out.
.INPUTS
$(custom_resourceGroupName) Pipeline variable for resource group of ENV
.OUTPUTS
Writes updated app settings to app service instances
.NOTES
Script assumes that there are at least one ipplication insights resource and one webapp or function app in the specified
resource group.
Because of our specific nameing convention it will calculate the names of the application insights based on the resource group name. if this is not
disired then you can include another parameter to feed it the name if the application insight resource
.EXAMPLE
.\configureAppInsights.ps1 -envResourceGroupName <insert resource group name that you are targeting>
.AUTHOR
Dries Vemter
#>
#---------------------------------------------------------[Initialisations]--------------------------------------------------------
#region parameters
[CmdletBinding()]
param (
$envResourceGroupName
)
#regionend parameters
$ErrorActionPreference = "Stop"
#----------------------------------------------------------[Declarations]----------------------------------------------------------
#region variables
$resourceGroupName = $envResourceGroupName
$webAppNames = (Get-AzWebApp -ResourceGroupName $resourceGroupName).Name
$appinsightsResource = ($resourceGroupName.Replace("-", "")).ToLower()
$MaximumWaitMinutes = 10
$DelayBetweenCheckSeconds = 10
#endregion variables
#-----------------------------------------------------------[Functions]------------------------------------------------------------
#region Functions
#endregion Functions
#-----------------------------------------------------------[Execution]------------------------------------------------------------
#region script main
#Get instrumentation key from ENV application insights resource
$appInsightsInstrumentationKey = (Get-AzApplicationInsights -Name $appinsightsResource -ResourceGroupName $resourceGroupName).InstrumentationKey
#enumirate the app service instances within the specified resource group then amend the exisiting app setting with the additional settings below.
#Script Block to allow for parallel jobs to be executed.
$setWebAppConfig = {
param (
[string] $resourceGroupName,
[string] $webAppName,
[string] $appInsightsInstrumentationKey
)
try {
#Local Vars$resourceName = "$webAppName"$resourceNameString = $resourceName + "/Microsoft.ApplicationInsights.AzureWebSites"#Get the web app object$webApp = Get-AzwebApp -ResourceGroupName $resourceGroupName -Name $webAppName
Write-host "Targeting Web APP: " $webApp.Name
#Set the appseting to send telemetry to common applicaiton insights.$webAppSettings = $webApp.SiteConfig.AppSettings
$hash = @{ }
Write-Host "Clearing hash table" -ForegroundColor Green
foreach ($setting in $webAppSettings) {
$hash[$setting.Name] = $setting.Value
}
$hash['APPINSIGHTS_INSTRUMENTATIONKEY'] = "$appInsightsInstrumentationKey" #its important to include the syntax around the variable eg. "$($var)"" if not supplied like this it will change the hash table's object type.$hash['ApplicationInsightsAgent_EXTENSION_VERSION'] = "~2"$hash['XDT_MicrosoftApplicationInsights_Mode'] = "recommended"$hash['APPINSIGHTS_PROFILERFEATURE_VERSION'] = "1.0.0"$hash['DiagnosticServices_EXTENSION_VERSION'] = "~3"$hash['APPINSIGHTS_SNAPSHOTFEATURE_VERSION'] = "1.0.0"$hash['SnapshotDebugger_EXTENSION_VERSION'] = "disabled"$hash['InstrumentationEngine_EXTENSION_VERSION'] = "disabled"$hash['XDT_MicrosoftApplicationInsights_BaseExtensions'] = "disabled"#Write back app settings into web app
Write-Host "Writing back updated appsettings to app service" $resourceName -ForegroundColor Green
Set-AzWebApp -AppSettings $hash -Name $resourceName -ResourceGroupName $resourceGroupName -verbose -ErrorAction stop
#Enable Application insight extention$resourceName = "$webAppName"$resourceNameString = $resourceName + "/Microsoft.ApplicationInsights.AzureWebSites"
Write-host "Enabling Application Insights Extension on" $resourceName -ForegroundColor DarkYellow
Write-host "'$resourceNameString'" #debug
Write-host "'$resourceGroupName'" #debug
New-AzResource -ResourceType "Microsoft.Web/sites/siteextensions" -ResourceGroupName $resourceGroupName -Name $resourceNameString -ApiVersion "2018-02-01" -Force -ErrorAction Stop
Write-host "Completed enabling app insights extention" \
#Restart Web App
Write-host "Restarting WebApp" -ForegroundColor Green
Write-Host $resourceName -ForegroundColor Green
Restart-AzWebApp -ResourceGroupName $resourceGroupName -Name $resourceName
}
catch {
Write-Host "Configuration did not complete on " $resourceName$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-host $ErrorMessage
Write-host $FailedItem
}
}
#Initiating parallel run
ForEach ($webAppName in $webAppNames) {
Start-Job -ScriptBlock $setWebAppConfig -ArgumentList $resourceGroupName, $webAppName, $appInsightsInstrumentationKey
}
#logic to check that jobs completed before main scripts closes down.
$Timeout = new-timespan -Minutes $MaximumWaitMinutes
$Stopwatch = [diagnostics.stopwatch]::StartNew()
Write-Host "Waiting for all jobs to complete - ($($DelayBetweenCheckSeconds) second(s) check / $($MaximumWaitMinutes) minute(s) max wait)";
while ($Stopwatch.elapsed -lt $Timeout) {
# Get job status$Status = Get-Job | Where-object { $_.State -eq "Running" }
$status$status.count #to be used for debugging
Write-host "Waiting for app services configuration to complete"
# break if all completedif ($status.count -eq 0) { break }
#if (!($Status)) { break; }# Wait until next check
Start-Sleep -seconds $DelayBetweenCheckSeconds
}
#debug step (not required for normal running but helps you see what is going on inside the job)
Write-host "About to get status of Jobs" -ForegroundColor green
$jobs = Get-Job
foreach ($job in $jobs) {
Receive-job -id $job.id
}
Write-host "Done"
#endregion script main
I was struggling with getting it working in the pipeline but manage to get it doing its thing by adjusting the timeouts on the jobs. Should all be working now. Let me know what you think.
Resources
My Blog
https://driesventer.com/?p=141
The Script:
https://github.com/Dries-Venter/PowershellScripts/blob/master/configureAppInsightsParallelJob.ps1
Microsoft Docs:
https://docs.microsoft.com/en-us/azure/azure-monitor/app/powershell-azure-diagnostics
Great find Dries V.
This is cool Dries! Nice work mate
Nice Dries!