Public/Get-TaskLog.ps1
|
function Get-TaskLog { <# .SYNOPSIS Retrieves and queries Toolbox execution logs. .DESCRIPTION Reads and filters log entries from Toolbox log files. Supports filtering by run ID, computer, task name, log level, date range, and search text. .PARAMETER RunId Filter logs by specific execution run ID. .PARAMETER Computer Filter logs by target computer name. Supports wildcards. .PARAMETER TaskName Filter logs by task name. Supports wildcards. .PARAMETER Level Filter logs by log level. .PARAMETER StartDate Filter logs from this date/time forward. .PARAMETER EndDate Filter logs up to this date/time. .PARAMETER Search Search for text in log messages. .PARAMETER Last Return only the last N log entries. .PARAMETER Tail Continuously monitor and display new log entries (like tail -f). .EXAMPLE Get-TaskLog -Last 50 Retrieves the last 50 log entries. .EXAMPLE Get-TaskLog -RunId "abc123-def456" Retrieves all log entries for a specific run. .EXAMPLE Get-TaskLog -Computer "SERVER*" -Level Error Retrieves error-level logs for computers matching "SERVER*". .EXAMPLE Get-TaskLog -TaskName "File.TestPathExists" -StartDate (Get-Date).AddHours(-1) Retrieves logs for a specific task from the last hour. .EXAMPLE Get-TaskLog -Tail Continuously displays new log entries as they are written. .EXAMPLE Get-TaskLog -StartDate (Get-Date).AddDays(-7) -Level Error | Export-Csv errors.csv Exports all errors from the last 7 days to CSV. .EXAMPLE Get-TaskLog -Search "timeout" -Last 100 Searches the last 100 log entries for the word "timeout". .EXAMPLE Get-TaskLog -Computer "WEB*" -TaskName "Service.*" | Group-Object Level | Select-Object Count, Name Groups logs by level for web servers running service tasks. .OUTPUTS PSCustomObject array containing log entries. .NOTES Logs are stored in %APPDATA%\Toolbox\Logs in JSON Lines (.jsonl) format. Log files are automatically rotated based on size and retention settings. Use -Tail for real-time monitoring during task execution. #> [CmdletBinding(DefaultParameterSetName = "Filter")] param( [Parameter(ParameterSetName = "Filter")] [string]$RunId, [Parameter(ParameterSetName = "Filter")] [SupportsWildcards()] [string]$Computer, [Parameter(ParameterSetName = "Filter")] [SupportsWildcards()] [string]$TaskName, [Parameter(ParameterSetName = "Filter")] [ValidateSet("Verbose", "Info", "Warning", "Error")] [string]$Level, [Parameter(ParameterSetName = "Filter")] [datetime]$StartDate, [Parameter(ParameterSetName = "Filter")] [datetime]$EndDate, [Parameter(ParameterSetName = "Filter")] [string]$Search, [Parameter(ParameterSetName = "Filter")] [int]$Last, [Parameter(ParameterSetName = "Tail")] [switch]$Tail ) # Get log configuration $config = Get-TbConfig -Section Logging if (-not (Test-Path $config.LogPath)) { Write-Warning "Log directory not found: $($config.LogPath)" return } try { if ($Tail) { # Tail mode - continuously monitor logs Write-Host "Monitoring logs... (Press Ctrl+C to stop)" -ForegroundColor Cyan $logFiles = Get-ChildItem -Path $config.LogPath -Filter "Toolbox_*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if (-not $logFiles) { Write-Warning "No log files found" return } $currentFile = $logFiles.FullName $lastPosition = (Get-Item $currentFile).Length while ($true) { Start-Sleep -Milliseconds 500 # Check for new log file $latestFile = Get-ChildItem -Path $config.LogPath -Filter "Toolbox_*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($latestFile.FullName -ne $currentFile) { $currentFile = $latestFile.FullName $lastPosition = 0 } $currentLength = (Get-Item $currentFile).Length if ($currentLength -gt $lastPosition) { $stream = [System.IO.File]::Open($currentFile, "Open", "Read", "ReadWrite") $stream.Position = $lastPosition $reader = New-Object System.IO.StreamReader($stream) while ($null -ne ($line = $reader.ReadLine())) { try { $entry = $line | ConvertFrom-Json Format-LogEntry -Entry $entry } catch { Write-Host $line } } $lastPosition = $stream.Position $reader.Close() $stream.Close() } } } else { # Standard filter mode $logFiles = Get-ChildItem -Path $config.LogPath -Filter "Toolbox_*.log" | Sort-Object LastWriteTime -Descending if (-not $logFiles) { Write-Warning "No log files found in: $($config.LogPath)" return } $allEntries = @() foreach ($logFile in $logFiles) { $content = Get-Content -Path $logFile.FullName -Encoding UTF8 foreach ($line in $content) { if ([string]::IsNullOrWhiteSpace($line)) { continue } try { $entry = $line | ConvertFrom-Json $allEntries += $entry } catch { Write-Verbose "Failed to parse log line: $line" } } } # Apply filters $filteredEntries = $allEntries if ($RunId) { $filteredEntries = $filteredEntries | Where-Object { $_.RunId -eq $RunId } } if ($Computer) { $filteredEntries = $filteredEntries | Where-Object { $_.Computer -like $Computer } } if ($TaskName) { $filteredEntries = $filteredEntries | Where-Object { $_.TaskName -like $TaskName } } if ($Level) { $filteredEntries = $filteredEntries | Where-Object { $_.Level -eq $Level } } if ($StartDate) { $filteredEntries = $filteredEntries | Where-Object { [datetime]$_.Timestamp -ge $StartDate } } if ($EndDate) { $filteredEntries = $filteredEntries | Where-Object { [datetime]$_.Timestamp -le $EndDate } } if ($Search) { $filteredEntries = $filteredEntries | Where-Object { $_.Message -like "*$Search*" } } # Sort by timestamp $filteredEntries = $filteredEntries | Sort-Object Timestamp # Apply Last filter if ($Last) { $filteredEntries = $filteredEntries | Select-Object -Last $Last } return $filteredEntries } } catch { Write-Error "Failed to retrieve logs: $_" } } function Format-LogEntry { <# .SYNOPSIS Formats a log entry for console display. #> param( [Parameter(Mandatory)] [PSCustomObject]$Entry ) $timestamp = [datetime]::Parse($Entry.Timestamp).ToString("yyyy-MM-dd HH:mm:ss") $color = switch ($Entry.Level) { "Verbose" { "Gray" } "Info" { "White" } "Warning" { "Yellow" } "Error" { "Red" } default { "White" } } $prefix = "[$timestamp][$($Entry.Level)]" if ($Entry.Computer) { $prefix += "[$($Entry.Computer)]" } if ($Entry.TaskName) { $prefix += "[$($Entry.TaskName)]" } Write-Host $prefix -ForegroundColor $color -NoNewline Write-Host " $($Entry.Message)" if ($Entry.Error) { Write-Host " Error: $($Entry.Error.Message)" -ForegroundColor Red } } |