Public/Get-PCOciUsage.ps1
|
function Get-PCOciUsage { <# .SYNOPSIS Queries the Usage API for a daily series of cost or usage and writes it to a file. .DESCRIPTION Daily granularity, cost, and no aggregation over time unless asked (decision D-009), so the file holds one row per day per group and the month-on-month question can be answered from it. A window longer than 90 days is split into several queries; a window ending within 48 hours of now is flagged in the report because the service still receives late usage for it. Up to four group-by dimensions. .PARAMETER Start The first day, inclusive. Default: the first day of the previous calendar month, UTC. .PARAMETER End The day after the last day, exclusive. Default: the first day of the current calendar month, UTC. .PARAMETER GroupBy Up to four of: service, skuName, skuPartNumber, unit, compartmentName, compartmentPath, compartmentId, platform, region, logicalAd, resourceId, resourceName, tenantId, tenantName. .PARAMETER AggregateByTime One row per group for the whole window instead of one per period. The file then says granularity TOTAL. .EXAMPLE Get-PCOciUsage -GroupBy service, compartmentPath -Path .\data\usage-2026-10.json -Deterministic #> [CmdletBinding(SupportsShouldProcess)] [OutputType([pscustomobject], [PowerCraft.OCI.Core.Usage.UsageSeries])] param( [PowerCraft.OCI.Core.Identity.OciContext]$Context, [datetime]$Start, [datetime]$End, [ValidateSet('Cost', 'Usage')][string]$QueryType = 'Cost', [ValidateSet('Daily', 'Hourly', 'Monthly')][string]$Granularity = 'Daily', [ValidateCount(0, 4)] [ValidateSet('service', 'skuName', 'skuPartNumber', 'unit', 'compartmentName', 'compartmentPath', 'compartmentId', 'platform', 'region', 'logicalAd', 'resourceId', 'resourceName', 'tenantId', 'tenantName')] [string[]]$GroupBy, [switch]$AggregateByTime, [ValidateRange(0, 6)][int]$CompartmentDepth = 6, [string]$Path = (Join-Path (Get-Location).Path 'usage.json'), [switch]$Deterministic, [string]$ReportPath, [switch]$PassThru, [switch]$Force ) $ctx = Get-PCOciContextOrThrow -Context $Context if ((Test-Path -LiteralPath $Path) -and -not $Force) { throw "A file already exists at '$Path'. Use -Force to overwrite it." } if (-not $ReportPath) { $ReportPath = [IO.Path]::ChangeExtension($Path, '.report.json') } $today = [DateTime]::UtcNow.Date $thisMonth = [DateTime]::new($today.Year, $today.Month, 1, 0, 0, 0, [DateTimeKind]::Utc) if (-not $PSBoundParameters.ContainsKey('End')) { $End = $thisMonth } if (-not $PSBoundParameters.ContainsKey('Start')) { $Start = $thisMonth.AddMonths(-1) } $query = [PowerCraft.OCI.Core.Usage.UsageQuery]::new() $query.TenancyId = $ctx.TenancyId $query.Start = [DateTimeOffset]::new([DateTime]::SpecifyKind($Start, [DateTimeKind]::Utc)) $query.End = [DateTimeOffset]::new([DateTime]::SpecifyKind($End, [DateTimeKind]::Utc)) $query.QueryType = $QueryType.ToUpperInvariant() $query.Granularity = $Granularity.ToUpperInvariant() if ($GroupBy) { $query.GroupBy.AddRange([string[]]$GroupBy) } $query.AggregateByTime = [bool]$AggregateByTime $query.CompartmentDepth = $CompartmentDepth $plan = [PowerCraft.OCI.Core.Usage.UsagePlanner]::Plan($query, [DateTimeOffset]::UtcNow) if (-not $PSCmdlet.ShouldProcess($Path, "Query $($query.QueryType) $($query.Granularity) for $($plan.Windows.Count) window(s)")) { return } $report = [PowerCraft.OCI.Core.Report.RunReport]::new() $report.Verb = 'Get-PCOciUsage' $started = [DateTimeOffset]::UtcNow $report.StartedAt = $started $series = [PowerCraft.OCI.Core.Gateways.UsageGateway]::Run($ctx, $query, $plan, $report) $duration = [long]([DateTimeOffset]::UtcNow - $started).TotalMilliseconds $report.DurationMs = $duration [PowerCraft.OCI.Core.Usage.UsageWriter]::Write($series, $Path, [bool]$Deterministic) $report.Write($ReportPath, [bool]$Deterministic) foreach ($w in $report.Warnings) { Write-Warning $w } if (-not $series.Complete) { Write-Warning ("The usage series is incomplete: {0} failure(s). See '{1}'." -f $report.Failures.Count, $ReportPath) } if ($PassThru) { return $series } [pscustomobject]@{ UsagePath = (Resolve-Path -LiteralPath $Path).Path ReportPath = (Resolve-Path -LiteralPath $ReportPath).Path Complete = $series.Complete Start = $series.Start End = $series.End QueryType = $series.QueryType Granularity = $series.Granularity GroupBy = @($series.GroupBy) Windows = $plan.Windows.Count Rows = $series.Rows.Count Currency = $series.Currency DurationMs = $duration } } |