2009-04-10 14 views
14

Estoy buscando sugerencias sobre la mejor manera de reconfigurar dinámicamente el nivel de registro Log4Net en mis aplicaciones ASP.NET. Generalmente utilizo una configuración simple en la que el registrador de raíz define el nivel de registro predeterminado, p.Reconfigurar dinámicamente Log4Net

<log4net> 
    <root> 
    <level value="INFO" /> 
    <appender-ref ref="..." /> 
    <appender-ref ref="..." /> 
    ... etc ...  
    </root> 
    ... etc 

y puede haber varios appenders, cada uno con filtros para definir los niveles de registro que utilizan.

  1. La primera cosa que me gustaría ser capaz de hacerlo sería permitir a los administradores conectarse a una página de administración que les permite (a) ver el nivel actual para el registrador de la raíz y (b) de forma dinámica cambialo. No quiero usar "ConfigureAndWatch" y escribir en el archivo de configuración en el disco porque no quiero que estos cambios persistan cuando la aplicación se recicla.

  2. Siguiente Quisiera ir más allá, y en una página de administración poder mostrar un TreeView con todos los registradores actuales que existen en la aplicación, y su nivel de registro actual. Y permita que el administrador pueda cambiar el nivel de registro de forma selectiva en cualquier nivel de la jerarquía.

La idea es crear una página de administración genérica que puedo poner en todas mis aplicaciones que permite a los administradores activar selectivamente el registro de nivel de depuración de forma dinámica para solucionar problemas.

Creo que las API de Log4Net son un poco confusas, ¿alguien puede señalar muestras o mostrar la mejor manera de lograr esto?

Actualización:

Ambas respuestas son igualmente buenas, así que he aceptado la primera - gracias. Para repetir, puedo conseguir todos los registradores actuales de la siguiente manera:

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 
     ) 
     ); 
} 
  • EffectiveLevel es el nivel efectivo - Igual que el nivel si éste no es nulo, de lo contrario heredada del padre.

  • Al menos uno de los registradores devueltos anteriormente tendrá el registrador de raíz como principal, lo que me permite obtener una referencia al registrador de raíz.

Con lo anterior, debería ser posible reconstruir la jerarquía del registrador.

Actualización 2

Gracias de nuevo. Implementé un control de servidor ASP.NET que muestra la jerarquía del registrador en un TreeView con casillas de verificación, y permite al usuario cambiar dinámicamente el nivel de registro en cualquier nodo de la jerarquía. Funciona muy bien y lo pondré en la página de administración en todas mis aplicaciones de Web y servicios web de ASP.NET.

Respuesta

8

¿Estás buscando algo como esto (código no probado):

foreach (ILog logger in log4net.LogManager.GetCurrentLoggers()) 
{ 
    ((log4net.Repository.Hierarchy.Logger)logger).Level = 
     log4net.Core.Level.Error; 
} 

Usted podría, obviamente, sacar el nombre del registrador, etc de la misma manera.

+0

He probado el código anterior y se encontró que tenía que recorrer todos los repositorios, revisa con el tipo. foreach (repo var en LogManager.GetAllRepositories()) foreach (. Logger var en repo.GetCurrentLoggers() OfType ()) logger.Level = Nivel; –

+0

FYI: una vez me encontré con problemas de simultaneidad cuando uso la API de configuración dinámica de log4net; no parece ser seguro para subprocesos. – galaktor

+0

con que versión de log4net fue esto? No veo ninguna implementación de ILog que pueda convertirse en Repository.Hierarchy.Logger –

3

He cambiado con éxito programáticamente el nivel de registro de un registrador log4net, pero no es obvio cómo hacerlo desde la API pública. Dada esta Logger:

private readonly log4net.ILog mylogger; 

Tienes que hacer el siguiente juego de piernas para configurarlo para depurar:

((log4net.Repository.Hierarchy.Logger)mylogger.Logger).Level = 
log4net.Core.Level.Debug; 

Para algunas situaciones - No sé lo que hace que este requisito más complicado - Es posible que deba seguir los pasos adicionales que se muestran en el artículo log4net and changing the logger levels.

2

puede no ser bastante exactamente lo que quiere, sin embargo:

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" />