forked from actions/runner-images
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmeasure-provisioners-duration.ps1
122 lines (103 loc) · 4.67 KB
/
measure-provisioners-duration.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
param(
[Parameter(Mandatory=$true)]
[string]$PackerLogPath,
[string]$PrefixToPathTrim,
[int]$PrintTopNLongest = 25
)
$DateTimeRegex = "(\d+\/\d+\/\d+ \d+:\d+:\d+)"
$TelemetryLineRegex = "\[INFO\] \(telemetry\)"
$StartProvisionerRegex = "^${DateTimeRegex} ${TelemetryLineRegex} Starting provisioner (.+)$"
$EndProvisionerRegex = "^${DateTimeRegex} ${TelemetryLineRegex} ending (.+)$"
$ShellScriptSubItemRegex = "${DateTimeRegex} ui: ==> .+: Provisioning with \w+ script: (.+)"
$DownloadUploadSubItemRegex = "${DateTimeRegex} ui: ==> .+: (Downloading .+|Uploading .+)"
function Start-ProvisionerItem {
param([string]$ProvisionerType, [string]$StartTime)
return @{
ProvisionerType = $ProvisionerType
StartTime = [DateTime]::Parse($StartTime)
SubItems = @()
}
}
function End-ProvisionerItem {
param([object]$Provisioner, [string]$EndTime)
$Provisioner.EndTime = [DateTime]::Parse($EndTime)
$Provisioner.Duration = New-TimeSpan -Start $Provisioner.StartTime -End $Provisioner.EndTime
}
function Add-ProvisionerSubItem {
param([object]$Provisioner, [string]$Command, [string]$DateTime)
$lastItem = $Provisioner.SubItems | Select-Object -Last 1
if ($lastItem) {
$lastItem.EndTime = [DateTime]::Parse($DateTime)
$lastItem.Duration = New-TimeSpan -Start $lastItem.StartTime -End $lastItem.EndTime
}
if ($Command) {
if ($PrefixToPathTrim) { $Command = $Command.Replace($PrefixToPathTrim, ".") }
$Provisioner.SubItems += @{
Command = $Command
StartTime = [DateTime]::Parse($DateTime)
}
}
}
function Invoke-TryFindProvisionerSubItem {
param([object]$Provisioner, [string] $Line)
if ($Provisioner.ProvisionerType -in "powershell", "shell", "windows-shell") {
if ($Line -match $ShellScriptSubItemRegex) {
Add-ProvisionerSubItem -Provisioner $Provisioner -Command $Matches[2] -DateTime $Matches[1]
}
} elseif ($Provisioner.ProvisionerType -eq "file") {
if ($Line -match $DownloadUploadSubItemRegex) {
Add-ProvisionerSubItem -Provisioner $Provisioner -Command $Matches[2] -DateTime $Matches[1]
}
}
}
function Assert-StartProvisioner {
param([object]$Provisioner, [string]$ProvisionerType)
if ($null -ne $Provisioner) {
throw "New provisioner '$ProvisionerType' has been started but previous '$($Provisioner.ProvisionerType)' was not finished yet"
}
}
function Assert-EndProvisioner {
param([object]$Provisioner, [string]$ProvisionerType)
if (($null -ne $Provisioner) -and ($Provisioner.ProvisionerType -ne $ProvisionerType)) {
throw "Expected end of '$($Provisioner.ProvisionerType)' provisioner but found end of '$ProvisionerType'"
}
}
$provisionersList = @()
$currentProvisioner = $null
if ((Get-Content $PackerLogPath -Raw) -notmatch $TelemetryLineRegex) {
throw "Packer log doesn't contain diagnostic information. Env PACKER_LOG must be set to 1"
}
Get-Content $PackerLogPath | ForEach-Object {
if ($_ -match $StartProvisionerRegex) {
Assert-StartProvisioner -Provisioner $currentProvisioner -ProvisionerType $Matches[2]
$currentProvisioner = Start-ProvisionerItem -ProvisionerType $Matches[2] -StartTime $Matches[1]
} elseif (($_ -match $EndProvisionerRegex) -and $currentProvisioner) {
Assert-EndProvisioner -Provisioner $currentProvisioner -ProvisionerType $Matches[2]
End-ProvisionerItem -Provisioner $currentProvisioner -EndTime $Matches[1]
Add-ProvisionerSubItem -Provisioner $currentProvisioner -Command $null -DateTime $Matches[1]
$provisionersList += $currentProvisioner
$currentProvisioner = $null
} elseif ($currentProvisioner) {
Invoke-TryFindProvisionerSubItem -Provisioner $currentProvisioner -Line $_
}
}
$totalProvisionersTime = New-TimeSpan
$provisionersList | ForEach-Object { $totalProvisionersTime = $totalProvisionersTime.Add($_.Duration) }
# Print information about provisioners in order of execution
Write-Host "Build timeline:"
$provisionersList | ForEach-Object {
Write-Host "- $($_.Duration) | $($_.ProvisionerType)"
$_.SubItems | ForEach-Object {
Write-Host " $($_.Duration) | $($_.Command)"
}
Write-Host ""
}
Write-Host "Total provisioners time: $totalProvisionersTime"
if ($PrintTopNLongest -gt 0) {
Write-Host "`n`nTop longest provisioners:"
$provisionersList | ForEach-Object {
if ($_.SubItems.Length -gt 0) { $_.SubItems } else { @{ Command = $_.ProvisionerType; Duration = $_.Duration } }
} | Sort-Object { $_.Duration } | Select-Object -Last $PrintTopNLongest | ForEach-Object {
Write-Host "- $($_.Duration) | $($_.Command)"
}
}