Public/Get-ChocoLogs.ps1

function Get-ChocoLogs {
    [CmdletBinding(DefaultParameterSetName = 'Filter')]
    param (
        # LogType
        [Parameter()]
        [ValidateSet('Summary', 'Full')]
        [string]
        $LogType = 'Summary',
        # Path to Chocolatey Log Folder
        [Parameter()]
        [string]
        $Path = (Join-Path $env:ChocolateyInstall 'logs'),
        # Last Number of Lines
        [Parameter(ParameterSetName = "Filter")]
        [int]
        $Last = 3000,
        # LogLevel
        [Parameter()]
        [ValidateSet('Information', 'Error', 'Warning', 'Debug')]
        [array]
        $LogLevel,
        # Message Search String
        [Parameter()]
        [Alias('Match')]
        [regex]
        $SearchString,
        # Minimum Date Filter, defaults to 7 days
        [Parameter(ParameterSetName = "Filter")]
        [datetime]
        $MinimumDate = (Get-Date).AddDays(-30),
        # Maximum Date Filter, defaults to now
        [Parameter(ParameterSetName = "Filter")]
        [datetime]
        $MaximumDate = (Get-Date),
        # Return All
        [Parameter(ParameterSetName = "All")]
        [switch]
        $All
    )
    
    if ($All) {
        $MinimumDate = [datetime]"01/01/1900"
        $Last = $null
    }
    if (-Not(Test-Path $Path)) {
        Write-Warning "Not able to access $Path"
        return
    }
    switch ($LogType) {
        Summary { $Logs = Get-ChildItem -Path $Path -Filter 'choco.summary*.log' | Where-Object { $_.LastWriteTime -ge $MinimumDate } | Get-Content }
        Full { $Logs = Get-ChildItem -Path $Path -Filter 'chocolatey*.log' | Where-Object { $_.LastWriteTime -ge $MinimumDate } | Get-Content }
        Default {}
    }
    if ($Logs.count -lt 1) {
        Write-Warning "No Log content found in files located at $Path"
        return
    }
    if ($Last -gt 0) {
        #Overprovission and reduce at the end as a hacky speedup
        $Logs = $Logs | Select-Object -Last ($Last * 3)
    }

    #Fix misc line returns
    $i = 0
    $Logsf = $Logs | ForEach-Object {
        if ($PSItem -match '\[ERROR\]|\[WARN \]|\[INFO \]|\[DEBUG\]') {
            if (($PSItem -split '] - ' | Select-Object -Last 1) -eq "") {
                $PSItem + $Logs[$i + 1]
            }
            if (($PSItem -split '] - ' | Select-Object -Last 1) -ne "") {
                $PSItem
            }
        }    
        $i++
    }

    $LogsError = [System.Collections.ArrayList]@()
    $LogsWarn = [System.Collections.ArrayList]@()
    $LogsInfo = [System.Collections.ArrayList]@()
    $LogsDebug = [System.Collections.ArrayList]@()

    $Logsf | ForEach-Object {
        if ($_ -match $SearchString -or $null -eq $SearchString) {
            if ($PSItem -Match '\[ERROR\]') {
                $null = $LogsError.Add("$PSItem")
            }
            if ($PSItem -Match '\[WARN \]') {
                $null = $LogsWarn.Add("$PSItem")
            }
            if ($PSItem -Match '\[INFO \]') {
                $null = $LogsInfo.Add("$PSItem")
            }
            if ($PSItem -Match '\[DEBUG\]') {
                $null = $LogsDebug.Add("$PSItem")
            }        
        }
        
    }

    #if ($SearchString -ne $null) {
    # Write-Verbose "RegEx SearchString: $SearchString"
    # $Logsf = $Logsf | Where-Object { $_ -match $SearchString }
    #}

    if ($LogLevel -contains 'Error' -or $null -eq $LogLevel) {
        $Job0 = Start-Job -ScriptBlock {
            $using:LogsError | ForEach-Object {
                $String = ((($PSItem -split '\[ERROR\]' | Select-Object -First 1) -split ','))
                $Message = ([string]($PSItem -split '\[ERROR\]' | Select-Object -Last 1)).TrimStart('- ')
                [datetime]$Date = ($String[0]) + ('.') + ($String[1] -split ' ' | Select-Object -First 1)
                [PSCustomObject]@{
                    Date     = $Date
                    LogLevel = 'Error'
                    Message  = $Message
                }
            }
        }
    }
    if ($LogLevel -contains 'Warning' -or $null -eq $LogLevel) {
        $Job1 = Start-Job -ScriptBlock {
            $using:LogsWarn | ForEach-Object {
                $String = ((($PSItem -split '\[WARN \]' | Select-Object -First 1) -split ','))
                $Message = ([string]($PSItem -split '\[WARN \]' | Select-Object -Last 1)).TrimStart('- ')
                [datetime]$Date = ($String[0]) + ('.') + ($String[1] -split ' ' | Select-Object -First 1)
                [PSCustomObject]@{
                    Date     = $Date
                    LogLevel = 'Warning'
                    Message  = $Message
                }
            }
        }
    }
    if ($LogLevel -contains 'Information' -or $null -eq $LogLevel) {
        $Job2 = Start-Job -ScriptBlock {
            $using:LogsInfo | ForEach-Object {
                $String = ((($PSItem -split '\[INFO \]' | Select-Object -First 1) -split ','))
                $Message = ([string]($PSItem -split '\[INFO \]' | Select-Object -Last 1)).TrimStart('- ')
                
                [datetime]$Date = ($String[0]) + ('.') + ($String[1] -split ' ' | Select-Object -First 1)
                [PSCustomObject]@{
                    Date     = $Date
                    LogLevel = 'Information'
                    Message  = $Message
                }
            }
        }  
    }
    if ($LogLevel -contains 'Debug' -or $null -eq $LogLevel) {
        $Job3 = Start-Job -ScriptBlock {
            $using:LogsDebug | ForEach-Object {
                $String = ((($PSItem -split '\[DEBUG\]' | Select-Object -First 1) -split ','))
                $Message = ([string]($PSItem -split '\[DEBUG\]' | Select-Object -Last 1)).TrimStart('- ')
                
                [datetime]$Date = ($String[0]) + ('.') + ($String[1] -split ' ' | Select-Object -First 1)
                [PSCustomObject]@{
                    Date     = $Date
                    LogLevel = 'Debug'
                    Message  = $Message
                }
            }
        }
    }

    $Job0 | Wait-Job -ErrorAction SilentlyContinue | Out-Null
    $Job1 | Wait-Job -ErrorAction SilentlyContinue | Out-Null
    $Job2 | Wait-Job -ErrorAction SilentlyContinue | Out-Null
    $Job3 | Wait-Job -ErrorAction SilentlyContinue | Out-Null

    $ObjectError = $job0 | Receive-Job -ErrorAction SilentlyContinue | Select-Object -Property Date, LogLevel, Message
    $ObjectWarn = $job1 | Receive-Job -ErrorAction SilentlyContinue | Select-Object -Property Date, LogLevel, Message
    $ObjectInfo = $job2 | Receive-Job -ErrorAction SilentlyContinue | Select-Object -Property Date, LogLevel, Message
    $ObjectDebug = $job3 | Receive-Job -ErrorAction SilentlyContinue | Select-Object -Property Date, LogLevel, Message
    
    [array]$ObjectReturn = @()
    if ($ObjectError.Count -gt 0) {
        $ObjectReturn += $ObjectError 
    }
    if ($ObjectWarn.Count -gt 0) {
        $ObjectReturn += $ObjectWarn 
    }
    if ($ObjectInfo.Count -gt 0) {
        $ObjectReturn += $ObjectInfo 
    }
    if ($ObjectDebug.Count -gt 0) {
        $ObjectReturn += $ObjectDebug 
    }

    $ObjectReturn = $ObjectReturn | Sort-Object -Property Date | Where-Object { ($_.Date -ge $MinimumDate) -and ($_.Date -le $MaximumDate) }
    if ($LogLevel -ne $null) {
        Write-Verbose "Filtering LogLevel: $LogLevel"
        $ObjectReturn = $ObjectReturn | Where-Object { $LogLevel -contains $_.LogLevel }
    }
    if ($Last -gt 0) {
        Write-Verbose "Return Last: $Last"
        $ObjectReturn = $ObjectReturn | Select-Object -Last $Last
    }
    return $ObjectReturn
}