Skip to content

Instantly share code, notes, and snippets.

@maskati
Last active December 16, 2024 09:27
Show Gist options
  • Save maskati/d16fdcf793718e57591ae31c08ddb938 to your computer and use it in GitHub Desktop.
Save maskati/d16fdcf793718e57591ae31c08ddb938 to your computer and use it in GitHub Desktop.
Create a Mermaid gantt chart of your Azure deployment operations

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
Loading

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment