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.
| 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 |
| 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.
# 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'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.
- Resource inventory comes from Azure Resource Graph.
- Azure Monitor metrics are collected at one-minute granularity.
- Suspect minutes are classified using Activity Log lifecycle events, Resource Health, and metric fallback rules.
- 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:
- Platform faults from Resource Health remain eligible downtime.
- Matching lifecycle events are excused.
- Resource Health
Unknownor customer-initiated periods are excused. - Remaining nulls are treated as metric issues and excused.
- 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.
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.
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.
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 |
- Azure CLI with Bicep support
- Contributor on the target resource group
- A subnet delegated to
Microsoft.App/environmentsforfnSubnetId - If
usePrivateEndpoints = true: a private endpoint subnet and existing private DNS zones for blob storage and Azure Websites
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 |
# 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.bicepparamThe Function App managed identity needs:
Readeron each subscription listed ingetavailSubscriptionsLog Analytics Readeron thesourceWorkspaceIdworkspace 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>'# 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