Skip to content

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Get-Availability

CI Release

Get-Availability reports month-scoped availability for Azure Virtual Machines, Azure SQL Databases, Azure Storage Accounts, and Azure Web Apps across one or more Azure subscriptions.

It runs either as a standalone PowerShell 7.6 script or as a timer-triggered Azure Function. Log Analytics ingestion is optional.

For each resource, the tool reports:

  • suspect minutes
  • confirmed platform faults
  • excused minutes
  • unresolved minutes
  • availability percentage

The relationship Suspect = Faults + Excused + Unresolved always holds.

Run the script

Prerequisites

Requirement Detail
PowerShell 7.6 or later (pwsh)
Az.Accounts Install-Module Az.Accounts
Az.ResourceGraph Install-Module Az.ResourceGraph
Azure sign-in Connect-AzAccount

Key parameters

Parameter Default Purpose
-Subscriptions required Azure subscription display names to inspect
-Month required Observation month in UTC, format YYYYMM
-Kinds vm,sql,storage,webapp Resource kinds to include
-Resource all Limit the run to one resource
-Parallelism auto Max concurrent API calls
-ActivityGraceMinutes 10 Grace window after lifecycle events
-Batch off Use the Metrics Batch API
-BatchSize 10 Batch size when -Batch is enabled
-SourceWorkspaceId none Source Log Analytics workspace for bulk Activity Log and older Resource Health history
-DceEndpoint none Data Collection Endpoint for ingestion
-DcrImmutableId none Data Collection Rule immutable ID for ingestion
-Version off Print version and exit

The observation window is a UTC calendar month. Past months use the full month; the current month is month-to-date. Metric and Activity Log collection support a 90-day lookback. Resource Health REST history is shorter, so -SourceWorkspaceId is the way to extend coverage beyond the last ~30 days.

Examples

# Single subscription
./Functions/GetAvail/get-availability.ps1 -Subscriptions 'Contoso-Production' -Month 202603

# Multiple subscriptions, filtered by kind
./Functions/GetAvail/get-availability.ps1 -Subscriptions 'Contoso-Development','Contoso-Production' -Month 202603 -Kinds vm,sql

# Single resource with a custom grace window
./Functions/GetAvail/get-availability.ps1 -Subscriptions 'Contoso-Development' -Month 202603 -Resource myvm02 -ActivityGraceMinutes 15

# Use Log Analytics as the source for Activity Log and older Resource Health history
./Functions/GetAvail/get-availability.ps1 -Subscriptions 'Contoso-Production' -Month 202603 -SourceWorkspaceId 'b233a4b7-3c43-433c-ac60-1f6ff217ddd4'

# Send results to Log Analytics custom tables
./Functions/GetAvail/get-availability.ps1 -Subscriptions 'Contoso-Production' -Month 202603 `
  -DceEndpoint 'https://dce-getavail-itn-001.italynorth-1.ingest.monitor.azure.com' `
  -DcrImmutableId 'dcr-00000000000000000000000000000000'

Output

The console output includes the observation window, any Resource Health coverage warning, a per-resource table, and aggregated summaries. The PowerShell version also emits objects to the pipeline so you can export to CSV or JSON.

Resources with zero eligible minutes are shown as N/A.

Classification model

  1. Resource inventory comes from Azure Resource Graph.
  2. Azure Monitor metrics are collected at one-minute granularity.
  3. Suspect minutes are classified using Activity Log lifecycle events, Resource Health, and metric fallback rules.
  4. Final availability is computed from eligible minutes and available minutes.

Metric sources by resource type:

Resource type Metrics
Virtual Machine VmAvailabilityMetric
Azure SQL Database Availability
Storage Account Availability, Transactions
Web App MemoryWorkingSet

Classification precedence is strict:

  1. Platform faults from Resource Health remain eligible downtime.
  2. Matching lifecycle events are excused.
  3. Resource Health Unknown or customer-initiated periods are excused.
  4. Remaining nulls are treated as metric issues and excused.
  5. Remaining zero or degraded values count against availability.

When -SourceWorkspaceId is set, Activity Log data and older Resource Health transitions are queried from Log Analytics in bulk, while the most recent Resource Health interval still comes from the REST API and remains authoritative.

Log Analytics ingestion

