簡體   English   中英

以編程方式將 NLog 目標切換到/從異步

[英]Programmatically switch NLog targets to/from async

很長一段時間以來,我一直試圖以編程方式打開和關閉 NLog 異步開關。 我無處可去。 我的代碼似乎可以執行我想要的操作,但是在進行更改后,我根本沒有任何日志記錄。 這是我到目前為止發現的:

當 NLog 配置文件包含async=true ,在運行時,配置文件中的每個目標都有兩個目標( LogManager.Configuration.AllTargets )。 一個是原始目標,以“_wrapped”結尾重命名。 另一個是包裹在AsyncTargetWrapper的原始(現已重命名)目標,並給出了我的原始目標的名稱。

在做任何事情(打開或關閉異步)之前,我首先清除所有的LoggingRules

要關閉異步,我從AsyncTargetWrapper獲取包裝的目標,將其重命名為原始名稱,刪除包裝目標(這似乎也刪除了原始目標),然后重新添加原始目標(現在已被賦予其原始名稱)重命名)。 然后我創建一個LoggingRule並設置適當的日志記錄級別。 最后,我調用LogManager.ReconfigExistingLoggers() 在這一點上,有些東西壞了,因為我不會得到任何日志記錄。

我在打開異步時遵循類似的過程,除了這次,我重命名原始目標,為其創建一個AsyncTargetWrapper ,然后添加新的包裝器目標。 同樣,我為新目標創建一個LoggingRule並設置日志記錄級別。 在這一點上,有些東西壞了,因為我不會得到任何日志記錄。

代碼如下:

LogManager.Configuration.LoggingRules.Clear();

if (async) // turning async ON
{
    foreach (var target in LogManager.Configuration.AllTargets)
    {
        if (!(target is AsyncTargetWrapper))
        {
            string targetName = target.Name;
            // rename the synchronous target to indicate that it is going to be wrapped by another target (an asynchronous wrapper)
            target.Name = $"{target.Name}_wrapped";

            // create an asynchronous target wrpper and give it the name of the synchronous target's original (non-wrapped) name
            AsyncTargetWrapper asyncTarget = new AsyncTargetWrapper(target) { Name = targetName };

            LogManager.Configuration.AddTarget(asyncTarget);

            LoggingRule asyncRule = new LoggingRule("*", asyncTarget);
            if (_minLevel != null && _maxLevel != null)
            {
                asyncRule.EnableLoggingForLevels(_minLevel, _maxLevel);
            }
            else
            {
                foreach (var level in LogLevel.AllLevels.Except(new List<LogLevel>() { LogLevel.Off }))
                {
                    if (Logger.IsEnabled(level)) asyncRule.EnableLoggingForLevel(level);
                }
            }
        }
    }
}
else // turning async OFF
{
    foreach (var target in LogManager.Configuration.AllTargets)
    {
        if (target is AsyncTargetWrapper)
        {
            // get the wrapped (synchronous) target from the wrapper
            Target syncTarget = ((AsyncTargetWrapper)target).WrappedTarget;

            // rename the synchronous target (remove "_wrapped" from the end of its name)
            syncTarget.Name = target.Name.Replace("_wrapped", "");

            // remove the wrapper target
            LogManager.Configuration.RemoveTarget(target.Name);

            LogManager.Configuration.AddTarget(syncTarget);

            // create a rule for the wrapped (synchronous) target
            LoggingRule syncRule = new LoggingRule("*", syncTarget);

            // set the logging level for the synchronous target
            if (_minLevel != null && _maxLevel != null)
            {
                syncRule.EnableLoggingForLevels(_minLevel, _maxLevel);
            }
            else
            {
                foreach (var level in LogLevel.AllLevels.Except(new List<LogLevel>() { LogLevel.Off }))
                {
                    if (Logger.IsEnabled(level)) syncRule.EnableLoggingForLevel(level);
                }
            }
        }
    }
}

LogManager.Configuration.Reload();
LogManager.ReconfigExistingLoggers();

我認為不需要最后兩行,但我嘗試了它們,因為沒有其他任何工作。

必須有正確的方法來翻轉異步標志,但我不知道它是什么。 誰能告訴我怎么做?

我發現了問題。 我過去有一個有效的實現,所以這對我來說非常混亂。 我的舊實現有問題,所以我決定重構它,但在新實現中犯了錯誤。 我遺漏了關鍵的代碼行! 新的日志規則必須在創建后添加到配置中:

LogManager.Configuration.LoggingRules.Add(syncRule);

現在它完全按照我的意願工作。 哇!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM