pf-trace.ps1

function Get-Log_Folder {
    $env:Log_folder
}

function Set-Log_Folder([string]$path, [switch]$default) {
    if ( $default -and -not $path ) {
        $rootScriptPath =  ($env:AGENT_BUILDDIRECTORY) ?? ( Get-ScriptPath -rootScript ) ?? $CommonScriptPath
        $path = Split-Path $rootScriptPath -Parent
        if (-not $path -or $path.StartsWith( $Env:SystemRoot ) ) {
            $path = $env:TEMP
        }
        $path = Join-Path $path 'Logs'
    } 
    if (-not ($path)) {
        $path = $env:TEMP
    }
    New-Folder_EnsureExists -folder $path
    $env:Log_folder = $path
}

function Get-ScriptLine ($level = 1) {
    $stack = Get-PSCallStack
    $callerStackFrame = if ( $stack.Count -gt $level ) { $stack[$level] } else { $stack[-1] }
    $name = $callerStackFrame.ScriptName + ':' + $callerStackFrame.ScriptLineNumber
    return $name
}

function Write-Time {
    param ([switch]$reset)

    $msg = "`n\_ LINE " + ( Get-ScriptLine -level 2 ) 
    $folder = $env:Log_folder 
    $timelog = "$folder\time.log"

    if (-not $Global:Debug_StartTime -or $reset) {
        $Global:Debug_StartTime = [DateTime]::Now
        $Global:Debug_LastTime = $Global:Debug_StartTime
        $msg = "TIME: $Global:Debug_StartTime, START" + $msg
        Write-Host $msg
        Set-Content -Path $timelog -Value $msg | Out-Null
        return 
    }
    $currentTime = [DateTime]::Now
    $totalDuration =  $currentTime - $Global:Debug_StartTime
    $LastDuration =  $currentTime - $Global:Debug_LastTime

    $msg = "TIME: $currentTime , TOTAL DURATION: $totalDuration, LAST DURATION: $LastDuration" + $msg
    Write-Host $msg
    Add-Content -Path $timelog -Value $msg | Out-Null
    $Global:Debug_LastTime = $currentTime
}

function Export-Context([string] $filenamePrefix, [switch]$append, [switch]$PassThru, [switch]$open) {
    $processInfo = @()
    $processInfo += "CommandLine " + ([System.Environment]::CommandLine) 
    $processInfo += "Process CurrentDirectory " + ([System.Environment]::CurrentDirectory)
    $processInfo += "Process Args " + ([System.Environment]::GetCommandLineArgs())
    
    $rootScriptName =  ( Split-Path ( Get-ScriptPath -rootScript ) -Leaf ) | Update-Path_ReplaceFileSpecialChars

    $filenamePrefix = $filenamePrefix + $rootScriptName + '_'

    $processInfo | Export-ToFile ( $filenamePrefix + "ProcessInfo.ps1.log" ) `

    ConvertFrom-EnvironmentVariables_To_Ps1 | Export-ToFile ( $filenamePrefix + "EnvironmentVariables.ps1.log" ) `
        -append:$append.IsPresent -PassThru:$PassThru.IsPresent -open:$open.IsPresent
    ConvertFrom_CallStack_To_String | Export-ToFile ( $filenamePrefix + "CallStack.Log" ) `
        -append:$append.IsPresent -PassThru:$PassThru.IsPresent -open:$open.IsPresent
    ConvertFrom-Variables_To_Ps1 | Export-ToFile ( $filenamePrefix + "Variables.ps1.log" ) `
        -append:$append.IsPresent -PassThru:$PassThru.IsPresent -open:$open.IsPresent
     
}

function ConvertFrom_CallStack_To_String {
    $callStack = Get-PSCallStack
    $result = $callStack | Format-List -GroupBy ScriptName
    $result | Out-String #Required in order to force it to convert as string that renders the info
}

function Initialize-ExportFile([string] $filename, [switch]$append, [switch]$silent ) {
    $logFolder = Get-Log_Folder
    $path = $logFolder ?? $env:TEMP
    $dumpfile = "$path\$filename"
    $parentFolder = Split-Path $dumpfile -Parent
    New-Folder_EnsureExists $parentFolder

    if (-not $silent) {
        $uncFile = Get-UNC_FileName $dumpfile
        write-host "Creating Export '$uncFile'"
    }

    if ( ( Test-Path $dumpfile ) -and -not $append ) {
        $ignoredOutput = Remove-Item $dumpfile
        Write-Verbose $ignoredOutput
    }
    return $dumpfile
}

function Export-ToFile ([string] $filename, [switch]$append, [switch]$PassThru, [switch]$open) {
    begin {
        $dumpfile = Initialize-ExportFile -filename $filename -appemd:$append.IsPresent
    }
    process {
        $_ | Out-File -FilePath $dumpfile -Append
        if ($PassThru) {
            $_
        }
    }
    end {
        if (Test-Path function:\Publish-AzPipeline_File) {
            Publish-AzPipeline_File -path $dumpfile
        }

        if ($open) {
            Show-File $dumpfile
        }
    }
}