Public/Timing/Invoke-WithSubStepTimer.ps1
|
<# .NOTES Compatibility shim - the stopwatch wrapper over Add-SubStepDuration, kept identical to the pre-generalisation verb. The actual list mutation lives in Add-SubStepDuration so the find-or-create + sticky-status logic has one implementation whether the caller measured the work itself or delegated here. #> function Invoke-WithSubStepTimer { <# .SYNOPSIS Time -Action and accumulate it under a sub-step of a named phase. .DESCRIPTION The common-case 2-level verb: run -Action under a stopwatch and add its wall-clock time to the (Parent, Name) sub-step on the default context. Mirrors Invoke-WithPhaseTimer's contract on the sub-step side - the action runs as-is, any exception propagates, and the elapsed is recorded even on failure (with the sub-step marked stickily Failed). Multi-call accumulation is the headline behaviour: post-provisioning runs per VM, so the same sub-step is timed once per VM and each call adds to the running total. .PARAMETER Parent Parent top-level phase name; must already be declared. .PARAMETER Name Sub-step display name; lazily created on first contact. .PARAMETER Action The work to time. Runs as-is; exceptions propagate. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string] $Parent, [Parameter(Mandatory)] [string] $Name, [Parameter(Mandatory)] [scriptblock] $Action ) $sw = [System.Diagnostics.Stopwatch]::StartNew() try { & $Action $sw.Stop() Add-SubStepDuration ` -Parent $Parent ` -Name $Name ` -ElapsedMs $sw.ElapsedMilliseconds } catch { # Capture the partial duration before re-throwing - the report still # needs to show how long the failing sub-step ran. The -Failed switch # makes the status stickily Failed even if a later VM's iteration of # the same sub-step succeeds. $sw.Stop() Add-SubStepDuration ` -Parent $Parent ` -Name $Name ` -ElapsedMs $sw.ElapsedMilliseconds ` -Failed throw } } |