You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题根因与解决方案

核心问题点

  1. 规则执行顺序错误:NLog会按LoggingRules集合的添加顺序依次匹配规则,初始配置中先添加了输出日志的规则,最后才添加过滤规则,日志已经被前面的规则匹配输出,过滤规则没有执行机会。
  2. 过滤规则未启用日志级别匹配:初始创建的antiPOCOLogginRule未指定匹配的日志级别,默认不会匹配任何级别的日志,内嵌的过滤器永远不会触发。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:54:03