我一直在尝试以编程方式打开和关闭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();
我认为不需要最后两行,但是我尝试了它们,因为其他任何方法都没有用。
必须有正确的方法来翻转异步标志,但我不知道它是什么。谁能告诉我该怎么做?
我发现了问题。过去我有一个可行的实现,所以这一切都让我感到困惑。我的旧实现存在问题,因此我决定对其进行重构,但是在新实现中犯了一个错误。我遗漏了critical行代码!创建新的日志记录规则后,必须将其添加到配置中:
LogManager.Configuration.LoggingRules.Add(syncRule);
现在,它完全可以按照我的意愿工作。哇!