Программно переключать цели NLog в / из асинхронного - PullRequest
0 голосов
/ 06 февраля 2020

Я пытался программным образом включить и выключить NLog asyn c в течение длительного времени. Я никуда не денусь. У меня есть код, который, кажется, делает то, что я хочу, но после внесения изменений я вообще не получаю логи. Вот что я нашел до сих пор:

Когда файл конфигурации NLog содержит async=true, тогда во время выполнения у меня будет две цели (LogManager.Configuration.AllTargets) для каждой цели в файле конфигурации. Одним из них является исходная цель, переименованная с «_wrapped» в конце. Другая - это исходная (теперь переименованная) цель, завернутая в AsyncTargetWrapper и получившая имя моей исходной цели.

Прежде чем что-либо делать (чтобы включить или отключить asyn c), сначала я очищаю все LoggingRules.

Чтобы отключить асин c, я получаю обернутую цель от AsyncTargetWrapper, переименовываю ее в исходное имя, удаляю цель обертки (которая, кажется, удаляет оригинал тоже), затем повторно добавьте исходную цель (которой теперь снова было дано ее первоначальное имя). Затем я создаю LoggingRule и устанавливаю соответствующие уровни ведения журнала. Наконец, я звоню LogManager.ReconfigExistingLoggers(). На этом этапе что-то сломано, так как я не буду ничего регистрировать.

Я следую аналогичному процессу при включении asyn c, за исключением того, что я переименую исходную цель, создаю AsyncTargetWrapper для этого, затем добавьте новую цель оболочки. Я снова создаю LoggingRule для новой цели и устанавливаю уровни ведения журнала. На данный момент, что-то сломано, так как я не буду ничего регистрировать.

Код ниже:

LogManager.Configuration.LoggingRules.Clear();

if (async) // turning async ON
{
    foreach (var target in LogManager.Configuration.AllTargets)
    {
        if (!(target is AsyncTargetWrapper))
        {
            string targetName = target.Name;
            // rename the synchronous target to indicate that it is going to be wrapped by another target (an asynchronous wrapper)
            target.Name = $"{target.Name}_wrapped";

            // create an asynchronous target wrpper and give it the name of the synchronous target's original (non-wrapped) name
            AsyncTargetWrapper asyncTarget = new AsyncTargetWrapper(target) { Name = targetName };

            LogManager.Configuration.AddTarget(asyncTarget);

            LoggingRule asyncRule = new LoggingRule("*", asyncTarget);
            if (_minLevel != null && _maxLevel != null)
            {
                asyncRule.EnableLoggingForLevels(_minLevel, _maxLevel);
            }
            else
            {
                foreach (var level in LogLevel.AllLevels.Except(new List<LogLevel>() { LogLevel.Off }))
                {
                    if (Logger.IsEnabled(level)) asyncRule.EnableLoggingForLevel(level);
                }
            }
        }
    }
}
else // turning async OFF
{
    foreach (var target in LogManager.Configuration.AllTargets)
    {
        if (target is AsyncTargetWrapper)
        {
            // get the wrapped (synchronous) target from the wrapper
            Target syncTarget = ((AsyncTargetWrapper)target).WrappedTarget;

            // rename the synchronous target (remove "_wrapped" from the end of its name)
            syncTarget.Name = target.Name.Replace("_wrapped", "");

            // remove the wrapper target
            LogManager.Configuration.RemoveTarget(target.Name);

            LogManager.Configuration.AddTarget(syncTarget);

            // create a rule for the wrapped (synchronous) target
            LoggingRule syncRule = new LoggingRule("*", syncTarget);

            // set the logging level for the synchronous target
            if (_minLevel != null && _maxLevel != null)
            {
                syncRule.EnableLoggingForLevels(_minLevel, _maxLevel);
            }
            else
            {
                foreach (var level in LogLevel.AllLevels.Except(new List<LogLevel>() { LogLevel.Off }))
                {
                    if (Logger.IsEnabled(level)) syncRule.EnableLoggingForLevel(level);
                }
            }
        }
    }
}

LogManager.Configuration.Reload();
LogManager.ReconfigExistingLoggers();

Я не думаю, что эти последние две строки нужны, но я попробовал их, потому что больше ничего не работало.

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

1 Ответ

1 голос
/ 06 февраля 2020

Я нашел проблему. У меня была рабочая реализация в прошлом, так что это все очень сбивало с толку. Были проблемы с моей старой реализацией, поэтому я решил ее реорганизовать, но допустил ошибку в новой реализации. Я пропустил критическую строку кода! Новые правила ведения журналов должны быть добавлены в конфигурацию после их создания:

LogManager.Configuration.LoggingRules.Add(syncRule);

Теперь все работает именно так, как я хочу. Уф!

...