Отдельные конфигурации Log4Net для каждого дополнения

Я использую Log4Net для нескольких программ, которые я пишу, всего того, что является надстройками к «родительскому» программному обеспечению. Это ведение журнала, однако файлы журнала перемешиваются ... Я хотел бы иметь приложение для файлов, которое регистрирует файлы, уникальные для каждого приложения и сеанса. Прямо сейчас делаю что-то вроде этого:

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

Это выполняется после считывания настроек программы (в основном это первое, что она делает), чтобы уровень журнала и путь к файлу соответствовали настройкам приложения. Однако, как вы можете видеть, он просто удаляет все дополнения и добавляет к каждой вещи свои собственные. Я думаю, поэтому он смешивает журналы; в основном побеждает последний.

В любом случае, я искал вокруг, и мне интересно, нужно ли мне как-то настраивать репозиторий? Я не мог найти ничего, что указывало бы на то, как это сделать.

Приветствуются любые указатели.


person sfaust    schedule 28.08.2019    source источник


Ответы (1)


Для тех, кто задается вопросом, что с этим сталкивается, я решил решить эту проблему, создав приложения с именами. Вот способ настройки одного надстройки:

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

В основном он просматривает регистраторы (названные в соответствии с типом, для которого они регистрируются) и пропускает те, которые не находятся в «общих» пространствах имен, которые я использую, или в том же пространстве имен уровня проекта, что и утилита, в которой это выполняется. Для остальных он запускает конфигурацию, которая гарантирует, что приложение для этого дополнения подключено. Если вы не хотите собирать журналы из этих общих библиотек, вы можете пропустить эту часть, но я в основном фильтрую только те пространства имен, которые хочу регистрировать, и вместо того, чтобы удалять все приложения, а затем добавлять свои, я просто удаляю и добавляю приложения, которые меня интересуют (таким образом, если другое дополнение также ведет журнал из общей библиотеки, оно может отображаться в обоих).

Кажется немного сложным, но вроде работает. Тем не менее был бы открыт для предложений по улучшению.

person sfaust    schedule 07.09.2019