Private/RunTiming.ps1
|
# How long a Run took, and each Check in it. # # A Run that takes four minutes on one machine and fourteen on another says something of # the second, and a Technician waiting at the window wants to know which Check is the # slow one. So the Run measures every Check, both Parts and itself, and says it three # times: in the window as it goes, in the box at the top of the Report, and as a table # among the evidence. Measured by the Run, and not by a Check: a Check does not know how # long it takes, and has no business knowing. function Format-RunDuration { <# .SYNOPSIS A length of time as a Technician reads it: "0,7 s" below ten seconds, whole seconds up to two minutes, minutes and seconds up to an hour, hours and minutes from there. Empty for none. Pure. #> [CmdletBinding()] [OutputType([string])] param([AllowNull()]$Seconds) $number = ConvertTo-Number $Seconds if ($null -eq $number) { return '' } $seconds = [math]::Max([double]0, [double]$number) if ($seconds -lt 10) { return (Get-Text 'Value.Duration.SecondsTenth' $seconds) } if ($seconds -lt 120) { return (Get-Text 'Value.Duration.Seconds' ([int][math]::Round($seconds))) } $whole = [int][math]::Round($seconds) if ($whole -lt 3600) { return (Get-Text 'Value.Duration.Minutes' ([int][math]::Floor($whole / 60)) ($whole % 60)) } Get-Text 'Value.Duration.Hours' ([int][math]::Floor($whole / 3600)) ([int][math]::Floor(($whole % 3600) / 60)) } function New-RunTiming { <# .SYNOPSIS One Check's time: its name, the Part it ran in, and its seconds. Pure. #> [CmdletBinding()] [OutputType([psobject])] param( [Parameter(Mandatory)][AllowEmptyString()][string]$Check, [ValidateSet('Main', 'Elevated')][string]$Part = 'Main', [double]$Seconds = 0 ) [pscustomobject]@{ Check = $Check; Part = $Part; Seconds = [math]::Round([math]::Max([double]0, $Seconds), 2) } } function Get-RunTimingRow { <# .SYNOPSIS How long the Run took, as a row of the box at the top of the Report: Group, Name, Value. Nothing where nothing was measured. Pure. .DESCRIPTION Until the Report was written: the time it takes to write it is the only part of a Run the Report cannot know. The Administrator Part is said beside it where there was one, being what a Technician waited for at the prompt. #> [CmdletBinding()] [OutputType([psobject])] param([AllowNull()]$Seconds, [AllowNull()]$ElevatedSeconds) $total = Format-RunDuration -Seconds $Seconds if (-not $total) { return } $value = $total $admin = Format-RunDuration -Seconds $ElevatedSeconds if ($admin) { $value = (Get-Text 'Run.DurationWithAdmin') -f $total, $admin } [pscustomobject]@{ Group = (Get-Text 'System.Info.Group.Run'); Name = (Get-Text 'Run.Duration'); Value = $value } } function New-RunTimingSection { <# .SYNOPSIS Every Check of the Run with its time, the longest first, and its share of the Run. Nothing where nothing was measured. Pure. #> [CmdletBinding()] [OutputType([psobject])] param([AllowNull()][AllowEmptyCollection()]$Timing, [AllowNull()]$Seconds) $all = @($Timing | Where-Object { $_ -and "$($_.Check)".Trim() }) if (-not $all.Count) { return } $total = ConvertTo-Number $Seconds $rows = @($all | Sort-Object @{ Expression = { [double]$_.Seconds }; Descending = $true }, Check | ForEach-Object { $row = [ordered]@{} $row[(Get-Text 'Column.Run.Check')] = "$($_.Check)" $row[(Get-Text 'Column.Run.Part')] = $(if ("$($_.Part)" -eq 'Elevated') { Get-Text 'Value.Run.PartAdmin' } else { Get-Text 'Value.Run.PartMain' }) $row[(Get-Text 'Column.Run.Took')] = '{0:N1}' -f [double]$_.Seconds $row[(Get-Text 'Column.Run.Share')] = $(if ($total -gt 0) { '{0:N0} %' -f ([double]$_.Seconds / $total * 100) } else { '' }) [pscustomobject]$row }) New-Section -Title (Get-Text 'Title.Run.Timing') -Row $rows -Help (Get-Text 'Help.Run.Timing') } |