Functions/Public/Export-MetricsToCSV.ps1
|
function Export-MetricsToCSV { <# .SYNOPSIS Exports metrics data to a CSV file with dynamic headers. .DESCRIPTION The Export-MetricsToCSV function takes a PSObject containing metrics and writes them to a CSV file. It automatically generates headers from the object properties and includes a timestamp. Supports both appending to existing files and overwriting. .PARAMETER Metrics A PSObject containing the metrics to export. Each property becomes a column. .PARAMETER Path The path to the CSV file. .PARAMETER DateFormat The date format for the timestamp column. Default is ISO 8601 format. .PARAMETER DateColumnName The name of the date column. Default is "Date". .PARAMETER Overwrite If specified, overwrites the file instead of appending. .PARAMETER NoHeader If specified, doesn't write headers (useful when appending to existing file with different structure - use with caution). .PARAMETER PassThru If specified, returns the CSV line that was written. .INPUTS System.Management.Automation.PSObject. You can pipe metrics objects. .OUTPUTS None by default. The CSV line string if -PassThru is specified. .EXAMPLE $metrics = [PSCustomObject]@{ TotalDevices = 1500 ActiveDevices = 1200 InactiveDevices = 300 } Export-MetricsToCSV -Metrics $metrics -Path "C:\Data\device-metrics.csv" Creates/appends to CSV with columns: Date, TotalDevices, ActiveDevices, InactiveDevices .EXAMPLE $metrics | Export-MetricsToCSV -Path $metricsFile -Overwrite Overwrites the file with new metrics. .EXAMPLE Export-MetricsToCSV -Metrics $stats -Path $logFile -DateFormat "yyyy-MM-dd" Uses date-only format for timestamp. .NOTES Author: Sune Alexandersen Narud Version: 1.0.0 Date: February 2026 This is a generalized version of Log-MetricsToCSV and Log-Statistics functions. .LINK Test-FileLock #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [PSObject]$Metrics, [Parameter(Mandatory = $true, Position = 1)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter()] [string]$DateFormat = 'yyyy-MM-ddTHH:mm:ssZ', [Parameter()] [string]$DateColumnName = 'Date', [Parameter()] [switch]$Overwrite, [Parameter()] [switch]$NoHeader, [Parameter()] [switch]$PassThru ) process { try { # Extract property names and values from the metrics object $properties = $Metrics.PSObject.Properties | Where-Object { $_.MemberType -eq 'NoteProperty' } if ($properties.Count -eq 0) { Write-Warning "No properties found in metrics object." return } $headers = @($DateColumnName) + ($properties | ForEach-Object { $_.Name }) $values = @(Get-Date -Format $DateFormat) + ($properties | ForEach-Object { $_.Value }) # Escape values that contain commas or quotes $escapedValues = $values | ForEach-Object { $val = "$_" if ($val -match '[,"\n]') { '"' + ($val -replace '"', '""') + '"' } else { $val } } $headerLine = $headers -join ',' $csvLine = $escapedValues -join ',' # Check if file needs headers $writeHeaders = $false if (-not (Test-Path $Path) -or $Overwrite) { $writeHeaders = $true } # Check file lock if file exists if (Test-Path $Path) { if (Get-Command -Name 'Test-FileLock' -ErrorAction SilentlyContinue) { $isLocked = Test-FileLock -FilePath $Path -Silent if ($isLocked) { Write-Warning "File '$Path' is locked. Waiting for it to become available..." Test-FileLock -FilePath $Path # Interactive wait } } } # Write to file if ($PSCmdlet.ShouldProcess($Path, "Export metrics")) { if ($Overwrite) { if (-not $NoHeader) { $headerLine | Out-File -FilePath $Path -Encoding UTF8 } $csvLine | Out-File -FilePath $Path -Append -Encoding UTF8 } else { if ($writeHeaders -and -not $NoHeader) { $headerLine | Out-File -FilePath $Path -Encoding UTF8 } $csvLine | Out-File -FilePath $Path -Append -Encoding UTF8 } } if ($PassThru) { return $csvLine } } catch { Write-Error "Failed to export metrics to CSV: $_" } } } |