logsloth.psm1

<#
.SYNOPSIS
.EXAMPLE
#>

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

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

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

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

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

    begin {
        $_oldTime = $null
        $_oldTid = 0
        $_threadIndentDic = @{}
        $_funcCountDic = @{}
        $_oldLog
        $_funcIndentDic = @{}
        $_oldfuncName = $null
        
        $_funcColorDic = @{}
        $_COLOR_LIST = @("Green", "DarkGray", "DarkGreen", "DarkYellow", "Gray", "Magenta", "Cyan", "DarkCyan", "DarkRed", "Yellow")
        $_oldClr = "White"

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

        
        if ($OUT_AS_HTML) {

            $_HTML_FILE_TOP = 
            @"
<html>
    <header>
        <style>
            pre {
                color: white;
                background-color: black;
                font-family: 'Courier New', Courier, monospace;
            }
        </style>
    </header>
    <body>
        <pre>
"@


            $_htmlFilePath = "logsloth-$([datetime]::Now.ToString("yyMMdd-HHmmss")).html"
            $_HTML_FILE_TOP | Out-File -Append $_htmlFilePath
        }
    }

    process {
        $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])")
        }
        else {
            Write-Host $LINE -ForegroundColor White

            if ($OUT_AS_HTML) {
                $htmlRow = $LINE
                $htmlRow | Out-File $_htmlFilePath -Append
            }

            return
        }

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

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



        $lineTokens = $LINE.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)
        $tid = $lineTokens[3]
        $tag = $lineTokens[5]
        $log = [string]::Join( " ", $lineTokens[6..$($lineTokens.Length)] ) 




        if (!$_funcIndentDic.ContainsKey($tid)) {
            $_funcIndentDic[$tid] = -1
        }

        if (($LINE -like "*!@#ENTER$%^*") -or ($LINE -like "*!@#EXIT$%^*")) {
            $enterExitOffset = 0

            if ($LINE -like "*!@#ENTER$%^*") {
                $enterExitOffset = 1
            }
            elseif ($LINE -like "*!@#EXIT$%^*") {
                $enterExitOffset = -1
            }

            $_funcIndentDic[$tid] = $_funcIndentDic[$tid] + $enterExitOffset
            return
        }



        $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
        $lineNum = 0
        
        for ( $i = 0; $i -lt $lineTokens.Length; $i++ ) {
            $token = $lineTokens[$i]
            if ($token -match "[.cpp|.h|.cc|.c|.cxx|.hpp]:\d+:") {
                $res = $token -split ":"
                $funcName = "$($res[0])::$($res[2])"
                $lineNum = $res[1]
                break
            }
        }

        if ($funcName -eq $null) {
            $funcName = "$tag$([string]::Join( " ", $lineTokens[5..6] ))"
            $log = "$tag$log"
        }

        if (!$_funcCountDic.ContainsKey($funcName)) {
            $_funcCountDic[$funcName] = 1
        }
        else {
            $_funcCountDic[$funcName] = $_funcCountDic[$funcName] + 1
        }

        $canSkipFuncName = ($_oldfuncName -eq $funcName)
        $_oldfuncName = $funcName

        if ($canSkipFuncName) {
            $log = [string]::Join( " ", $lineTokens[7..$($lineTokens.Length)] ) 
            $log = ":$lineNum $log"
        }
        else {
            Write-Host ""

            if ($OUT_AS_HTML) {
                $htmlRow = ""
                $htmlRow | Out-File $_htmlFilePath -Append
            }
        }



        $padCount = 0

        if (!$_threadIndentDic.ContainsKey($tid)) {
            $_threadIndentDic[$tid] = $_threadIndentDic.Count
        }

        $padCount = ($_threadIndentDic[$tid] % 10) * 4 + 1




        if (!$_funcColorDic.ContainsKey($funcName)) {
            $hashInt = _logsloth_str_2_byte_sum($funcName)
            $clrIdx = $hashInt % ($_COLOR_LIST.Length)
            $_funcColorDic[$funcName] = $_COLOR_LIST[$clrIdx];
        }

        

    
        
        $leftPadding = " " * $padCount;
        $funcIndent = [Math]::Max($_funcIndentDic[$tid], 0)
        $leftPadding += "·" * $funcIndent;

        

        $beuatyLog = "[$($lineTokens[0]) $($lineTokens[1])][$([string]::Format("{0,5:N0}", $period.TotalMilliseconds))ms]$($leftPadding)";

        if ($tid -ne $_oldTid) {
            Write-Host "TID[$tid]"

            if ($OUT_AS_HTML) {
                $htmlRow = "TID[$tid]"
                $htmlRow | Out-File $_htmlFilePath -Append
            }

            $_oldTid = $tid
        }

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

        $beuatyLog += $log
        $color = [System.ConsoleColor]::White

        if ($lineTokens[5] -eq "E") {
            $color = [System.ConsoleColor]::Red
        }
        elseif ($_funcColorDic.ContainsKey($funcName)) {
            $color = $_funcColorDic[$funcName]
        }

        Write-Host $beuatyLog -ForegroundColor $color

        if ($RETURN_LOG_AS_TABLE) {
            $row = New-Object psobject
            $row | Add-Member TimeStamp "$($lineTokens[0]) $($lineTokens[1])"
            $row | Add-Member Period "$([string]::Format("{0,5:N0}", $period.TotalMilliseconds))"
            $row | Add-Member TID $tid
            $row | Add-Member Color $color
            $row | Add-Member FuncName $funcName
            $row | Add-Member Log $log
            $row | Add-Member OldLog $_oldLog
            $_oldLog = $log
            return $row
        }

        if ($OUT_AS_HTML) {
            $htmlRow = "<span style='color: $color;'>$beuatyLog</span>"
            $htmlRow | Out-File $_htmlFilePath -Append
        }
    }

    end {
        if ($SHOW_FUNC_COUNT) {

            $_funcCountDic.Keys | 
                Sort-Object -Descending { 
                $funcName = $_
                $funcCount = $_funcCountDic[$funcName]
                return $funcCount } |
                foreach {
                $funcName = $_
                $funcCount = $_funcCountDic[$funcName]
                $statLog = "$([string]::Format("{0,-100} | {1,10}", $funcName, $funcCount))"
                Write-Host $statLog
            } # foreach
        } # if

        if ($OUT_AS_HTML) {

            $_HTML_FILE_BOTTOM = 
            @"
    </pre>
    </body>
</html>
"@


            $_HTML_FILE_BOTTOM | Out-File -Append $_htmlFilePath
        }


    } # end
}



function _logsloth_str_2_byte_sum {
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)]
        [string]
        $STR
    )
    
    $strBuf = [System.Text.Encoding]::UTF8.GetBytes($STR)
    $byteSum = 0
    
    foreach ($byte in $strBuf) {
        $byteSum += $byte
    }

    return $byteSum
}