logsloth.psm1

<#
.SYNOPSIS
.EXAMPLE
#>

function logsloth {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)]
        [System.String]
        $LINE,

        [switch]
        [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)]
        $TASKID_AS_SYMBOL = $false
    )

    begin {
        $_oldTime = $null
        $_stackDic = @{}
        $_mainTid = 0
        $_threadIndentDic = @{}
        
        $_funcColorDic = @{}
        $_COLOR_LIST = @("Green", "Red", "DarkGray", "DarkGreen", "DarkYellow", "Gray", "Magenta", "Cyan", "DarkCyan", "DarkRed", "Yellow")
        $_COLOR_LIST | Sort-Object { Get-Random } | Set-Variable _COLOR_LIST
        $_clrIdx = 0;

        $_taskIdSymDic = @{}
        $_TASK_SYM_LIST = "§ ☆ ★ ● ◎ ◇ ◆ ■ △ ▲ ▽ ▼ ◁ ◀ ▷ ▶ ♤ ♠ ♡ ♥ ♧ ♣ ⊙ ◈ ▣ ◐ ◑ ▒ ▤ ▥ ▨ ▧ ▦ ▩ ♨ ☏ ☎ ☜ ☞ ¶ †‡ ↕ ↗ ↙ ↖ ↘ ♭ ♩ ♪ ♬ ㉿ ㈜ ㉠ ㉡ ㉢ ㉣ ㉤ ㉥ ㉦ ㉧ ㉨ ㉩ ㉪ ㉫ ㉬ ㉭ ㉮ ㉯ ㉰ ㉱ ㉲ ㉳ ㉴ ㉵ ㉶ ㉷ ㉸ ㉹ ㉺ ㉻ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ㊀ ㊁ ㊂ ㊃ ㊄ ㊅ ㊆ ㊇ ㊈ ㊉ ㊊ ㊋ ㊌ ㊍ ㊎ ㊏ ㊐"
        $_TASK_SYM_LIST.split(' ', [System.StringSplitOptions]::RemoveEmptyEntries) | Sort-Object { Get-Random } | Set-Variable _TASK_SYM_LIST
        $_taskIdIdx = 0
    }

    process {
        try{
            $LINE = "$LINE "
            $curTime = $null

            if ($LINE -match "\d\d-\d\d\s\d\d:\d\d:\d\d.\d\d\d") {
                $curTime = [DateTime]::Parse("18-$($matches[0])")
            }
            elseif ($LINE -match "\d\d\d\d\d\d\d\d/\d\d:\d\d:\d\d.\d\d\d") {
                $orgTimeStr = $matches[0]
                $newTimeStr = "$($orgTimeStr.Substring(0, 4))-$($orgTimeStr.Substring(4, 2))-$($orgTimeStr.Substring(6, 2)) $($orgTimeStr.Substring(9))"
                $curTime = [DateTime]::Parse($newTimeStr)
            }
            else {
                $curTime = $_oldTime
            }

            if ($_oldTime -eq $null) {
                $_oldTime = $curTime
            }

            $period = $curTime - $_oldTime
            $_oldTime = $curTime


            $res = $LINE -match "LOGID\s:\s\d+\s\|"

            if (!$res) {
                return
            }

            $res = $matches[0] -match "\d+"
            $logId = $matches[0]

        


            $res = $LINE -match "TID\s:\s[-+]?\d+\s\|"

            if (!$res) {
                return
            }

            $res = $matches[0] -match "[-+]?\d+"
            $tid = $matches[0]
        



            $taskId = $null
            $taskSym = $null
            $res = $LINE -match "TASKID\s:\s\d+\s\|"

            if ($res) {
                $res = $matches[0] -match "\d+"
                $taskId = $matches[0]

                if ($_taskIdSymDic.ContainsKey($taskId)) {
                    $taskSym = $_taskIdSymDic[$taskId]
                }
                else {
                    $taskSym = $_TASK_SYM_LIST[$_taskIdIdx]
                    $_taskIdIdx += 1
                    $_taskIdSymDic[$taskId] = $taskSym
                }
            }




            if ($_mainTid -eq 0) {
                $_mainTid = $tid
            }

        

            $funcName = $null
            $idxBar = $LINE.LastIndexOf("|")
            $idxIn = $LINE.LastIndexOf(" ")
            $log = $LINE.Substring($idxBar + 2)

        

            if ($idxIn -gt 0) {
                $funcName = $LINE.Substring($idxBar + 1, $idxIn - $idxBar - 2)
                $funcName = $funcName.Trim()
            }

            $stack = $null
            $isNewTid = $false

            if ($_stackDic.ContainsKey($tid)) {
                $stack = $_stackDic[$tid]
            }
            else {
                $stack = New-Object "System.Collections.Generic.Stack[string]"
                $_stackDic[$tid] = $stack

                if ($tid -ne $_mainTid) {
                    $isNewTid = $true
                }
            }

            if ([string]::IsNullOrEmpty($funcName)) {
                if ($stack.Count -gt 0) {
                    $funcName = $stack.Peek()
                }
            }

            if (!$_funcColorDic.ContainsKey($funcName)) {
                $_funcColorDic[$funcName] = $_COLOR_LIST[$_clrIdx];
                $_clrIdx = ($_clrIdx + 1) % $_COLOR_LIST.Length;
            }

            if ($LINE -match "\sin\s") {
                $stack.Push($funcName)
            }

            $padCount = 0

            if ($_threadIndentDic.ContainsKey($tid)) {
                $padCount += $_threadIndentDic[$tid]
            }
            else {
                if ($tid -ne $_mainTid) {
                    $padCount += $_stackDic.Count * 20;
                }

                $_threadIndentDic[$tid] = $padCount;
            }
        
            $padCount += $stack.Count * 2;

            if (($LINE -match "\sout\s") -and ($stack.Count -gt 0)) {
                $res = $stack.Pop()

                if ($stack.Count -eq 0) {
                    $_stackDic.Remove($tid)
                }
            }
    
            $leftPadding = " " * $padCount;
            $beuatyLog = "[$([string]::Format("{0,6:N0}", $logId))][$([string]::Format("{0,5:N0}", $period.TotalMilliseconds))ms]$($leftPadding)";

            if ($isNewTid) {
                $beuatyLog += "TID[$tid]"
            }

            if ($taskId -ne $null) {
                if ($TASKID_AS_SYMBOL) {
                
                    $beuatyLog += $taskSym * 3
                }
                else {
                    $beuatyLog += "TASKID[$taskId]"
                }
            }

            $beuatyLog += " $log"

            if ($_funcColorDic.ContainsKey($funcName)) {
                Write-Host $beuatyLog -ForegroundColor $_funcColorDic[$funcName]
            }
            else {
                Write-Host $beuatyLog
            }
        } catch {
            Write-Host $LINE
        }
    }
}