NLog 包含过滤器未生效
Posted
技术标签:
【中文标题】NLog 包含过滤器未生效【英文标题】:NLog contains filter is not taking into effect 【发布时间】:2021-12-18 11:55:33 【问题描述】:我第一次尝试设置 NLog,但我无法让过滤器工作。
var antiPOCOLogginRule = new LoggingRule("*");
antiPOCOLogginRule.Filters.Add(new ConditionBasedFilter()
Condition = "contains('$message','POCO')",
Action = FilterResult.IgnoreFinal
);
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logDebug);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
config.AddRule(LogLevel.Warn, LogLevel.Fatal, logEvent);
config.LoggingRules.Add(antiPOCOLogginRule);
但输出仍然给我这个:
2021-11-04 09:09:07.8885|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.Views.ReorderLogsView property Logs_ItemsControl is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 09:09:07.9675|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.Views.SerialInputView property TextBox_SerialNumber is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 09:09:07.9953|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.Views.SerialInputView property ProgressBar_ProccessingSerialNumber is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 09:09:08.0058|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.Views.SerialInputView property Border_LastMessage is a POCO type and won't send change notifications, WhenAny will only return a single value!
2021-11-04 09:09:08.0271|WARN|ReactiveUI.POCOObservableForProperty|The class KardexTerminal_PDA_WPF.Views.SerialInputView property TextBlock_LastMessage is a POCO type and won't send change notifications, WhenAny will only return a single value!
我一定遗漏了一些非常明显的东西,但我不确定它是什么。 (这只是我要添加的过滤器,所以不会有任何干扰)
为了完整性,我正在添加整个日志记录配置。
我正在使用 Splat 日志记录,因为我正在为 WPF 使用 ReactiveUI。
public static void Configure()
var config = new NLog.Config.LoggingConfiguration();
var antiPOCOLogginRule = new LoggingRule("*");
antiPOCOLogginRule.Filters.Add(new ConditionBasedFilter()
Condition = "contains('$message','POCO')",
Action = FilterResult.IgnoreFinal
);
var logfile = new NLog.Targets.FileTarget("logfile")
FileName = "log.txt",
NetworkWrites = true,
OptimizeBufferReuse= true,
ArchiveAboveSize = 5000000,
ArchiveNumbering = ArchiveNumberingMode.Date,
MaxArchiveFiles = 5,
ArchiveOldFileOnStartup = true,
ConcurrentWrites = true
;
var logDebug = new NLog.Targets.DebuggerTarget("Debug");
var logEvent = new NLog.Targets.EventLogTarget("EventLog") OptimizeBufferReuse = true, Log = "Application" ;
// Rules for mapping loggers to targets
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logDebug);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
config.AddRule(LogLevel.Warn, LogLevel.Fatal, logEvent);
antiPOCOLogginRule.Targets.Add(logfile);
antiPOCOLogginRule.Targets.Add(logDebug);
antiPOCOLogginRule.Targets.Add(logEvent);
config.LoggingRules.Add(antiPOCOLogginRule);
// Apply config
NLog.LogManager.Configuration = config;
Locator.CurrentMutable.UseNLogWithWrappingFullLogger();
编辑----
根据 Rolf Kristensen 的反馈,我确实将我的代码改写为:
var antiPOCOLogginRule = new LoggingRule("*");
antiPOCOLogginRule.EnableLoggingForLevels(LogLevel.Trace, LogLevel.Fatal);
antiPOCOLogginRule.Filters.Add(new WhenMethodFilter(log => log.Message.Contains("POCO") ? FilterResult.IgnoreFinal : FilterResult.Neutral));
antiPOCOLogginRule.Targets.Add(logfile);
antiPOCOLogginRule.Targets.Add(logDebug);
antiPOCOLogginRule.Targets.Add(logEvent);
// Rules for mapping loggers to targets
config.LoggingRules.Add(antiPOCOLogginRule);
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logDebug);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
config.AddRule(LogLevel.Warn, LogLevel.Fatal, logEvent);
但由于某种原因,该规则仍然不适用……
【问题讨论】:
您对config.AddRule
的 3 次调用可确保所有记录器直接写入其目标,而不考虑为 antiPOCOLogginRule
应用的任何过滤。
哎呀,我真的不知道如何解决这个问题,你能指导我一下吗?
【参考方案1】:
觉得你很亲密:
var antiPOCOLogginRule = new LoggingRule() FilterDefaultAction = FilterResult.Neutral ;
antiPOCOLogginRule.LoggerNamePattern = "*";
antiPOCOLogginRule.EnableLoggingForLevels(NLog.LogLevel.Trace, NLog.LogLevel.Fatal);
antiPOCOLogginRule.Filters.Add(new ConditionBasedFilter()
Condition = "contains('$message','POCO')",
Action = FilterResult.IgnoreFinal
);
antiPOCOLogginRule.Targets.Add(new NLog.Targets.NullTarget()); // Dynamic filters requires a target
// Rules for mapping loggers to targets
config.LoggingRules.Add(antiPOCOLogginRule); // First filter final
config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logDebug);
config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
config.AddRule(NLog.LogLevel.Warn, NLog.LogLevel.Fatal, logEvent);
为antiPOCOLogginRule
更新了以下内容:
EnableLoggingForLevels
使其实际上匹配日志级别
添加LoggerNamePattern
,这样它就会真正匹配记录器
添加NullTarget
,因为NLog在没有目标时无法检查动态过滤器。
附:除了ConditionBasedFilter
,你也可以像这样使用WhenMethodFilter
:
antiPOCOLogginRule.Filters.Add(new WhenMethodFilter(log => log.FormattedMessage.Contains("POCO") ? FilterResult.IgnoreFinal : FilterResult.Neutral) Action = FilterResult.IgnoreFinal );
【讨论】:
请注意,您也可以将WhenMethodFilter
与LogEventInfo.FormattedMessage
一起使用,而不是ConditionBasedFilter
。
您好,我不太确定出了什么问题。请检查已编辑的 OP,我确实做了您建议的事情,但该规则仍然不适用...
@TomášFilip 是的,发现 LoggingRule(string ruleName)
-constructor 没有分配 LoggerNamePattern。已更新答案。以上是关于NLog 包含过滤器未生效的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式重新配置 NLog LoggingConfiguration 过滤器