You can create a Mermaid Gantt Chart in order to visualize the sequence and duration of Azure deployment operations. The output is similar to the following:
gantt
dateFormat %YYYY-%m-%dT%H:%M:%S.%L%Z
axisFormat %H:%M:%S.%L
title Deployment 'mydeployment'
> : milestone, 2024-12-09T14:00:14.1519943Z, 0ms
x : milestone, 2024-12-09T14:00:23.5689337Z, 0ms
section mydeployment
Create Microsoft.Resources/deployments B : active, 2024-12-09T14:00:14.7907764Z, 8205ms
Create Microsoft.Resources/deployments A : active, 2024-12-09T14:00:14.7907764Z, 6206ms
EvaluateDeploymentOutput 08584678540724326236 : done, 2024-12-09T14:00:23.1924209Z, 242ms
section B
> : milestone, 2024-12-09T14:00:14.7907764Z, 0ms
Create Microsoft.Resources/deployments C : active, 2024-12-09T14:00:17.3704893Z, 3625ms
EvaluateDeploymentOutput 08584678540693804152 : done, 2024-12-09T14:00:17.3704893Z, 3908ms
x : milestone, 2024-12-09T14:00:22.9959845Z, 0ms
section A
> : milestone, 2024-12-09T14:00:14.7907764Z, 0ms
EvaluateDeploymentOutput 08584678540693853489 : done, 2024-12-09T14:00:18.3662764Z, 173ms
x : milestone, 2024-12-09T14:00:20.9970226Z, 0ms
section C
> : milestone, 2024-12-09T14:00:17.3704893Z, 0ms
EvaluateDeploymentOutput 08584678540668082037 : done, 2024-12-09T14:00:19.3775373Z, 157ms
x : milestone, 2024-12-09T14:00:20.9955158Z, 0ms
You need to specify the deployment identifier as deploymentid
for the deployment root you want to visualize. You need to have read permissions to the deployment and all related deployments, potentially at different scopes than the root deployment.
The script gets the root deployment resource and associated deployment operations. For operations that are subdeployments (deployment resources of type Microsoft.Resources/deployments
) it recursively retrieves the nested deployment operations. It then generates a Gantt chart in Mermaid syntax, with operations grouped by deployment and sorted by starting time.
Finally the Gantt syntax can be rendered using Mermaid CLI as an image. It can also be embedded directly in GitHub markdown.
# specify the root deployment resource identifier
$deploymentid='/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Resources/deployments/mydeployment'
# get the root deployment resource
$deployment=az rest -m get -u "${deploymentid}?api-version=2022-12-01"|convertfrom-json
# recursively get deployment operations
function Get-Operations([string]$deploymentid){
if($deploymentid -match '/providers/Microsoft.Resources/deployments/([^/]+)$'){
write-host -f yellow "Getting operations for deployment $($matches[1])"
az rest -m get -u "${deploymentid}/operations?api-version=2022-12-01"|convertfrom-json|select -exp value|%{
$_|add-member -notepropertyname deploymentid -notepropertyvalue $deploymentid
write-output $_
if($_.properties.targetresource.resourcetype -eq 'Microsoft.Resources/deployments'){
get-operations $_.properties.targetresource.id
}
}
}else{throw}
}
get-operations $deployment.id|%{$operations=@()}{
$duration=[xml.xmlconvert]::totimespan($_.properties.duration)
$end=$_.properties.timestamp.touniversaltime()
$_|add-member -notepropertyname duration -notepropertyvalue $duration
$_|add-member -notepropertyname end -notepropertyvalue $end
$_|add-member -notepropertyname start -notepropertyvalue $end.subtract($duration)
$operations+=$_
}
# generate a mermaid gantt chart
$gantt=$operations|group-object deploymentid|sort-object {$_.group|measure-object -min start|select -exp minimum}|%{
'gantt'
' dateFormat %YYYY-%m-%dT%H:%M:%S.%L%Z'
' axisFormat %H:%M:%S.%L'
" title Deployment '$($deployment.name)'"
" 🟢 : milestone, $($deployment.properties.timestamp.touniversaltime().subtract([xml.xmlconvert]::totimespan($deployment.properties.duration)).tostring('o')), 0ms"
" 🔴 : milestone, $($deployment.properties.timestamp.touniversaltime().tostring('o')), 0ms"
}{
$deploymentid=$_.name
$operation=$operations|?{$_.properties.targetresource.resourcetype -eq 'Microsoft.Resources/deployments' -and $_.properties.targetresource.id -eq $deploymentid}|select -first 1
" section $($_.name -split '/'|select -last 1)"
if($operation){
" 🟢 : milestone, $($operation.start.tostring('o')), 0ms"
}
$_.group|sort-object start|%{
" $($_.properties.provisioningoperation) $($_.properties.targetresource.resourcetype) $($_.properties.targetresource.resourcename ?? $_.operationid) ($($_.duration.totalmilliseconds.tostring('f0'))ms) : $($_.properties.provisioningstate -eq 'Succeeded' ? ($_.properties.targetresource.resourcetype -eq 'Microsoft.Resources/deployments' ? 'active' : 'done') : 'crit'), $($_.start.tostring('o')), $($_.duration.totalmilliseconds.tostring('f0'))ms"
}
if($operation){
" 🔴 : milestone, $($operation.end.tostring('o')), 0ms"
}
}
# optionally render the gantt chart as an image using mermaid cli
# use configfile to support large diagrams
@{maxTextSize=99999999;maxEdges=99999999}|convertto-json|out-file mermaid.json
$gantt|npx -p @mermaid-js/mermaid-cli mmdc -i - -o gantt.svg --width 2048 --configFile=mermaid.json