mayho33
Goto Top

NLog callsite und callsite-linenumber in Powershell verwenden

Hi @ All

Ich möchte in Powershell Nlog ${callsite} und ${callsite-linenumber} verwenden und habe die Funktionalität aus meinem C#-Projekt übernommen. Leider funktioniert es nicht. Ich bekomme immer nur sowas in meinem Log:
05-06-2020 21:07:01.489 :: (WARN) :: <no type>.CallSite.Target :: 0 :: message

In C# funktioniert das einwandfrei. NLog schreibt, dass auch Powershell bis auf kleinere Einschränkungen voll unterstützt wird. Bin etwas ratlos und wäre froh, wenn jemand den zündenden Hinweis liefern kann.

hier meine Methode und eine kurze Erklärung dazu:
2 Logger. der erste schreibt in ein normales Log und gleichzeitig in die Console. Der zweite wird nur beschrieben, wenn in einem try-catch Fehler auftreten.
Function Initialize-Nlog()
{
    [CmdletBinding()]
    Param 
    (
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, Position=0, ParameterSetName = "INIT")][switch]$Initialize,  
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, Position=1, ParameterSetName = "INIT")][ValidateNotNullOrEmpty()][string]$LoggingFileName,  
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, Position=2,ParameterSetName = "GETLOGGER")][switch]$GetLoggerI,  
        [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, Position=3,ParameterSetName = "GETLOGGER")][switch]$GetLoggerF  
    )

    process {

        if(!$LoggingFileName.ToLower().Contains(".log"))  
        {
            $LoggingFileName += ".log"  
        }

        if($Initialize.IsPresent)
        {
            [Void] [System.Reflection.Assembly]::LoadFile("$env:windir\NLog.dll")  

            $logLayout_NORMAL = [string]::Format("{0}", '${message}')  
            $logLayout_INTERN = [string]::Format("{0} :: {1} :: {2} :: Zeile {3} :: {4}", '${date:format=dd\-MM\-yyyy HH\:mm\:ss\.fff}', '(${uppercase:${level}})', '${callsite}', '${callsite-linenumber}',  '${message} ${exception}')  


            #region NORMAL to Console
            $tagetC_INFO                  = New-Object NLog.Targets.ConsoleRowHighlightingRule
            $tagetC_INFO.Condition        = [NLog.Conditions.ConditionParser]::ParseExpression("level == LogLevel.Info")  
            $tagetC_INFO.ForegroundColor  = [NLog.Targets.ConsoleOutputColor]::White

            $tagetC_DEBUG                 = New-Object NLog.Targets.ConsoleRowHighlightingRule
            $tagetC_DEBUG.Condition       = [NLog.Conditions.ConditionParser]::ParseExpression("level == LogLevel.Debug")  
            $tagetC_DEBUG.ForegroundColor = [NLog.Targets.ConsoleOutputColor]::Green

            $tagetC_WARN                  = New-Object NLog.Targets.ConsoleRowHighlightingRule
            $tagetC_WARN.Condition        = [NLog.Conditions.ConditionParser]::ParseExpression("level == LogLevel.Warn")  
            $tagetC_WARN.ForegroundColor  = [NLog.Targets.ConsoleOutputColor]::Yellow

            $tagetC_TRACE                 = New-Object NLog.Targets.ConsoleRowHighlightingRule
            $tagetC_TRACE.Condition       = [NLog.Conditions.ConditionParser]::ParseExpression("level == LogLevel.Trace")  
            $tagetC_TRACE.ForegroundColor = [NLog.Targets.ConsoleOutputColor]::Gray

            $tagetC_ERROR                 = New-Object NLog.Targets.ConsoleRowHighlightingRule
            $tagetC_ERROR.Condition       = [NLog.Conditions.ConditionParser]::ParseExpression("level == LogLevel.Error")  
            $tagetC_ERROR.ForegroundColor = [NLog.Targets.ConsoleOutputColor]::Red

            $targetC                      = New-Object NLog.Targets.ColoredConsoleTarget
            $targetC.Name                 = "console"  
            $targetC.Layout               = $logLayout_NORMAL

            $targetC.RowHighlightingRules.Add($tagetC_INFO)
            $targetC.RowHighlightingRules.Add($tagetC_DEBUG)
            $targetC.RowHighlightingRules.Add($tagetC_WARN)
            $targetC.RowHighlightingRules.Add($tagetC_TRACE)
            $targetC.RowHighlightingRules.Add($tagetC_ERROR)
            #endregion

            #region INTERN for Internal Error log
            $targetI                         = New-Object NLog.Targets.FileTarget
            $targetI.Name                    = "intern"  
            $targetI.Encoding                = [System.Text.Encoding]::UTF8
            $targetI.FileName                = [System.IO.Path]::Combine($env:LoggingDirectory, "InstallTools_ERROR.log")  
            $targetI.ConcurrentWrites        = $true
            $targetI.ArchiveOldFileOnStartup = $false
            $targetI.KeepFileOpen            = $false
            $targetI.CreateDirs              = $true
            $targetI.DeleteOldFileOnStartup  = $false
            $targetI.MaxArchiveFiles         = 0
            $targetI.Layout                  = $logLayout_INTERN
            #endregion

            #region NORMAL to File
            $targetF                         = New-Object NLog.Targets.FileTarget
            $targetF.Name                    = "file"  
            $targetF.Encoding                = [System.Text.Encoding]::UTF8
            $targetF.ArchiveOldFileOnStartup = $true
            $targetF.ArchiveNumbering        = [NLog.Targets.ArchiveNumberingMode]::Date
            $targetF.FileName                = [System.IO.Path]::Combine($env:LoggingDirectory, $LoggingFileName)
            $targetF.ArchiveDateFormat       = "yyyy.MM.dd HH.mm.ss"  
            $targetF.ArchiveFileName         = [System.IO.Path]::Combine($env:LoggingDirectory, [System.IO.Path]::GetFileNameWithoutExtension($filePath) + '__{#}.log')  
            $targetF.ConcurrentWrites        = $true
            $targetF.ArchiveOldFileOnStartup = $true
            $targetF.KeepFileOpen            = $false
            $targetF.MaxArchiveFiles         = -1
            $targetF.CreateDirs              = $true
            $targetF.Layout                  = $logLayout_NORMAL
            #endregion

            #region LoggingRules
            $LoggingRuleF = New-Object NLog.Config.LoggingRule
            $LoggingRuleF.LoggerNamePattern = "logNormal"  
            $LoggingRuleF.SetLoggingLevels([NLog.LogLevel]::Trace, [NLog.LogLevel]::Fatal)
            $LoggingRuleF.Targets.Add($targetF)
            $LoggingRuleF.Targets.Add($targetC)

            $LoggingRuleI = New-Object NLog.Config.LoggingRule
            $LoggingRuleI.LoggerNamePattern = "logIntern"  
            $LoggingRuleI.SetLoggingLevels([NLog.LogLevel]::Trace, [NLog.LogLevel]::Fatal)
            $LoggingRuleI.Targets.Add($targetI)

            $LoggingConfig = New-Object NLog.Config.LoggingConfiguration
            $LoggingConfig.AddTarget("normal", $targetF)  
            $LoggingConfig.LoggingRules.Add($LoggingRuleF)
            $LoggingConfig.AddTarget("intern", $targetI)  
            $LoggingConfig.LoggingRules.Add($LoggingRuleI)
            #endregion

            [NLog.LogManager]::Configuration = $LoggingConfig
        }

        if($GetLoggerI.IsPresent)
        {
            return [NLog.LogManager]::GetLogger("logIntern")  
        }

        if($GetLoggerF.IsPresent)
        {
            return [NLog.LogManager]::GetLogger("logNormal")  
        }
    }
}

