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 );

【讨论】:

请注意,您也可以将WhenMethodFilterLogEventInfo.FormattedMessage 一起使用,而不是ConditionBasedFilter 您好,我不太确定出了什么问题。请检查已编辑的 OP,我确实做了您建议的事情,但该规则仍然不适用... @TomášFilip 是的,发现 LoggingRule(string ruleName)-constructor 没有分配 LoggerNamePattern。已更新答案。

以上是关于NLog 包含过滤器未生效的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式重新配置 NLog LoggingConfiguration 过滤器

使用 anotar catel nlog 日志记录时无法过滤类名(在 NLog.config 中)

对象可能是“未定义” - 在包含未定义检查的过滤器之后

Fiddler—filter过滤器

Magento 类别页面未包含属性过滤器中的所有产品

PostgreSQL 按日期过滤条目,但包括未包含日期为空的条目