Динамично преконфигурирайте Log4Net

Търся съвети за най-добрия начин за динамично преконфигуриране на нивото на регистриране на Log4Net в моите ASP.NET приложения. Обикновено използвам проста конфигурация, при която root регистраторът дефинира нивото на регистриране по подразбиране, напр.

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

и може да има няколко добавки, всяка с филтри за определяне на нивата на регистриране, които използват.

  1. Първото нещо, което бих искал да мога да направя, е да позволя на администраторите да се свържат с администраторска страница, която им позволява да (a) преглеждат текущото ниво за root регистратора и (b) динамично да го променят. Не искам да използвам "ConfigureAndWatch" и да пиша в конфигурационния файл на диска, защото не искам тези промени да се запазят, когато приложението се рециклира.

  2. След това бих искал да отида по-далеч и на страницата на администратора да мога да покажа TreeView с всички текущи регистратори, които съществуват в приложението, и текущото им ниво на регистриране. И позволява на администратора да може да променя нивото на регистриране избирателно на всяко ниво на йерархията.

Идеята е да създам обща администраторска страница, която мога да поставя във всичките си приложения, която позволява на администраторите избирателно да активират динамично регистриране на ниво DEBUG за целите на отстраняване на неизправности.

Намирам API-тата на Log4Net за малко объркващи, може ли някой да посочи проби или да покаже най-добрия начин за постигане на това.

Актуализация:

И двата отговора са еднакво добри, така че приех първия - благодаря. За да повторя, мога да получа всички текущи регистратори, както следва:

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 е ефективното ниво - същото като Level, ако последното не е null, в противен случай се наследява от родителя.

  • Поне един от върнатите по-горе регистратори ще има основния регистратор като родител, което ми позволява да получа препратка към основния регистратор.

С горното трябва да е възможно да се реконструира йерархията на регистратора.

Актуализация 2

Благодаря отново. Внедрих сървърна контрола на ASP.NET, която показва йерархията на регистратора в TreeView с квадратчета за отметка и позволява на потребителя динамично да променя нивото на регистриране във всеки възел в йерархията. Работи страхотно и ще го поставя на страницата за администриране във всички мои приложения за ASP.NET Web и Web Service!


person Joe    schedule 10.04.2009    source източник


Отговори (3)


Търсите ли нещо подобно (нетестван код):

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

Очевидно можете да извадите името на регистратора и т.н. по същия начин.

person dommer    schedule 10.04.2009
comment
Тествах горния код и открих, че трябва да прегледам всички хранилища и да проверя отново типа. foreach (var repo в LogManager.GetAllRepositories()) foreach (var logger в repo.GetCurrentLoggers().OfType‹Logger›()) logger.Level = ниво; - person Chris Dibbs; 03.01.2011
comment
FYI: Веднъж се натъкнах на проблеми с паралелността, когато използвах API за динамична конфигурация на log4net - изглежда, че не е безопасен за нишки. - person galaktor; 28.04.2011
comment
с коя версия на log4net беше това? Не виждам никакви реализации на ILog, които могат да се прехвърлят към Repository.Hierarchy.Logger - person George Mauer; 04.12.2013
comment
След като току-що направих това, трябваше да използвам logger.Logger, за да работи актьорският състав. - person James Barrass; 19.02.2015

Успешно промених програмно нивото на регистриране на log4net регистратор, но не е очевидно как да го направя от публичния API. Предвид този регистратор:

private readonly log4net.ILog mylogger;

Трябва да направите следната фантастична работа, за да го настроите на Debug:

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

За някои ситуации -- не знам какво причинява това по-сложно изискване -- може да се наложи да следвате допълнителните стъпки, показани в статията log4net и промяна на нивата на регистратора.

person Eddie    schedule 10.04.2009

Може да не е точно това, което искате, но все пак:

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" />
person Yordan Georgiev    schedule 03.05.2009