und so initialisiere ich das ganze um zu simmulieren, dass der Fehler in einer Methode auftritt (Beispiel):
function Test-Me() {

[string]$env:Publisher      = 'Citrix'  
[string]$env:DisplayName    = 'WebSpinner'  
[string]$env:DisplayVersion = '1.3.4.675'  


$env:LoggingDirectory = "C:\Logs"  
$env:LogFileName = $($env:Publisher + " " + $env:DisplayName + " " + $env:DisplayVersion)  

Initialize-Nlog -Initialize -LoggingFileName $env:LogFileName
$log = Initialize-Nlog -GetLoggerF
$logError = Initialize-Nlog -GetLoggerI

$log.Info("Eintrag 1")  
$log.Info("Eintrag 2")  

$logError.Debug("blabla")  
$logError.Info("blabla")  
$logError.Warn("blabla")  
$logError.Error("blabla")  
}

Test-Me

Vielen Dank für eure Unterstützung!

Mayho

Content-ID: 577335

Url: https://administrator.de/contentid/577335

Ausgedruckt am: 23.11.2024 um 22:11 Uhr

144260
144260 06.06.2020 aktualisiert um 13:21:09 Uhr
Goto Top
$logLayout_NORMAL = [string]::Format("{0}", '${message}')
$logLayout_INTERN = [string]::Format("{0} :: {1} :: {2} :: Zeile {3} :: {4}", '${date:format=dd\-MM\-yyyy HH\:mm\:ss\.fff}', '(${uppercase:${level}})', '${callsite}', '${callsite-linenumber}', '${message} ${exception}')


Subexpressions $() innerhalb von Single Quotes (') funktionieren in PS nicht, die funktionieren nur innerhalb von Double Quotes (").
Und das date:format geht so auch nicht geht so (get-date -F 'xxxxxxxxxxxxx').
mayho33
mayho33 06.06.2020 um 19:23:48 Uhr
Goto Top
Ich habe keine Fehler. Das Date-Format funktiiniert einwandfrei(siehe oben).

Was nicht funktioniert ist, dass callsite nicht die Methode anzeigt und callsite-linenumber immer 0 ist.
144260
Lösung 144260 06.06.2020 aktualisiert um 20:23:56 Uhr
Goto Top
Uups da habe ich die Klammern verwechselt , sorry.

Die Abhängigkeiten die hier zusätzlich eingebunden werden fehlen bei dir ...
https://gist.github.com/dbl4ck/7e392efd8357a1f422ca7d115b068234
Vielleicht wird eine/mehrere davon noch benötigt.
mayho33
mayho33 08.06.2020 aktualisiert um 17:24:24 Uhr
Goto Top
Zitat von @144260:
Die Abhängigkeiten die hier zusätzlich eingebunden werden fehlen bei dir ...
https://gist.github.com/dbl4ck/7e392efd8357a1f422ca7d115b068234
Vielleicht wird eine/mehrere davon noch benötigt.

Eine Schande, dass NLog Powershell immer noch nicht voll unterstützt und externe Tools notwendig sind. Ist ja nicht so, dass PS noch besonders jung wäre und die Verbreitung ist ebenfalls hoch.

Danke jedenfalls! Werde das alsbald ausprobieren.

Bei Durchsicht meines Log Layouts ist mir aber tatsächlich einen unnötige Klammerung aufgefallen:

Das...
'(${uppercase:${level}})'  

...funktioniert auch so:
'${uppercase:${level}}'