Private/Get-AACCostContributor.ps1
|
function Get-AACCostContributor { <# .SYNOPSIS The resources behind a cost anomaly: from daily cost rows grouped by resource, each one's average a day during the anomaly against the days before it - the biggest rises first. .DESCRIPTION -Rows are Cost Management rows (Cost, UsageDate, ResourceId) from the days before -Start to -End. Returns up to -Top objects: @{ Resource; ResourceId; Before (a day); During (a day); Change }. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [AllowEmptyCollection()] [object[]] $Rows = @(), [Parameter(Mandatory)] [datetime] $Start, [Parameter(Mandatory)] [datetime] $End, [int] $Top = 3 ) $value = { param($Row, [string] $Name) if ($Row -is [System.Collections.IDictionary]) { $Row[$Name] } else { $p = $Row.PSObject.Properties[$Name]; if ($p) { $p.Value } } } $toDay = { param($Raw) if ($Raw -is [datetime]) { $Raw.Date } elseif ([string]$Raw -match '^\d{8}$') { [datetime]::ParseExact([string]$Raw, 'yyyyMMdd', [cultureinfo]::InvariantCulture) } else { ([datetime]$Raw).Date } } $from = $Start.Date $to = $End.Date $beforeDays = [Math]::Max(1, @($Rows | ForEach-Object { & $toDay (& $value $_ 'UsageDate') } | Where-Object { $_ -lt $from } | Select-Object -Unique).Count) $duringDays = [int]($to - $from).TotalDays + 1 $byResource = @{} foreach ($row in $Rows) { $id = [string](& $value $row 'ResourceId') if (-not $id) { continue } $day = & $toDay (& $value $row 'UsageDate') if (-not $byResource.Contains($id)) { $byResource[$id] = @{ Before = 0.0; During = 0.0 } } if ($day -lt $from) { $byResource[$id].Before += [double](& $value $row 'Cost') } elseif ($day -le $to) { $byResource[$id].During += [double](& $value $row 'Cost') } } @(foreach ($id in $byResource.Keys) { $before = $byResource[$id].Before / $beforeDays $during = $byResource[$id].During / $duringDays [pscustomobject]@{ Resource = ($id.TrimEnd('/') -replace '^.*/', ''); ResourceId = $id; Before = [Math]::Round($before, 2); During = [Math]::Round($during, 2); Change = [Math]::Round($during - $before, 2) } }) | Where-Object { $_.Change -gt 0 } | Sort-Object -Property Change -Descending | Select-Object -First $Top } |