Files
Cloud-20Engineering/Powershell/Lists/Azure/AppInsightsWorkspace.ps1
Jurjen Ladenius a226ca97ac added documetation
2025-11-03 08:12:01 +01:00

288 lines
14 KiB
PowerShell

<#
.SYNOPSIS
Exports detailed information about Azure Application Insights resources across all enabled subscriptions.
.DESCRIPTION
This script analyzes all Application Insights resources across enabled Azure subscriptions and
collects comprehensive information including:
- Basic resource metadata (ID, name, resource group, subscription)
- Log Analytics workspace associations
- Resource tags for governance and organization
The script is particularly useful for:
- Application Insights inventory and governance
- Monitoring workspace associations for centralized logging
- Tag compliance auditing
- Cost management and resource organization
.PARAMETER SubscriptionFilter
Optional array of subscription IDs to analyze. If not specified, all enabled subscriptions are processed.
.PARAMETER OutputPath
Custom path for the output CSV file. If not specified, creates a timestamped file in the current directory.
.EXAMPLE
.\AppInsightsWorkspace.ps1
Analyzes all Application Insights resources across all enabled subscriptions.
.EXAMPLE
.\AppInsightsWorkspace.ps1 -SubscriptionFilter @("12345678-1234-1234-1234-123456789012", "87654321-4321-4321-4321-210987654321")
Analyzes Application Insights resources in specific subscriptions only.
.EXAMPLE
.\AppInsightsWorkspace.ps1 -OutputPath "C:\Reports\appinsights-analysis.csv"
Analyzes all Application Insights resources and saves to a custom location.
.OUTPUTS
Creates a CSV file with the following columns:
- SubscriptionId: Azure subscription unique identifier
- SubscriptionName: Azure subscription display name
- Id: Application Insights resource ID
- ResourceGroupName: Resource group containing the Application Insights resource
- Name: Application Insights resource name
- WorkspaceResourceId: Associated Log Analytics workspace resource ID (if any)
- Tag_Team: Value of 'team' tag
- Tag_Product: Value of 'product' tag
- Tag_Environment: Value of 'environment' tag
- Tag_Data: Value of 'data' tag
- Tag_CreatedOnDate: Value of 'CreatedOnDate' tag
- Tag_Deployment: Value of 'drp_deployment' tag
Also displays a formatted table of results in the console.
.NOTES
Author: Cloud Engineering Team
Created: 2025
Requires: PowerShell 5.1 or later, Az PowerShell module
Dependencies: Az.ApplicationInsights, Az.Accounts, Az.Resources modules
Prerequisites:
- Install Az PowerShell module: Install-Module -Name Az
- Connect to Azure: Connect-AzAccount
- Appropriate permissions to read Application Insights resources across target subscriptions
Performance Considerations:
- Processing time depends on the number of subscriptions and Application Insights resources
- The script switches contexts between subscriptions, which may take time with many subscriptions
- Large numbers of resources may result in longer execution times
Tag Analysis:
The script looks for specific tags commonly used for governance:
- team: Identifies the responsible team
- product: Associates the resource with a product or service
- environment: Indicates the environment (dev, test, prod, etc.)
- data: Data classification or sensitivity level
- CreatedOnDate: Resource creation timestamp
- drp_deployment: Deployment-related information
Workspace Association:
- Modern Application Insights resources should be associated with Log Analytics workspaces
- Resources without workspace associations may be using legacy standalone mode
- Workspace associations enable advanced querying and cross-resource analytics
.LINK
https://docs.microsoft.com/en-us/powershell/module/az.applicationinsights/
https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview
#>
param(
[Parameter(Mandatory = $false, HelpMessage = "Array of subscription IDs to analyze (analyzes all enabled subscriptions if not specified)")]
[string[]]$SubscriptionFilter = @(),
[Parameter(Mandatory = $false, HelpMessage = "Custom path for the output CSV file")]
[string]$OutputPath = ""
)
# Check Azure PowerShell authentication
Write-Host "Verifying Azure PowerShell authentication..." -ForegroundColor Yellow
try {
$azContext = Get-AzContext
if (-not $azContext) {
Write-Host "Not authenticated to Azure. Attempting to connect..." -ForegroundColor Yellow
Connect-AzAccount
$azContext = Get-AzContext
}
Write-Host "Azure authentication verified - Account: $($azContext.Account.Id)" -ForegroundColor Green
}
catch {
Write-Host "ERROR: Unable to authenticate to Azure. Please run 'Connect-AzAccount' manually." -ForegroundColor Red
exit 1
}
# Generate filename if not provided
if (-not $OutputPath) {
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
$OutputPath = ".\$date appinsights.csv"
}
# Get target subscriptions based on filter or all enabled subscriptions
Write-Host "Retrieving target subscriptions..." -ForegroundColor Yellow
if ($SubscriptionFilter.Count -gt 0) {
$subscriptions = $SubscriptionFilter | ForEach-Object {
Get-AzSubscription -SubscriptionId $_ | Where-Object State -eq "Enabled"
} | Where-Object { $_ -ne $null }
Write-Host "Analyzing $($subscriptions.Count) filtered subscriptions" -ForegroundColor Green
} else {
$subscriptions = Get-AzSubscription | Where-Object State -eq "Enabled"
Write-Host "Analyzing all $($subscriptions.Count) enabled subscriptions" -ForegroundColor Green
}
# Define a class to structure Application Insights resource information
class AppInsightsCheck {
[string] $SubscriptionId = "" # Azure subscription unique identifier
[string] $SubscriptionName = "" # Azure subscription display name
[string] $Id = "" # Application Insights resource ID
[string] $ResourceGroupName = "" # Resource group containing the resource
[string] $Name = "" # Application Insights resource name
[string] $WorkspaceResourceId = "" # Associated Log Analytics workspace resource ID
[string] $Tag_Team = "" # Team responsible for the resource
[string] $Tag_Product = "" # Product or service association
[string] $Tag_Environment = "" # Environment designation (dev, test, prod)
[string] $Tag_Data = "" # Data classification or sensitivity level
[string] $Tag_CreatedOnDate = "" # Resource creation date from tags
[string] $Tag_Deployment = "" # Deployment-related information
}
# Initialize array to store Application Insights analysis results
[AppInsightsCheck[]]$Result = @()
$totalResourcesProcessed = 0
# Display analysis banner
Write-Host "`n========================================================================================================================================================================"
Write-Host "AZURE APPLICATION INSIGHTS ANALYSIS"
Write-Host "========================================================================================================================================================================"
# Process each subscription to analyze Application Insights resources
foreach ($subscription in $subscriptions) {
Write-Host "`nAnalyzing subscription: $($subscription.Name) ($($subscription.Id))" -ForegroundColor Cyan
try {
# Switch to the current subscription context
Set-AzContext -SubscriptionId $subscription.Id -ErrorAction Stop | Out-Null
# Get all Application Insights resources in the subscription
Write-Host " Retrieving Application Insights resources..." -ForegroundColor Gray
$allAppinsights = Get-AzApplicationInsights -ErrorAction Stop
if ($allAppinsights.Count -eq 0) {
Write-Host " No Application Insights resources found" -ForegroundColor Yellow
continue
}
Write-Host " Found $($allAppinsights.Count) Application Insights resources" -ForegroundColor Green
# Process each Application Insights resource
foreach ($appinsights in $allAppinsights) {
Write-Host " Processing: $($appinsights.Name)" -ForegroundColor Gray
try {
# Create new analysis object and populate basic information
[AppInsightsCheck] $AppInsightsCheck = [AppInsightsCheck]::new()
$AppInsightsCheck.SubscriptionId = $subscription.Id
$AppInsightsCheck.SubscriptionName = $subscription.Name
$AppInsightsCheck.Id = $appinsights.Id
$AppInsightsCheck.Name = $appinsights.Name
$AppInsightsCheck.ResourceGroupName = $appinsights.ResourceGroupName
$AppInsightsCheck.WorkspaceResourceId = $appinsights.WorkspaceResourceId
# Check workspace association
if ($appinsights.WorkspaceResourceId) {
Write-Host " Workspace-based Application Insights" -ForegroundColor Green
} else {
Write-Host " Legacy standalone Application Insights (consider migrating)" -ForegroundColor Yellow
}
# Retrieve detailed resource information for tags
Write-Host " Retrieving resource tags..." -ForegroundColor Gray
$resource = Get-AzResource -ResourceId $appinsights.Id -ErrorAction Stop
# Extract governance tags
$AppInsightsCheck.Tag_Team = $resource.Tags.team
$AppInsightsCheck.Tag_Product = $resource.Tags.product
$AppInsightsCheck.Tag_Environment = $resource.Tags.environment
$AppInsightsCheck.Tag_Data = $resource.Tags.data
$AppInsightsCheck.Tag_CreatedOnDate = $resource.Tags.CreatedOnDate
$AppInsightsCheck.Tag_Deployment = $resource.Tags.drp_deployment
# Report on tag compliance
$tagCount = @($AppInsightsCheck.Tag_Team, $AppInsightsCheck.Tag_Product, $AppInsightsCheck.Tag_Environment) | Where-Object { $_ } | Measure-Object | Select-Object -ExpandProperty Count
if ($tagCount -eq 3) {
Write-Host " All required tags present" -ForegroundColor Green
} else {
Write-Host " Missing required tags (team, product, environment)" -ForegroundColor Yellow
}
# Add to results
$Result += $AppInsightsCheck
$totalResourcesProcessed++
} catch {
Write-Host " ERROR processing resource: $($_.Exception.Message)" -ForegroundColor Red
# Still add basic info even if tag retrieval fails
[AppInsightsCheck] $AppInsightsCheck = [AppInsightsCheck]::new()
$AppInsightsCheck.SubscriptionId = $subscription.Id
$AppInsightsCheck.SubscriptionName = $subscription.Name
$AppInsightsCheck.Id = $appinsights.Id
$AppInsightsCheck.Name = $appinsights.Name
$AppInsightsCheck.ResourceGroupName = $appinsights.ResourceGroupName
$AppInsightsCheck.WorkspaceResourceId = $appinsights.WorkspaceResourceId
$Result += $AppInsightsCheck
$totalResourcesProcessed++
}
}
} catch {
Write-Host " ERROR accessing subscription: $($_.Exception.Message)" -ForegroundColor Red
continue
}
}
# Export results to CSV file
Write-Host "`nExporting results to: $OutputPath" -ForegroundColor Yellow
$Result | Export-Csv -Path $OutputPath -NoTypeInformation -Force
# Calculate and display summary statistics
$totalSubscriptions = $subscriptions.Count
$workspaceBasedCount = ($Result | Where-Object { $_.WorkspaceResourceId -ne "" }).Count
$legacyCount = ($Result | Where-Object { $_.WorkspaceResourceId -eq "" }).Count
$taggedResourcesCount = ($Result | Where-Object { $_.Tag_Team -ne "" -and $_.Tag_Product -ne "" -and $_.Tag_Environment -ne "" }).Count
# Display completion summary
Write-Host "`n========================================================================================================================================================================"
Write-Host "APPLICATION INSIGHTS ANALYSIS COMPLETED SUCCESSFULLY!" -ForegroundColor Green
Write-Host "========================================================================================================================================================================"
Write-Host ""
Write-Host "SUMMARY STATISTICS:" -ForegroundColor Cyan
Write-Host "Subscriptions analyzed: $totalSubscriptions" -ForegroundColor Yellow
Write-Host "Total Application Insights resources: $totalResourcesProcessed" -ForegroundColor Yellow
Write-Host "Workspace-based resources: $workspaceBasedCount" -ForegroundColor Yellow
Write-Host "Legacy standalone resources: $legacyCount" -ForegroundColor Yellow
Write-Host "Resources with complete tags (team, product, environment): $taggedResourcesCount" -ForegroundColor Yellow
# Highlight areas needing attention
if ($legacyCount -gt 0) {
Write-Host ""
Write-Host "RECOMMENDATIONS:" -ForegroundColor Cyan
Write-Host "- $legacyCount legacy Application Insights resources should be migrated to workspace-based mode" -ForegroundColor Yellow
}
if ($taggedResourcesCount -lt $totalResourcesProcessed) {
$untaggedCount = $totalResourcesProcessed - $taggedResourcesCount
Write-Host "- $untaggedCount resources are missing required governance tags" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Output file: $OutputPath" -ForegroundColor Yellow
# Display results table
Write-Host ""
Write-Host "DETAILED RESULTS:" -ForegroundColor Cyan
$Result | Format-Table -Property SubscriptionName, Name, ResourceGroupName, @{
Name = 'WorkspaceAssociated'
Expression = { if ($_.WorkspaceResourceId) { 'Yes' } else { 'No' } }
}, Tag_Team, Tag_Product, Tag_Environment -AutoSize
Write-Host "========================================================================================================================================================================"