2009-04-10 13 views
14

Ich bin auf der Suche nach Tipps, wie Log4Net Logging-Level in meinen ASP.NET-Apps am besten rekonfiguriert werden können. Im Allgemeinen verwende ich eine einfache Konfiguration, bei der der Stammlogger die Standardprotokollierungsstufe definiert, z.Log4Net dynamisch rekonfigurieren

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

und es kann mehrere Appen sein, die jeweils mit Filter, um die Protokollebenen verwenden sie zu definieren.

  1. Das erste, was ich in der Lage sein möchten, zu tun wäre, Administratoren zu ermöglichen, auf eine Admin-Seite zu verbinden, die ihnen ermöglicht, (a) das aktuelle Niveau für den Root-Logger anzuzeigen und (b) dynamisch ändern Sie es. Ich möchte "ConfigureAndWatch" nicht verwenden und in die Konfigurationsdatei auf dem Datenträger schreiben, da diese Änderungen nicht beibehalten werden sollen, wenn die Anwendung wiederverwendet wird.

  2. Als nächstes möchte ich weiter gehen und auf einer Admin-Seite in der Lage sein, eine TreeView mit allen aktuellen Loggern, die in der Anwendung existieren, und ihre aktuelle Protokollierungsebene anzuzeigen. Und erlauben Sie dem Administrator, die Protokollierungsstufe auf jeder Ebene der Hierarchie selektiv zu ändern.

Die Idee ist, eine generische Admin-Seite zu erstellen, die ich in all meinen Anwendungen setzen kann, die Administratoren ermöglicht, DEBUG-Level-Protokollierung dynamisch zur Fehlerbehebung selektiv zu aktivieren.

Ich finde die Log4Net APIs ein wenig verwirrend, kann jemand auf Stichproben zeigen oder zeigen Sie den besten Weg, dies zu erreichen.

Update:

Beide Antworten sind gleich gut, also habe ich akzeptiert die erste - danke. Wiederzuschätzen, kann ich alle aktuellen Logger erhalten wie folgt:

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 ist die effektive Ebene - wie Stufe, wenn diese nicht Null ist, andernfalls von dem übergeordneten geerbt.

  • Mindestens einer der Logger, die oben zurückgegeben wurden, wird der Root-Logger als übergeordnetes Element haben, was es mir ermöglicht, einen Verweis auf den Root-Logger zu erhalten.

Mit dem oben genannten sollte es möglich sein, die Logger-Hierarchie zu rekonstruieren.

aktualisieren 2

Nochmals vielen Dank. Ich habe ein ASP.NET-Serversteuerelement implementiert, das die Loggerhierarchie in einem TreeView mit Kontrollkästchen anzeigt, und es dem Benutzer ermöglicht, das Protokollierungslevel an jedem Knoten in der Hierarchie dynamisch zu ändern. Funktioniert hervorragend und ich setze es auf die Admin-Seite in allen meinen ASP.NET Web- und Webservice-Apps!

Antwort

8

Sind Sie für so etwas wie dieses (ungetestet Code) auf der Suche:

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

Man könnte natürlich den Logger Namen herausziehen, usw. auf die gleiche Weise.

+0

ich den obigen Code getestet und festgestellt, dass ich eine Schleife benötigt durch all die Repositories und die doppelte Art überprüfen. foreach (var repo in LogManager.GetAllRepositories()) foreach (var. Loggers in repo.GetCurrentLoggers() OfType ()) logger.Level = Level; –

+0

FYI: Ich habe einmal Probleme mit Parallelität bei der Verwendung der dynamischen log4net-Konfigurations-API festgestellt - es scheint nicht Thread-sicher zu sein. – galaktor

+0

Welche Version von Log4net war das? Ich sehe keine Implementierungen von ILog, die nach Repository castebar sind. Hierarchy.Logger –

3

Ich habe die Protokollierungsstufe eines log4net-Loggers erfolgreich programmgesteuert geändert, aber es ist nicht offensichtlich, wie dies von der öffentlichen API aus geschieht. Vor diesem Logger:

private readonly log4net.ILog mylogger; 

Sie haben die folgende Beinarbeit zu tun, um Debug zu setzen:

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

Für einige Situationen - ich weiß nicht, was diese kompliziertere Anforderung verursacht - Möglicherweise müssen Sie die zusätzlichen Schritte befolgen, die in dem Artikel log4net and changing the logger levels gezeigt werden.

2

vielleicht nicht ganz genau, was Sie wollen, aber:

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