首页 > 解决方案 > NLog 包含过滤器未生效

问题描述

我第一次尝试设置 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 日志记录,因为我将 ReactiveUI 用于 WPF。

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

但是由于某种原因,该规则仍然不适用...

标签: c#.netasp.net-corenlog

解决方案


认为你非常接近:

        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 在没有目标时无法检查动态过滤器。

PS 而不是ConditionBasedFilter这样你也可以WhenMethodFilter这样使用:

antiPOCOLogginRule.Filters.Add(new WhenMethodFilter(log => log.FormattedMessage.Contains("POCO") ? FilterResult.IgnoreFinal : FilterResult.Neutral) { Action = FilterResult.IgnoreFinal });

推荐阅读