NLog配置contains过滤器过滤含POCO的日志不生效问题求助
NLog消息内容过滤器不生效问题解决
问题描述
首次配置NLog时,尝试添加过滤规则忽略内容包含POCO的日志,但规则始终不生效,日志输出中仍存在大量匹配内容的告警记录。
初始配置代码
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!
完整初始配置(含ReactiveUI Splat桥接)
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(); }
首次调整后的配置(仍未生效)
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);
问题根因与解决方案
核心问题点
- 规则执行顺序错误:NLog会按
LoggingRules集合的添加顺序依次匹配规则,初始配置中先添加了输出日志的规则,最后才添加过滤规则,日志已经被前面的规则匹配输出,过滤规则没有执行机会。 - 过滤规则未启用日志级别匹配:初始创建的
antiPOCOLogginRule未指定匹配的日志级别,默认不会匹配任何级别的日志,内嵌的过滤器永远不会触发。 - WhenMethodFilter取值范围问题:
WhenMethodFilter的log.Message取的是日志原始模板,若Splat桥接后消息是延迟渲染的,可能出现匹配不到的情况,推荐直接使用NLog内置的条件过滤器处理渲染后的消息。
最终可用配置
public static void Configure() { var config = new NLog.Config.LoggingConfiguration(); // 初始化输出目标 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" }; // 第一步先添加全局过滤规则,放在所有规则最前面 var antiPOCOLogginRule = new LoggingRule("*"); // 匹配所有日志级别 antiPOCOLogginRule.EnableLoggingForLevels(LogLevel.Trace, LogLevel.Fatal); // 使用内置条件过滤器,匹配渲染后的消息内容 antiPOCOLogginRule.Filters.Add(new ConditionBasedFilter() { Condition = "contains(message, 'POCO')", Action = FilterResult.IgnoreFinal }); // 关联所有目标,确保匹配后直接拦截所有目标的输出 antiPOCOLogginRule.Targets.AddRange(new[] { logDebug, logfile, logEvent }); 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); // 应用配置 NLog.LogManager.Configuration = config; Locator.CurrentMutable.UseNLogWithWrappingFullLogger(); }
额外简化方案
如果不需要单独配置规则,也可以直接在NLog全局配置中添加默认过滤器:
config.DefaultFilterResult = FilterResult.Neutral; config.Filters.Add(new ConditionBasedFilter() { Condition = "contains(message, 'POCO')", Action = FilterResult.Ignore });
内容的提问来源于stack exchange,提问作者Tomáš Filip
相关产品推荐
相关产品推荐

