Private/Export-LogReport.ps1
function Export-LogReport { [CmdletBinding()] param ( [Parameter(Mandatory)] [hashtable]$Summary, [Parameter(Mandatory)] [array]$Entries, [Parameter(Mandatory)] [string]$SourcePath, [Parameter(Mandatory)] [string]$OutputPath, [ValidateSet("Text", "Json", "Csv", "Html")] [string]$Format = "Text", [switch]$Redact, [switch]$IncludeMetadata, [switch]$GenerateRedactionLog ) $moduleVersion = '1.0.0' $timestamp = Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ' $metadata = @{ GeneratedAt = $timestamp ModuleVersion = $moduleVersion SourceFile = $SourcePath EntryCount = $Entries.Count } # Prepare redaction log (by reference) $redactionLogRef = [ref](New-Object System.Collections.Generic.List[string]) if ($Redact) { $Entries = $Entries | ForEach-Object { Protect-LogEntry -Entry $_ -RedactionLog $redactionLogRef } } if ($GenerateRedactionLog -and $Redact -and $redactionLogRef.Value.Count -gt 0) { $logPath = [System.IO.Path]::Combine((Split-Path -Path $OutputPath), 'redaction-log.txt') $logContent = @( "SmartLogAnalyzer Redaction Log - $timestamp", "Source File: $SourcePath", "Redacted Fields:", "" ) + $redactionLogRef.Value $logContent | Out-File -FilePath $logPath -Encoding UTF8 Write-Host "🛡️ Redaction log saved to: $logPath" -ForegroundColor DarkYellow } switch ($Format) { "Json" { $report = @{ Metadata = $IncludeMetadata ? $metadata : $null Summary = $Summary Entries = $Entries } | ConvertTo-Json -Depth 5 $report | Out-File -FilePath $OutputPath -Encoding UTF8 } "Csv" { $Entries | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 } "Text" { $lines = @() if ($IncludeMetadata) { $lines += "# SmartLogAnalyzer Report" $lines += "Generated At: $timestamp" $lines += "Source: $SourcePath" $lines += "Entries: $($Entries.Count)" $lines += "Version: $moduleVersion" $lines += "" } $lines += "=== Summary ===" foreach ($key in $Summary.Keys) { $lines += "$key : $($Summary[$key])" } $lines += "" $lines += "=== Log Entries ===" foreach ($entry in $Entries) { $lines += ($entry | Out-String).Trim() $lines += "-" * 40 } $lines | Out-File -FilePath $OutputPath -Encoding UTF8 } "Html" { $html = @" <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>SmartLogAnalyzer Report</title> <style> body { font-family: Consolas, monospace; padding: 1em; background: #f4f4f4; } h1 { color: #333; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #999; padding: 5px; text-align: left; } th { background-color: #eee; } </style> </head> <body> <h1>SmartLogAnalyzer Report</h1> <p><strong>Generated:</strong> $timestamp<br> <strong>Source:</strong> $SourcePath<br> <strong>Entries:</strong> $($Entries.Count)<br> <strong>Version:</strong> $moduleVersion</p> <h2>Summary</h2> <ul> "@ foreach ($key in $Summary.Keys) { $value = $Summary[$key] $html += "<li><strong>$key</strong>: $value</li>" } $html += "</ul><h2>Entries</h2><table><thead><tr>" $props = $Entries[0].PSObject.Properties.Name foreach ($p in $props) { $html += "<th>$p</th>" } $html += "</tr></thead><tbody>" foreach ($entry in $Entries) { $html += "<tr>" foreach ($p in $props) { $v = $entry.$p -replace '<', '<' -replace '>', '>' $html += "<td>$v</td>" } $html += "</tr>" } $html += "</tbody></table></body></html>" $html | Out-File -FilePath $OutputPath -Encoding UTF8 } default { throw "Unsupported format: $Format" } } Write-Verbose "Report exported: $OutputPath" } # SIG # Begin signature block # MIIFsAYJKoZIhvcNAQcCoIIFoTCCBZ0CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCC1iz1swtZS+la # KXUmonNqs450PZXXN0S3xa/rQVtGAKCCAxwwggMYMIICAKADAgECAhAVMtqhUrdy # mkjK9MI220b3MA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGVNtYXJ0TG9nQW5h # bHl6ZXIgRGV2IENlcnQwHhcNMjUwNjE4MjIxMTA3WhcNMjYwNjE4MjIzMTA3WjAk # MSIwIAYDVQQDDBlTbWFydExvZ0FuYWx5emVyIERldiBDZXJ0MIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzLQdDt7qLciu6u2CtXOuwfSDoMKY73xMjh7l # AcWWteWEvv9zLo6zQ02uHX5Xgz+dLyNhYs0kqQor4s8DkSRRQXzr90IENyL5LG5B # sMyFhhmmUjA4QFQxgn5exm4DI56hNw/VrDKTkGUvHE2SAai7spZBSkU6hXe2+aEj # Ld9vdbJc5gS0iGQ+XIF6oJUB3owuQE+30WFZaGpqtHfS8jtxkwUsfwxM1Y2AK+Zj # Mv1P+njfhVDbfIsXS051dtXbeE5ClEu5XINZP7zVXy4XEsGo/br/cA3OubbEzEJW # SnPVuuZGsw4SoM3RJx0MVPZG4vd2YLZDKiJYqv3uJBgQi4LYhQIDAQABo0YwRDAO # BgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFEOg # ZC7C7IdkMQsB+4Eti+0plKQ1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ+i2wjjPtCzjF # hrZw0IfpPcOOy/1fQXAryX52thXIA/Wcb+6qi5WmEpHZtZTxnZ3qyIkRpGa0NsuH # BlYu0HlTN9Y6JA25gdiOQ9idDpUbpOz+gfD/t9vs0+cQC664l7mnFqHGXRrSsC4N # zLYnde5ROU3NWfUkZyEsftBk0IghIi4qvJXAW3ic6dDQdq4rEpuUrI+pa2R2h1nE # sjkv2ru5yL58u8zS7enQ4XGMJRfcow4yyS55a3tQYtnZzCyWS7AeYkbTTjzE4Oxg # p31zzX01eYEundHvZAxoLg7QENvbqWiFwkbx7ssc/6ehiwOapNUhJTOB1glNAqX/ # rGRwMRitMYIB6jCCAeYCAQEwODAkMSIwIAYDVQQDDBlTbWFydExvZ0FuYWx5emVy # IERldiBDZXJ0AhAVMtqhUrdymkjK9MI220b3MA0GCWCGSAFlAwQCAQUAoIGEMBgG # CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC # AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE # ID8yOFQXW0a1Zf6YbZ1MYT8crQUbynU8aR3aXjT+Y1MSMA0GCSqGSIb3DQEBAQUA # BIIBAHz1uo4Vz8AauRe4iLurlbNX4dZjSTDw/zX+NCkFDmia0md7Qn2RXcfRqH8d # kZR+Gi7CBR3Stj+QgxcJkFAJuCL+54tl/7rQLJgjlrmAabzIQh0amJZBblW8HSbG # 3njDrOPFKwuB4ZNiIUHSSUy0YSBNdMCLP+2QnL4J/mENJiOgxsPCCiu7swhnewv3 # Hiw6bxs/VUiTMVWcpNYc3jbPxMtb814JZ1OssbM6e6I4+58hb+eF6ivrZNu4i5ZG # WFFE4HjZHLE8c1raXKBuieYx9lU1KXRdCDulk1wdjSH9GpGs6jpvv/XKBTVu6HFt # LMcC+S9mxqUc7P4YUjT9Vp2SOfA= # SIG # End signature block |