Public/Get-LogEntries.ps1
function Get-LogEntries { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$Path, [string[]]$IncludeKeywords = @(), [string[]]$ExcludeKeywords = @(), [datetime]$StartTime, [datetime]$EndTime, [ValidateSet("Forward", "Reverse")] [string]$SortOrder = "Forward", [int[]]$EventId, [string[]]$Level, [string[]]$ProviderName, [string]$ExportPath, [ValidateSet("CSV", "JSON")] [string]$ExportFormat = "CSV", [int]$Tail, [int]$LineLimit ) if (-not (Test-Path $Path) -and ($Path -ne 'journalctl')) { throw [System.IO.FileNotFoundException]::new("File not found: $Path", $Path) } $entries = @() # Windows Event Log Parsing if ($Path -match '\.(evtx|evt)$') { if (-not $IsWindows) { throw "❌ Windows event log parsing is only supported on Windows." } try { $events = Get-WinEvent -Path $Path -Oldest if ($StartTime) { $events = $events | Where-Object { $_.TimeCreated -ge $StartTime } } if ($EndTime) { $events = $events | Where-Object { $_.TimeCreated -le $EndTime } } if ($EventId) { $events = $events | Where-Object { $EventId -contains $_.Id } } if ($Level) { $events = $events | Where-Object { $Level -contains $_.LevelDisplayName } } if ($ProviderName) { $events = $events | Where-Object { $ProviderName -contains $_.ProviderName } } if ($SortOrder -eq "Reverse") { $events = $events | Sort-Object TimeCreated -Descending } $entries = $events | ForEach-Object { "$($_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')) [$($_.LevelDisplayName)] $($_.ProviderName): Event ID $($_.Id) - $($_.Message)" } } catch { throw "❌ Failed to parse EVT/EVTX file: $_" } } elseif ($Path -eq 'journalctl' -and !$IsWindows) { # journalctl support (Linux only) try { $cmd = "journalctl --no-pager" if ($StartTime) { $cmd += " --since '$($StartTime.ToString("yyyy-MM-dd HH:mm:ss"))'" } if ($EndTime) { $cmd += " --until '$($EndTime.ToString("yyyy-MM-dd HH:mm:ss"))'" } $entries = bash -c $cmd } catch { throw "❌ Failed to retrieve journalctl entries: $_" } } else { try { $entries = Get-Content -Path $Path -Encoding UTF8 -ErrorAction Stop } catch { throw "❌ Failed to read text log: $_" } if ($SortOrder -eq "Reverse") { $entries = $entries | Sort-Object { [array]::IndexOf($entries, $_) } -Descending } if ($StartTime -or $EndTime) { $entries = $entries | Where-Object { if ($_ -match '^(?<Time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})') { try { $logTime = [datetime]::ParseExact($matches.Time, 'yyyy-MM-dd HH:mm:ss', $null) (!($StartTime) -or $logTime -ge $StartTime) -and (!($EndTime) -or $logTime -le $EndTime) } catch { $false } } else { $false } } } } # Keyword filtering if ($IncludeKeywords.Count -gt 0) { $pattern = ($IncludeKeywords -join '|') $entries = $entries | Where-Object { $_ -match $pattern } } if ($ExcludeKeywords.Count -gt 0) { $pattern = ($ExcludeKeywords -join '|') $entries = $entries | Where-Object { $_ -notmatch $pattern } } if ($Tail) { $entries = $entries | Select-Object -Last $Tail } elseif ($LineLimit) { $entries = $entries | Select-Object -First $LineLimit } # Log Summary try { $summary = Get-LogSummary -LogLines $entries Write-Host "`n=== LOG SUMMARY ===" -ForegroundColor Cyan $summary | Format-List } catch { Write-Warning "⚠️ Get-LogSummary failed or not available." } # Export if ($ExportPath) { try { if ($ExportFormat -eq "CSV") { $entries | ForEach-Object { [PSCustomObject]@{ Entry = $_ } } | Export-Csv -Path $ExportPath -NoTypeInformation -Force } elseif ($ExportFormat -eq "JSON") { $entries | ForEach-Object { [PSCustomObject]@{ Entry = $_ } } | ConvertTo-Json -Depth 3 | Out-File -FilePath $ExportPath -Encoding UTF8 } Write-Host "✅ Log entries exported to $ExportPath" -ForegroundColor Green } catch { Write-Warning "❌ Failed to export: $_" } } return $entries } |