c# - 以编程方式将 NLog 目标切换到/从异步
问题描述
很长一段时间以来,我一直在尝试以编程方式打开和关闭 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);
现在它完全按照我的意愿工作。哇!
推荐阅读
- android-layout - 在 Gridview.count 之后放置一个按钮 - Flutter
- javascript - 多个复选框动作
- asp.net-mvc - 从控制器中的模型访问数据?
- c# - 实体框架数据类
- python-3.x - 如何检查文件是否已关闭?蟒蛇3
- android - 几个位置后的自定义gridview显示不正确的数据
- c# - 如何以 Html 形式绑定 Ajax 数据
- javascript - Error importing component from forked npm package
- ruby-on-rails - Rails webpacker in model
- x11 - How to get mode name using XCB?