每个插件的 Log4Net 单独配置

Log4Net Separate Configurations per Addin

我正在为我正在编写的几个软件使用 Log4Net,所有这些都是 'parent' 软件的插件。它正在记录,但是日志文件正在混合......我想要一个文件附加程序来记录每个应用程序和会话唯一的文件。现在我正在做这样的事情:

 foreach (ILog log in LogManager.GetCurrentLoggers())
        {
            var logger = (Logger)log.Logger;
            logger.Level = wFSettings.CommonSettings.LogLevel;
            logger.RemoveAllAppenders();

            var ap = new FileAppender()
            {
                Name = "fileWF",
                File = _logPath,
                AppendToFile = true,
                ImmediateFlush = true,
                LockingModel = new FileAppender.MinimalLock(),
                Threshold = Level.All,
            };
            var lp = new PatternLayout() { ConversionPattern = "%date [%thread] %level %logger - %message%newline" };
            lp.ActivateOptions();
            ap.Layout = lp;
            ap.ActivateOptions();
            logger.AddAppender(ap);
            logger.Repository.Configured = true;
        }

在读取程序设置后运行(基本上是它做的第一件事),以便每个应用程序设置的日志级别和文件路径都是正确的。然而,正如您所看到的,它只是删除了所有附加程序并为每个事物添加了自己的附加程序。我在想这就是它混合日志的原因;基本上最后一个获胜。

无论如何我已经四处搜索,我想知道我是否需要以某种方式自定义存储库?不过,我找不到任何关于如何操作的信息。

任何指点将不胜感激。

对于任何想知道遇到这个问题的人,我最终通过创建带有名称的附加程序来解决这个问题。下面是一个插件的配置方法:

    public static void ConfigureLogger(Logger logger)
    {
        // Set actual logger to all and filter appenders
        logger.Level = Level.All;
        var ap = logger.Appenders.ToArray().FirstOrDefault(x => x.Name == "fileWF");

        if (ap != null)
        {
            logger.Appenders.Remove(ap);
        }

        var fa = new FileAppender()
        {
            Name = "fileWF",
            File = _logPath,
            AppendToFile = true,
            ImmediateFlush = true,
            LockingModel = new FileAppender.MinimalLock(),
            Threshold = wFSettings.CommonSettings.LogLevel
        };
        var lp = new PatternLayout() { ConversionPattern = "%date [%thread] %level %logger - %message%newline" };
        lp.ActivateOptions();
        fa.Layout = lp;
        fa.ActivateOptions();
        logger.AddAppender(fa);

#if DEBUG
        var ta = new TraceAppender()
        {
            Name = "traceWF",
            ImmediateFlush = true,
            Threshold = wFSettings.CommonSettings.LogLevel,
            Layout = lp
        };
        logger.AddAppender(ta);
#endif
        logger.Repository.Configured = true;
    }

所以基本上它是创建具有特定名称的附加程序(在本例中为 'fileWF')并将它们添加到记录器,附加程序写入该附加程序的文件。在启动时以及在应用程序中更改日志记录级别时,它运行此:

    internal static void UpdateLogConfig()
    {
        if (wFSettings.CommonSettings == null) return;
        if (!string.IsNullOrEmpty(wFSettings.CommonSettings.CustomLoggerConfig) && !_customLoggerConfigured)
        {
            XmlConfigurator.Configure(new Uri(wFSettings.CommonSettings.CustomLoggerConfig));
            _customLoggerConfigured = true;
            return;
        }

        //No custom config, construct default
        if (string.IsNullOrEmpty(_logPath))
        {
            _logPath = Path.Combine(Props.LogFolder,
                                    "WF Log - " + DateTime.Now.ToString("yyyy-MM-dd_hh_mm_ss") + ".log");
        }

        var commonNamespaces = new List<string>()
        {
            "rdes.license.core",
            "rd.utility",
            "rd.datamodel",
            "rdrestconsumer",
            "rdes.common",
            "rdfilewatcher"
        };

        var ns = typeof(WfUtility).Namespace?.Replace("Shared", string.Empty);

        foreach (ILog log in LogManager.GetCurrentLoggers())
        {
            var logger = (Logger)log.Logger;

            // Ignore KM and SM
            if (ns != null && !logger.Name.StartsWith(ns) &&
                !commonNamespaces.Any(x => logger.Name.ToLower().StartsWith(x))) continue;

            // Set actual logger to all and filter appenders
            ConfigureLogger(logger);
        }
    }

基本上它会查看记录器(根据记录的类型命名)并跳过任何不在我使用的 'common' 命名空间或与实用程序相同的项目级命名空间中的任何内容这运行。对于其他人,它运行确保此插件的附加程序已连接的配置。如果你不想从那些公共库中捕获日志,你可以跳过那部分,但我基本上只过滤到我想记录的命名空间,而不是删除所有附加程序然后添加我的我只是删除和添加我感兴趣的附加程序(这样,如果另一个插件也从共享库中登录,它可以同时显示在两者中)。

似乎有点复杂,但它似乎工作。仍然愿意接受改进建议。