When -DceEndpoint and -DcrImmutableId are both supplied, the script sends results through the Azure Monitor Ingestion API into:

Table Content
GetAvailResources_CL Per-resource results
GetAvailSummary_CL Aggregated summaries

Payloads are gzip-compressed and batched to stay within ingestion limits.

Deploy to Azure

The Bicep template in Bicep/ deploys the complete Azure-hosted stack:

  • Log Analytics workspace and custom tables
  • Data Collection Endpoint and Data Collection Rule
  • Storage account
  • Flex Consumption Function App
  • Application Insights
  • RBAC assignments for ingestion and storage access
  • Optional private endpoints for the storage account and Function App

The Function App settings are auto-wired from the deployed resources, so after infrastructure deployment and func publish no manual app-setting step is required.

Networking modes

The template now supports two network modes controlled by usePrivateEndpoints:

usePrivateEndpoints Behavior
true Preserves the current deployment model: creates storage and Function App private endpoints, uses the private endpoint subnet and shared private DNS zones, and keeps public access disabled on those resources
false Skips private endpoints and DNS zone references, and keeps the storage account and Function App publicly reachable

Deployment prerequisites

  • Azure CLI with Bicep support
  • Contributor on the target resource group
  • A subnet delegated to Microsoft.App/environments for fnSubnetId
  • If usePrivateEndpoints = true: a private endpoint subnet and existing private DNS zones for blob storage and Azure Websites

Parameters

See Bicep/parameters.dev.bicepparam for a commented example. The main parameters are:

Parameter Purpose
logAnalyticsWorkspaceName Log Analytics workspace name
dataCollectionEndpointName Data Collection Endpoint name
dataCollectionRuleName Data Collection Rule name
storageAccountName Storage account for the Function App
functionAppName Function App name
applicationInsightsName Application Insights instance
usePrivateEndpoints Toggle between private networking and public reachability
fnSubnetId Delegated subnet for Function App VNet integration
peSubnetId Private endpoint subnet when private endpoints are enabled
dnsZonesSubscriptionId Subscription containing shared private DNS zones
dnsZonesResourceGroupName Resource group containing shared private DNS zones
getavailSubscriptions Comma-separated subscriptions to monitor
getavailKinds Resource kinds to monitor
getavailBatch Use regional Metrics Batch API requests (default: true)
getavailBatchSize Maximum resources per batch request (default: 10)
sourceWorkspaceId Optional source workspace for Activity Log and Resource Health history
timerSchedule CRON expression for the timer trigger

Deploy the infrastructure

# Create resource group (one time)
az group create --name rg-getavail-itn-001 --location italynorth --tags solution=Get-Availability

# Validate
az deployment group validate --resource-group rg-getavail-itn-001 --parameters Bicep/parameters.dev.bicepparam

# What-if
az deployment group what-if --resource-group rg-getavail-itn-001 --parameters Bicep/parameters.dev.bicepparam

# Deploy
az deployment group create --resource-group rg-getavail-itn-001 --parameters Bicep/parameters.dev.bicepparam

Post-deployment access

The Function App managed identity needs:

  • Reader on each subscription listed in getavailSubscriptions
  • Log Analytics Reader on the sourceWorkspaceId workspace when that feature is used

Example:

$principalId = az functionapp identity show `
  --name fn-getavail-itn-001 `
  --resource-group rg-getavail-itn-001 `
  --query principalId -o tsv

$subscriptions = @('Flaz-Connectivity', 'Flaz-Management', 'Flaz-Identity', 'Flaz-Workloads')
foreach ($sub in $subscriptions) {
  $subId = az account show --subscription $sub --query id -o tsv
  az role assignment create --assignee $principalId --role Reader --scope "/subscriptions/$subId"
}

az role assignment create --assignee $principalId --role 'Log Analytics Reader' `
  --scope '<source-workspace-resource-id>'

Publish the Function App

# Save required modules (one time or when upgrading)
Save-Module -Name Az.Accounts -Path Functions/GetAvail/Modules -Repository PSGallery -Force
Save-Module -Name Az.ResourceGraph -Path Functions/GetAvail/Modules -Repository PSGallery -Force

# Publish
cd Functions/GetAvail
func azure functionapp publish fn-getavail-itn-001 --powershell

About

Month-scoped Azure resource availability reporter (via interactive PowerShell or Azure Function)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages