How Azure Resource Graph is gonna change the way you search and script

Azure Resource Graph has been announced a while ago (Ignite 2018) and I immediately understood this would be a game changer in terms of querying and data digging for the Azure resources I need to manage.

What is Azure Resource Graph

From the Microsoft documentation:

Azure Resource Graph is a service in Azure that is designed to extend Azure Resource Management by providing efficient and performant resource exploration with the ability to query at scale across all subscriptions and management groups so that you can effectively govern your environment.

The old way...

I created a lot a script over the years and when it comes the time to list or search for resources across all subscriptions, the usage pattern is pretty much always the same: Connect to a subscription, fetch what you need, switch to the next subscription, rinse and repeat.

Example in PowerShell:

$results = Get-AzSubscription | % { 
    Write-Host ('Processing subscription {0}' -f $_.Name)
    $null = Set-AzContext -Subscription $_.Id
    Get-AzResource -ResourceType 'Microsoft.Web/sites'     ...
}
$results.Count

Time to execute something like this over my ~30 subscriptions: 131 sec (2m11s)
This approach was the only way possible until the graph was made available. It is very slow, but hey, it served me well.

How to use Azure Resource Graph

You can use the REST API directly, Azure CLI or Azure PowerShell (Az module) to use Azure Resource Graph.

Here is an example in PowerShell:

$results = Search-AzGraph -Query "where type =~ 'Microsoft.Web/sites'" -First 5000
$results.Count

Time to execute something like this over my ~30 subscriptions: 2.5 sec -- which is over 50x faster!

Working with large datasets

There is one catch though, by default the behavior for -First parameter is 100 results. At the time of writing this, First currently has a maximum allowed value of 5000. Beyond that you need to page your results.

From the Microsoft documentation:

The control that is most restrictive will win. For example, if your query uses the top or limit operators and would result in more records than First, the maximum records returned would be equal to First. Likewise, if top or limit is smaller than First, the record set returned would be the smaller value configured by top or limit.

Paging your results

If you really want paging, at the moment of writing this, you'll need to call the REST API directly. The REST API QueryResponse provides values to indicate of a result set has been broken up: resultTruncated and $skipToken.

There is good documentation on how to handle paging with the REST API, but if you use PowerShell for example, you will need to put a little bit more effort to page properly until the native support is implemented. First, you need to sort your results, otherwise they will be outputted randomly and you'll never be able to page.

You can sort in your query by using the following construct: order by [field1], [field2] asc|desc

Here is an example how you can implement paging in PowerShell until native support is there:

$pageSize = 1000
$iteration = 0
$searchParams = @{
    Query = "where type =~ 'Microsoft.Web/sites' | project id, name, resourceGroup | order by id, resourceGroup desc"
    First = $pageSize
}

$results = do {
    $iteration += 1
    Write-Verbose "Iteration #$iteration" -Verbose
    $pageResults = Search-AzGraph @searchParams
    $searchParams.Skip += $pageResults.Count
    $pageResults
} while ($pageResults.Count -eq $pageSize)
$results.Count

Conclusion

There is no good reason not to use Azure Resource Graph from now on, it is very fast and enable you to dig into resources in a brand new way. Psst, it is a subset of Kusto, the same query language behind Application Insights, Azure Log Analytics & Azure Data Explorer. Mastering this query language will be an asset for sure going forward in Azure.

References