Изменить программный уровень log4net
Это похоже на 650694, но ответа там не было принято, я не могу заставить кого-либо из этих предложений работать вообще, и я подозреваю, что могу быть в несколько иной ситуации.
Я вызываю log4net.Config.XmlConfigurator.Configure(). Но после этой точки в программе я хочу изменить порог регистрации на значение, известное только во время выполнения.
Из другого вопроса я попытался:
((log4net.Repository.Hierarchy.Logger)mylogger.Logger).Level = log4net.Core.Level.Error;
и
var appender = new log4net.Appender.ColoredConsoleAppender();
appender.Layout = new log4net.Layout.PatternLayout(@"%date %-5level %message%newline");
appender.Threshold = log4net.Core.Level.Error;
appender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(appender);
но ни один из них не имеет никакого эффекта: я все еще вижу инструкции консолидации DEBUG и INFO на консоли.
Моя догадка заключается в том, что я добавляю новый appender, который не влияет на appender, объявленный в конфигурации XML (который говорит ему печатать сообщения уровня DEBUG), но пока у меня нет никаких доказательств.
Я уже давно перебираю API-интерфейс log4net, и я просто не вижу его. Есть что-то простое, что мне не хватает?
Ответы
Ответ 1
Ни одно из этих решений, представленных здесь, не работало для меня. Он не менялся в время выполнения
Вот что сработало для меня:
((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Level = Level.Debug;
((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).RaiseConfigurationChanged(EventArgs.Empty);
Вы должны вызвать RaiseConfigurationChanged после внесения изменений в его конфигурацию.
Ответ 2
Наконец, найдено рабочее решение, здесь.
Большие куски были:
- необходимо установить пороговое значение для всех регистраторов, в том числе "невозможно получить по имени" корневой журнал
- необходимо получить уровень из иерархии LevelMap
Большое спасибо Эдди за то, что он задал хорошие острые вопросы, что привело меня к правильным словам. Я никогда бы не подумал об этом.
(Помимо этого: репозиторий, иерархия, регистратор, RootLogger, LevelMap - я и не подозревал, что это возможно даже для того, чтобы сделать библиотеку протоколирования этим комплексом. Она получила около 20 уровней косвенности, что, я уверен, делает ее достаточно гибкой для чего угодно, но делает почти невозможным выполнение простых вещей, таких как "не записывать сообщения над порогом X". Gah!)
Ответ 3
Есть простой способ сделать это:
LogManager.GetRepository().Threshold = Level.Info;
Более подробную информацию можно найти здесь.
Ответ 4
Пробовал все эти ответы, и никто из них не работал. В отладчике я мог видеть, что все уровни регистратора, корневые уровни, пороги были установлены по указанию. Несмотря на это, я не видел изменения уровня журнала в файле, который я записывал.
Затем я обнаружил, что в файле конфигурации элемент appender также указал пороговое значение. Поэтому, когда я хотел изменить уровень на "Отладка", в то время как приложение было настроено на "Предупреждать", например, этот appender не взял дополнительные сообщения, поскольку они были ниже порогового значения. Поэтому я удалил порог из конфигурации appender и просто сохранил конфигурацию уровня.
<root>
<level value="Warn" />
<appender-ref ref="RollingFile" />
</root>
Затем я решил использовать решение Ken для изменения уровня во время выполнения.
Ответ 5
Если это работает для кого-то, вот как я реализовал в своем веб-приложении конечную точку уровня переключения, предоставляемую посредством вызова API, чтобы я мог на лету изменить уровень ведения журнала.
public HttpResponseMessage Post([FromBody] string logLevel)
{
var newLevel = ToggleLogging(logLevel);
// Create your own response here.
return newLevel;
}
И фактическая реализация
private Level ToggleLogging(string logLevel)
{
Level level = null;
if (logLevel != null)
{
level = LogManager.GetRepository().LevelMap[logLevel];
}
if (level == null)
{
level = Level.Warn;
}
ILoggerRepository[] repositories = LogManager.GetAllRepositories();
//Configure all loggers to be at the same level.
foreach (ILoggerRepository repository in repositories)
{
repository.Threshold = level;
Hierarchy hier = (Hierarchy)repository;
ILogger[] loggers = hier.GetCurrentLoggers();
foreach (ILogger logger in loggers)
{
((Logger)logger).Level = level;
}
}
//Configure the root logger.
Hierarchy h = (Hierarchy)LogManager.GetRepository();
Logger rootLogger = h.Root;
rootLogger.Level = level;
return level;
}
Ответ 6
Я искал тот же подход и обнаружил, что последняя версия NLog 3.2.0.0 дает ниже возможность изменить уровень ведения журнала во время выполнения.
LogManager.GlobalThreshold = LogLevel.Debug;
Я думаю, что другой подход может заключаться в использовании LogManager.Configuration
для перезаписывания настроек конфигурации с использованием переменных.
Ответ 7
В моем случае у меня были разные уровни по умолчанию для разных аппендеров, но я хотел переопределить их, если приложение находилось в подробном режиме.
Я использовал следующее:
var log4NetHierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
foreach (var appender in log4NetHierarchy.GetAppenders())
{
if (appender is AppenderSkeleton appenderSkeleton)
{
appenderSkeleton.Threshold = Level.All;
}
}
log4NetHierarchy.RaiseConfigurationChanged(EventArgs.Empty);