modules/Azure/Discovery/Private/InvokeCIEMDiscoveryPhase.ps1
|
function InvokeCIEMDiscoveryPhase { <# .SYNOPSIS Runs one named phase of Start-CIEMAzureDiscovery with uniform stopwatch + try/catch + logging semantics. .DESCRIPTION Every collection/persistence step of discovery follows the same shape: start a stopwatch, run an action, log elapsed time, and route any exceptions into a shared error accumulator so the run can complete as Partial instead of exploding on the first failure. This helper centralizes that shell so individual phase Actions contain only the domain logic. On success, returns the Action's output. On failure, returns $null and mutates $ErrorMessages with a phase-prefixed message. The caller can then decide whether to set a per-phase success flag. .PARAMETER Name Human-readable phase label used in logs and error messages. .PARAMETER Action Scriptblock executing the phase. May return any value; its output is forwarded to the caller. .PARAMETER ErrorMessages Shared error accumulator list. Failed phases append "<Name> failed: <message>" entries. .PARAMETER WarningCounter Ref to an integer counter. Failed phases increment it. .PARAMETER OnSuccess Optional scriptblock invoked after a successful Action with the Action's output as $args[0]. Use this to update row counts or set per-phase success flags. .PARAMETER DetailBuilder Optional scriptblock invoked (with the Action output as $args[0]) to produce a log-detail suffix like "123 rows". #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory)] [scriptblock]$Action, [Parameter(Mandatory)] [System.Collections.Generic.List[string]]$ErrorMessages, [Parameter(Mandatory)] [ref]$WarningCounter, [Parameter()] [scriptblock]$OnSuccess, [Parameter()] [scriptblock]$DetailBuilder ) $ErrorActionPreference = 'Stop' $stopwatch = [Diagnostics.Stopwatch]::StartNew() $result = $null $succeeded = $true try { $result = & $Action } catch { $succeeded = $false $WarningCounter.Value++ $failMessage = "${Name} failed: $($_.Exception.Message)" $ErrorMessages.Add($failMessage) Write-Warning $failMessage } $stopwatch.Stop() $elapsed = [math]::Round($stopwatch.Elapsed.TotalSeconds, 2) if ($succeeded) { $detail = if ($DetailBuilder) { try { & $DetailBuilder $result } catch { $null } } else { $null } $logMessage = "Phase ${Name} completed in ${elapsed}s" if ($detail) { $logMessage += " - $detail" } Write-CIEMLog -Message $logMessage -Component 'Discovery' if ($OnSuccess) { & $OnSuccess $result } } else { Write-CIEMLog -Message "Phase ${Name} failed after ${elapsed}s" -Severity WARNING -Component 'Discovery' } [pscustomobject]@{ Name = $Name Succeeded = $succeeded Result = $result ElapsedSeconds = $elapsed } } |