XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
UTF-8
param(
    [Parameter(Mandatory=$true)][string]$RunDirectory,
    [string]$TraceId,
    [switch]$AllLevels,
    [long]$FromSequence=0,
    [ValidateRange(1,500)][int]$Limit=40
)
$ErrorActionPreference='Stop'
$logRoot=Join-Path ([IO.Path]::GetFullPath($RunDirectory)) 'logs'
$records=[Collections.Generic.List[object]]::new()
$invalid=0
foreach($file in (Get-ChildItem -LiteralPath $logRoot -File | Where-Object {$_.Name -match '^(offline-runtime|bootstrapper)\.\d{4}\.jsonl$'} | Sort-Object Name)) {
    $logInput=[IO.FileStream]::new($file.FullName,[IO.FileMode]::Open,[IO.FileAccess]::Read,[IO.FileShare]::ReadWrite)
    $logReader=[IO.StreamReader]::new($logInput)
    try { while($null -ne ($line=$logReader.ReadLine())) {
        try {
            $entry=ConvertFrom-Json -InputObject $line -AsHashtable
            if($entry.sequence -lt $FromSequence){continue}
            $fields=if($entry.ContainsKey('fields')){$entry.fields}else{@{}}
            if($TraceId -and $entry.traceId -ne $TraceId -and $fields.httpTraceId -ne $TraceId){continue}
            if(-not $AllLevels -and $entry.level -notin @('warning','error','critical')){continue}
            $entry['logFile']=$file.FullName
            $records.Add($entry)
        } catch { $invalid++ }
    } } finally { $logReader.Dispose() }
}
if($invalid){Write-Warning "未能解析 $invalid 条记录(运行中的最后一条可能尚未写完)。"}
$groups=$records | Group-Object { $_.component+'|'+$_.event+'|'+$_.message+'|'+$_.source.file+'|'+$_.source.line }
$result=foreach($group in ($groups | Sort-Object {$_.Group[0].utc} | Select-Object -First $Limit)) {
    $first=$group.Group[0];$last=$group.Group[-1]
    $fields=if($first.ContainsKey('fields')){$first.fields}else{@{}}
    [pscustomobject]@{
        firstUtc=$first.utc;lastUtc=$last.utc;count=$group.Count;sequence=$first.sequence
        level=$first.level;component=$first.component;event=$first.event;message=$first.message
        sourceFile=$first.source.file;sourceLine=$first.source.line;sourceMember=$first.source.member
        nativeFunction=$fields.nativeFunctionRva;nativeReturn=$fields.nativeReturnRva
        traceId=$first.traceId;httpTraceId=$fields.httpTraceId;fields=$fields
        exception=$first.exception;logFile=$first.logFile
    }
}
ConvertTo-Json -InputObject @($result) -Depth 8