Динамически перенастроить Log4Net
Я ищу советы по наилучшему способу реконфигурировать уровень ведения журнала Log4Net динамически в моих приложениях ASP.NET. Обычно я использую простую конфигурацию, в которой корневой регистратор определяет уровень ведения журнала по умолчанию, например.
<log4net>
<root>
<level value="INFO" />
<appender-ref ref="..." />
<appender-ref ref="..." />
... etc ...
</root>
... etc
и может быть несколько приложений, каждый из которых имеет фильтры для определения уровней ведения журнала, которые они используют.
-
Первое, что я хотел бы сделать, это разрешить администраторам подключаться к странице администратора, которая позволяет им (a) просматривать текущий уровень для корневого регистратора и (b) динамически изменять Это. Я не хочу использовать "ConfigureAndWatch" и записывать в файл конфигурации на диске, потому что я не хочу, чтобы эти изменения сохранялись при повторном использовании приложения.
-
Далее я хотел бы перейти дальше, и на странице администратора можно отобразить TreeView со всеми текущими Loggers, которые существуют в приложении, и их текущий уровень ведения журнала. И позвольте администратору иметь возможность изменять уровень ведения журнала выборочно на любом уровне иерархии.
Идея состоит в том, чтобы создать общую страницу администратора, которую я могу разместить во всех моих приложениях, что позволяет администраторам выборочно включать протоколы уровня DEBUG динамически для устранения неполадок.
Я нахожу API Log4Net несколько запутанным, может ли кто-нибудь указать на образцы или показать лучший способ достичь этого.
Update:
Оба ответа одинаково хороши, поэтому я принял первое - спасибо. Чтобы повторить, я могу получить все текущие регистраторы следующим образом:
foreach (log4net.ILog log in log4net.LogManager.GetCurrentLoggers())
{
log4net.Repository.Hierarchy.Logger logger =
(log4net.Repository.Hierarchy.Logger)log.Logger;
Debug.WriteLine(
String.Format("{0} Parent {1} Level {2} EffectiveLevel {3}<br>",
logger.Name,
logger.Parent.Name,
logger.Level == null ? "<null>" : logger.Level.Name,
logger.EffectiveLevel
)
);
}
-
Эффективный уровень - это эффективный уровень - тот же, что и Level, если последний не является нулевым, иначе унаследован от родителя.
-
Как минимум один из вышеперечисленных регистраторов будет иметь корневой регистратор как родительский, что позволит мне получить ссылку на корневой журнал.
С вышесказанным следует восстановить иерархию регистратора.
Обновление 2
Еще раз спасибо. Я реализовал серверный элемент управления ASP.NET, который отображает иерархию регистратора в TreeView с флажками и позволяет пользователю динамически изменять уровень ведения журнала на любом node в иерархии. Отлично работает, и я буду размещать его на странице администратора во всех приложениях ASP.NET для веб-и веб-сервисов!
Ответы
Ответ 1
Вы ищете что-то вроде этого (непроверенный код):
foreach (ILog logger in log4net.LogManager.GetCurrentLoggers())
{
((log4net.Repository.Hierarchy.Logger)logger).Level =
log4net.Core.Level.Error;
}
Вы могли бы явно вытащить имя регистратора и т.д. таким же образом.
Ответ 2
Я успешно программным образом изменил уровень ведения журнала журнала log4net, но это не очевидно, как это сделать из общедоступного API. Учитывая этот регистратор:
private readonly log4net.ILog mylogger;
Вы должны сделать следующие причудливые работы, чтобы настроить его на Debug:
((log4net.Repository.Hierarchy.Logger)mylogger.Logger).Level =
log4net.Core.Level.Debug;
В некоторых ситуациях - я не знаю, что вызывает это более сложное требование - вам может потребоваться выполнить дополнительные шаги, показанные в статье log4net и изменение уровней журналов.
Ответ 3
Может быть, совсем не совсем то, что вы хотите:
using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using log4net.Config;
using NUnit.Framework;
namespace ExampleConsoleApplication
{
enum DebugLevel : int
{
Fatal_Msgs = 0 ,
Fatal_Error_Msgs = 1 ,
Fatal_Error_Warn_Msgs = 2 ,
Fatal_Error_Warn_Info_Msgs = 3 ,
Fatal_Error_Warn_Info_Debug_Msgs = 4
}
class TestClass
{
private static readonly ILog logger =
LogManager.GetLogger ( typeof ( TestClass ) );
static void Main ( string[] args )
{
TestClass objTestClass = new TestClass ();
Console.WriteLine ( " START " );
int shouldLog = 4; //CHANGE THIS FROM 0 TO 4 integer to check the functionality of the example
//0 -- prints only FATAL messages
//1 -- prints FATAL and ERROR messages
//2 -- prints FATAL , ERROR and WARN messages
//3 -- prints FATAL , ERROR , WARN and INFO messages
//4 -- prints FATAL , ERROR , WARN , INFO and DEBUG messages
string srtLogLevel = String.Empty ;
switch (shouldLog)
{
case (int)DebugLevel.Fatal_Msgs :
srtLogLevel = "FATAL";
break;
case (int)DebugLevel.Fatal_Error_Msgs:
srtLogLevel = "ERROR";
break;
case (int)DebugLevel.Fatal_Error_Warn_Msgs :
srtLogLevel = "WARN";
break;
case (int)DebugLevel.Fatal_Error_Warn_Info_Msgs :
srtLogLevel = "INFO";
break;
case (int)DebugLevel.Fatal_Error_Warn_Info_Debug_Msgs :
srtLogLevel = "DEBUG" ;
break ;
default:
srtLogLevel = "FATAL";
break;
}
objTestClass.SetLogingLevel ( srtLogLevel );
objTestClass.LogSomething ();
Console.WriteLine ( " END HIT A KEY TO EXIT " );
Console.ReadLine ();
} //eof method
/// <summary>
/// Activates debug level
/// </summary>
/// <sourceurl>http://geekswithblogs.net/rakker/archive/2007/08/22/114900.aspx</sourceurl>
private void SetLogingLevel ( string strLogLevel )
{
string strChecker = "WARN_INFO_DEBUG_ERROR_FATAL" ;
if (String.IsNullOrEmpty ( strLogLevel ) == true || strChecker.Contains ( strLogLevel ) == false)
throw new Exception ( " The strLogLevel should be set to WARN , INFO , DEBUG ," );
log4net.Repository.ILoggerRepository[] repositories = log4net.LogManager.GetAllRepositories ();
//Configure all loggers to be at the debug level.
foreach (log4net.Repository.ILoggerRepository repository in repositories)
{
repository.Threshold = repository.LevelMap[ strLogLevel ];
log4net.Repository.Hierarchy.Hierarchy hier = (log4net.Repository.Hierarchy.Hierarchy)repository;
log4net.Core.ILogger[] loggers = hier.GetCurrentLoggers ();
foreach (log4net.Core.ILogger logger in loggers)
{
( (log4net.Repository.Hierarchy.Logger)logger ).Level = hier.LevelMap[ strLogLevel ];
}
}
//Configure the root logger.
log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository ();
log4net.Repository.Hierarchy.Logger rootLogger = h.Root;
rootLogger.Level = h.LevelMap[ strLogLevel ];
}
private void LogSomething ()
{
#region LoggerUsage
DOMConfigurator.Configure (); //tis configures the logger
logger.Debug ( "Here is a debug log." );
logger.Info ( "... and an Info log." );
logger.Warn ( "... and a warning." );
logger.Error ( "... and an error." );
logger.Fatal ( "... and a fatal error." );
#endregion LoggerUsage
}
} //eof class
} //eof namespace
#region TheAppConfig
/*
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<param name="File" value="LogTest2.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Header] \r\n" />
<param name="Footer" value="[Footer] \r\n" />
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<foreColor value="White" />
<backColor value="Red, HighIntensity" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.2.10.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=ysg;initial catalog=DBGA_DEV;integrated security=true;persist security info=True;" />
<commandText value="INSERT INTO [DBGA_DEV].[ga].[tb_Data_Log] ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout" value="%thread" />
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout" value="%level" />
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout" value="%logger" />
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout" value="%messag2e" />
</parameter>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="AdoNetAppender" />
<appender-ref ref="ColoredConsoleAppender" />
</root>
</log4net>
</configuration>
*/
#endregion TheAppconfig
//this is the xml added replace here your log4net and Nunit paths
//<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
// <SpecificVersion>False</SpecificVersion>
// <HintPath>..\..\..\Log4Net\log4net-1.2.10\bin\net\2.0\release\log4net.dll</HintPath>
//</Reference>
//<Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />