2009-05-19 7 views
13

Próbuję skonfigurować Log4Net wyłącznie za pomocą kodu, ale kiedy zrobiłem z minimalną konfiguracją, zostałem zalany przez rejestrowanie wiadomości od NHibernate i płynnego interfejsu.Konfiguracja czystego kodu log4net z filtrem w C#

To, co próbuję zrobić, jest proste. Poinformuj Log4Net, aby wyświetlał mi tylko komunikaty logów z mojej pojedynczej klasy. I bawił się wokół trochę, ale nie mogę tego rozgryźć ...

Czy ktoś może pomóc, myślę, że poniższy kod ilustruje mój pomysł:

var filter = new log4net.Filter.LoggerMatchFilter(); 
filter.LoggerToMatch = typeof(DatabaseDirectory).ToString(); 
filter.AcceptOnMatch = false; 

var x = new log4net.Appender.ConsoleAppender(); 
x.Layout = new log4net.Layout.SimpleLayout(); 
x.AddFilter(filter); 

log4net.Config.BasicConfigurator.Configure(x); 

Ok, dzięki za pomoc, ale nie tutaj musi być jakiś problem. Ale podchodzę bliżej. Wypróbowałem konfigurację XML, która ma znacznie więcej dokumentacji. I udało mi się osiągnąć pożądany rezultat przy użyciu następującej konfiguracji XML. Musi być jakaś błędna konfiguracja w powyższej wersji "czystego kodu".

Poniższa konfiguracja XML zawiera "poprawne" dane wyjściowe, które nie są takie same, jak powyższy kod konfiguracji. Ktoś widzi różnicę?

<log4net> 
<root> 
    <level value="DEBUG" /> 
    <appender-ref ref="ConsoleAppender" /> 
</root> 
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" > 
    <filter type="log4net.Filter.LoggerMatchFilter"> 
    <loggerToMatch value="Examples.FirstProject.Entities.DatabaseDirectory"/> 
    </filter> 
    <filter type="log4net.Filter.DenyAllFilter" /> 
    <layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="[%C.%M] %-5p %m%n" /> 
    </layout> 
</appender> 

+0

Początkowo swoją konfiguracja wygląda perfekcyjnie. Czy próbowałeś logować się bez usługi NHibernate, tylko dwa z własnych rejestratorów i sprawdzić, czy jeden jest akceptowany, a jeden odmowy? W ten sposób możesz przynajmniej wykluczyć NHibernate. –

Odpowiedz

9

I zdobione .. Czasami, po prostu pisząc ją otwiera oczy ...

 var filter = new log4net.Filter.LoggerMatchFilter(); 
     filter.LoggerToMatch = typeof(DatabaseDirectory).ToString(); 
     filter.AcceptOnMatch = true; 

     var filterDeny = new log4net.Filter.DenyAllFilter(); 


     var x = new log4net.Appender.ConsoleAppender(); 
     x.Layout = new log4net.Layout.SimpleLayout(); 
     x.AddFilter(filter); 
     x.AddFilter(filterDeny); 

     log4net.Config.BasicConfigurator.Configure(x); 

zobaczyć, co brakowało :-) Filtr denyall !!

Niektóre dalsze przykłady kodu:

public static void AllToConsoleSetup() 
    { 
     var x = new log4net.Appender.ConsoleAppender { Layout = new log4net.Layout.SimpleLayout() }; 
     log4net.Config.BasicConfigurator.Configure(x); 
     SetupDone = true; 
    } 


    public static void ShowOnlyLogOf(Type t) 
    { 
     var filter = new log4net.Filter.LoggerMatchFilter {LoggerToMatch = t.ToString(), AcceptOnMatch = true}; 
     var filterDeny = new log4net.Filter.DenyAllFilter(); 
     var x = new log4net.Appender.ConsoleAppender {Layout = new log4net.Layout.SimpleLayout()}; 
     x.AddFilter(filter); 
     x.AddFilter(filterDeny); 

     log4net.Config.BasicConfigurator.Configure(x); 
     SetupDone = true; 
    } 

naprawdę brzydki, ale pracujące (śruby ją podświetlić, nie przegap ostatnie linijki):

 public static void DefaultSetup() 
    { 
     // AllToConsoleSetup(); 
     XmlConfigurator.Configure(XmlSetup()); 
     // DbConfig(); 

    } 


    private static Stream XmlSetup() 
    { 
     const string x = @" <log4net> 
<root> 

    <level value=""ALL"" /> 
    <appender-ref ref=""AdoNetAppender""> 

    </appender-ref> 
</root> 


<appender name=""AdoNetAppender"" type=""log4net.Appender.AdoNetAppender""> 
    <bufferSize value=""1"" /> 
    <connectionType value=""System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" /> 
    <connectionString value=""data source=Christian-PC\SQLEXPRESS;initial catalog=log4net_2;integrated security=false;persist security info=True;User ID=log4net;Password=XXXX"" /> 
    <commandText value=""INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)"" /> 
    <parameter> 
    <parameterName value=""@log_date"" /> 
    <dbType value=""DateTime"" /> 
    <layout type=""log4net.Layout.RawTimeStampLayout"" /> 
    </parameter> 
    <parameter> 
    <parameterName value=""@thread"" /> 
    <dbType value=""String"" /> 
    <size value=""655"" /> 
    <layout type=""log4net.Layout.PatternLayout""> 
     <conversionPattern value=""%thread"" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value=""@log_level"" /> 
    <dbType value=""String"" /> 
    <size value=""50"" /> 
    <layout type=""log4net.Layout.PatternLayout""> 
     <conversionPattern value=""%level"" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value=""@logger"" /> 
    <dbType value=""String"" /> 
    <size value=""655"" /> 
    <layout type=""log4net.Layout.PatternLayout""> 
     <conversionPattern value=""%logger"" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value=""@message"" /> 
    <dbType value=""String"" /> 
    <size value=""4000"" /> 
    <layout type=""log4net.Layout.PatternLayout""> 
     <conversionPattern value=""%message"" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value=""@exception"" /> 
    <dbType value=""String"" /> 
    <size value=""2000"" /> 
    <layout type=""log4net.Layout.ExceptionLayout"" /> 
    </parameter> 
    <filter type=""log4net.Filter.LoggerMatchFilter""> 
    <param name=""LoggerToMatch"" value=""Ruppert"" /> 
    </filter> 
    <filter type=""log4net.Filter.DenyAllFilter""> 
    </filter> 
</appender> 
</log4net>"; 
     return new MemoryStream(ASCIIEncoding.Default.GetBytes(x)); 
    } 
+0

Christian - czy mógłbyś wskazać jakieś zasoby do konfiguracji log4netu używając tylko kodu (który mógłby użyć nowicjusz log4net)? –

+0

Niestety, nie masz prawdziwego linku tutaj. Spróbuj wyszukać fragmenty kodu, takie jak Layout.SimpleLayout ... Dodam trochę więcej kodu w poście powyżej .. –

+0

Dzięki Christian, to naprawdę przydatne, aby zacząć.Bardzo doceniane. –

5

Oto anohter sposób konfigurowania log4net z XML za pomocą kodu przy użyciu XmlDocument, aby załadować xml. Różnica od przykładu Christiana polega na tym, że używam przeciążenia XmlConfigurator.Configure, które przyjmuje jako parametr XmlElement. Użyłem również pojedynczych znaczników zamiast podwójnego podwójnego cudzysłowu. Podsumowując, uważam, że jest to najmniejsza odrobina czystości.

string xml = 
    @"<log4net> 
    <appender name='file1' type='log4net.Appender.RollingFileAppender'> 
     <!-- Log file locaation --> 
     <param name='File' value='log4net.log'/> 
     <param name='AppendToFile' value='true'/> 
     <!-- Maximum size of a log file --> 
     <maximumFileSize value='2KB'/> 
     <!--Maximum number of log file --> 
     <maxSizeRollBackups value='8'/> 
     <!--Set rolling style of log file --> 
     <param name='RollingStyle' value='Composite'/> 
     <param name='StaticLogFileName' value='false'/> 
     <param name='DatePattern' value='.yyyy-MM-dd.lo\g'/> 
     <layout type='log4net.Layout.PatternLayout'> 
     <param name='ConversionPattern' value='%d [%t] %-5p %m%n'/> 
     </layout> 
    </appender> 

    <!-- Appender layout fix to view in console--> 
    <appender name='console' type='log4net.Appender.ConsoleAppender'> 
     <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 %m%n'/> 
     </layout> 
    </appender> 

    <appender name='debug' type='log4net.Appender.DebugAppender'> 
     <layout type='log4net.Layout.PatternLayout'> 
     <param name='ConversionPattern' value='%d [%t] %logger %-5p %m%n'/> 
     </layout> 
    </appender> 
    <root> 
     <level value='INFO'/> 
     <!-- 
      Log level priority in descending order: 

      FATAL = 1 show log -> FATAL 
      ERROR = 2 show log -> FATAL ERROR 
      WARN = 3 show log -> FATAL ERROR WARN 
      INFO = 4 show log -> FATAL ERROR WARN INFO 
      DEBUG = 5 show log -> FATAL ERROR WARN INFO DEBUG 
      --> 
     <!-- To write log in file --> 
     <appender-ref ref='debug'/> 
     <appender-ref ref='file1'/> 
    </root> 

    </log4net>"; 

    // 
    // Use XmlDocument to load the xml string then pass the DocumentElement to 
    // XmlConfigurator.Configure. 
    // 
    XmlDocument doc = new XmlDocument(); 
    doc.LoadXml(xml); 

    log4net.Config.XmlConfigurator.Configure(doc.DocumentElement); 
