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.

  1. Applications insights extension need to be enable
  2. App settings need to be updated with some settings that configures your web app to send its telemetry data to Application Insights.
  3. 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.

  1. Create a new Web App in Azure portal.
  2. Ensure that the app settings are empty
  3. Enable the Application Insights Extension in Portal and setup the settings. (See the screenshot in figure 1)
  4. Get the app settings. (See the screenshot in figure 2)
  5. Use these app settings when configuring your app settings through powerhell.
  6. Delete this webapp.
Figure 1
Figure 2

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 completed
    if ($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

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

Dries Venter

Leave a Reply

Your email address will not be published. Required fields are marked *