4

Poniższe kody dotyczą sposobu konfigurowania AdoNetAppender w kodach. Jeśli chcesz dodać filtr, musisz dodać instancję filtru do instancji aplikacji dostarczającej w metodzie GetAppender(). Aby używać rejestratora w aplikacji, zaleca się stosowanie Dependency Injection w celu odizolowania implementacji rejestratora i interfejsu. Ponadto, użyj koncepcji zasięgu DI, aby uczynić ją unikalną w celu uniknięcia rekreacji obiektów. Uwaga: Klasa CrmConfigHelper służy do uzyskiwania dostępu do sekcji konfiguracji aplikacji pliku konfiguracji aplikacji.

Próbki kody są pokazane poniżej

public sealed class SqlLogger:ILogger 
{ 
    private ILog _logger; 
    public SqlLogger() 
    {    
     log4net.Config.BasicConfigurator.Configure(GetAppender()); 
     this._logger = log4net.LogManager.GetLogger(CrmConfigHelper.GetString(Constants.LOG4NET_LOGGER_NAME)); 
    } 

    private log4net.Appender.AdoNetAppender GetAppender() 
    {    
     log4net.Appender.AdoNetAppender appender = new log4net.Appender.AdoNetAppender(); 
     appender.ConnectionType = CrmConfigHelper.GetString(Constants.LOG4NET_CONNECTION_TYPE); 
     appender.ConnectionString = CrmConfigHelper.GetString(Constants.LOG4NET_DB_CONNECTION); 
     appender.BufferSize = CrmConfigHelper.getInteger(Constants.LOG4NET_BUFFER_SIZE); 
     appender.CommandText = "INSERT INTO [EventLog] ([Date],[HostName],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @hostname, @log_level, @logger, @message,@exception)"; 
     appender.CommandType = System.Data.CommandType.Text; 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() { 
      ParameterName = "@log_date", 
      DbType = System.Data.DbType.DateTime, 
      Size = 100, 
      Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}")) as IRawLayout 
     }); 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() 
     { 
      ParameterName = "@hostname", 
      DbType = System.Data.DbType.String, 
      Size = 50, 
      Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%property{log4net:HostName}")) as IRawLayout 
     }); 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() 
     { 
      ParameterName = "@log_level", 
      DbType = System.Data.DbType.String, 
      Size = 50, 
      Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%level")) as IRawLayout 
     }); 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() 
     { 
      ParameterName = "@logger", 
      DbType = System.Data.DbType.String, 
      Size = 50, 
      Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%logger")) as IRawLayout 
     }); 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() 
     { 
      ParameterName = "@message", 
      DbType = System.Data.DbType.String, 
      Size = 4000, 
      Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%message")) as IRawLayout 
     }); 
     appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() 
     { 
      ParameterName = "@exception", 
      DbType = System.Data.DbType.String, 
      Size = 2000, 
      Layout = new RawLayoutConverter().ConvertFrom(new ExceptionLayout()) as IRawLayout 
     }); 

     appender.ActivateOptions(); 
     return appender; 
    } 

    public void Error(Message context) 
    { 
     _logger.Error(context.ToJsonString()); 
    } 

    public void Error(Message context, Exception exception) 
    { 
     _logger.Error(context.ToJsonString(), exception); 
    } 

    public void Warn(Message context) 
    { 
     _logger.Warn(context.ToJsonString()); 
    } 

    public void Warn(Message context, Exception exception) 
    { 
     _logger.Warn(context.ToJsonString(), exception); 
    } 

    public void Info(Message context) 
    { 
     _logger.Info(context.ToJsonString()); 
    } 

    public void Info(Message context, Exception exception) 
    { 
     _logger.Info(context.ToJsonString(), exception); 
    } 
} 

public interface ILogger 
{ 
    void Error(Message context); 
    void Error(Message context, Exception exception); 
    void Warn(Message context); 
    void Warn(Message context, Exception exception); 
    void Info(Message context); 
    void Info(Message context, Exception exception); 
} 

public sealed class Message 
{ 
    public string RunDate { get; set; } 
    public string RunBy { get; set; } 
    public string Message { get; set; } 

    public string ToJsonString() 
    { 
     return new JavaScriptSerializer().Serialize(this); 
    } 
} 
+1

Co to jest CrmConfigHelper? – Phil

+0

@Phil: Wygląda na to, że to coś, co idzie i pobiera informacje z plików konfiguracyjnych projektu. Osobiście zapewne przekazywałbym te informacje jako parametry, więc SQLLogger nie musiałby nic wiedzieć o projekcie. Następnie możesz podzielić to na oddzielny, samodzielny projekt i po prostu umieścić go w dowolnym projekcie, dla którego chcesz włączyć rejestrowanie. – Ellesedil

+0

@Elesedil Autor zaktualizował odpowiedź wyjaśniając CrmConfigHelper. Mimo to, dzięki. – Phil