2009-03-16 36 views
15

Có cách nào để đặt mức nhật ký trong log4net theo lập trình không? Tôi đã giả định rằng sẽ có một tài sản mà sẽ cho phép bạn làm điều này, nhưng tôi dường như không thể tìm thấy nó.Thay đổi cấp nhật ký được lập trình trong log4net?

Điều tôi muốn làm là có tùy chọn cấu hình để vào chế độ gỡ lỗi. mà sẽ gây ra đăng nhập thêm.

Tôi đang sử dụng tệp cấu hình log4net riêng biệt x4. Hiện tại, các giải pháp mà tôi đã đưa ra như sau:

  1. Chỉnh sửa tệp nhật ký bằng cách sử dụng dom và sau đó gọi XMLConfigurator để định cấu hình tệp nhật ký theo tệp.

  2. Có hai tệp cấu hình nhật ký và tùy chọn thay đổi cuộc gọi xml Configurator để sử dụng tệp cấu hình nhật ký thích hợp.

Tôi đang nghiêng về phía 2, có bất kỳ lý do nào không hoạt động không?

Trả lời

7

Đây là cách tôi cấu hình log4net lập trình:

//declared as a class variable 
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

PatternLayout layout = new PatternLayout(@"%date %-5level %message%newline"); 
    RollingFileAppender appender = new RollingFileAppender(); 
    appender.Layout = layout; 
    appender.File = "c:\log.txt"; 
    appender.AppendToFile = true; 
    appender.MaximumFileSize = "1MB"; 
    appender.MaxSizeRollBackups = 0; //no backup files 
    appender.Threshold = Level.Error; 
    appender.ActivateOptions();      
    log4net.Config.BasicConfigurator.Configure(appender); 

Tôi nghĩ rằng tài sản Threshold của appender là những gì bạn đang tìm kiếm, nó sẽ kiểm soát những gì mức độ đăng nhập appender sẽ ra.

Log4net manual có nhiều ví dụ về cấu hình tốt.

+0

Tôi chưa thử điều đó, nhưng có vẻ khá gọn gàng. –

24

Bạn có thể thay đổi cấp độ ghi nhật ký của nhật ký log4net, nhưng không rõ ràng cách thực hiện. Tôi có một số mã thực hiện điều này. Với Logger này:

private readonly log4net.ILog mylogger; 

Bạn phải làm các động tác chân lạ mắt sau đây để thiết lập nó để gỡ lỗi:

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

Thay đổi mức của trình ghi nhật ký (hoặc của trình ghi nhật ký gốc) tốt hơn nhiều so với việc thay đổi cấp độ của một trình bổ sung cụ thể. +1 Tôi làm điều gì đó tương tự, nhưng trừu tượng nó thành RuntimeLoggingHelper.SetLoggerLevel (Loại (hoặc quá tải tên chuỗi), Cấp độ). –

+0

@ ThomasG.Mayfield và Eddie, bạn có thể giải thích tại sao thay đổi logger tốt hơn appender? Tôi đã có một logger duy nhất với 2 appender (Console, File). Tôi muốn có thể dễ dàng thay đổi những gì được ghi vào bàn điều khiển mà không thay đổi những gì được ghi vào tệp. Tôi đã tìm kiếm một giải pháp để thay đổi Ngưỡng/mức cho ứng dụng. Tôi có nên sử dụng 2 logger không? – Basic

+0

Bạn có thể thêm hoặc xóa các ứng dụng trong tương lai, nhưng mong muốn thay đổi cấp độ nhật ký của bạn là ảnh hưởng đến kết quả ghi nhật ký. Nếu bạn chỉ thay đổi một appender cụ thể theo lập trình, các appender khác sẽ bao gồm đầu ra mà bạn đã mong muốn được bao gồm/loại trừ. –

0

Đây là một theo dõi để nhận xét của bạn về câu trả lời của Mitch.

Trong khi bạn có thể đặt mức chương trình, tại sao không chỉ đặt mức nhật ký để gỡ lỗi? Bằng cách đó, người dùng của bạn sẽ không phải lo lắng về việc thiết lập mức nhật ký để gỡ lỗi, điều đó, tin tưởng tôi, sẽ không bao giờ được bật khi bạn cần.

Sau đó, khi xảy ra lỗi, chỉ cần yêu cầu người dùng gửi cho bạn tệp nhật ký đầy đủ và sử dụng trình xem nhật ký như Apache Chainsaw để chỉ chọn xem các cấp bạn muốn xem.

Một giải pháp khác là ghi lại các cấp độ khác nhau để phân tách các tệp. Bằng cách đó bạn có thể yêu cầu người dùng gửi cho bạn chỉ các cấp mà bạn muốn xem.

+1

Người dùng có chính sách công ty đĩa cứng hữu hạn là để gỡ lỗi để ghi nhật ký mọi thứ (các phương thức nhập và thoát) cũng như tôi đã được thông báo để làm cho mức ghi nhật ký có thể cấu hình được, vì vậy tôi phải tuân thủ, kháng cự vì nó là vô ích. –

+1

Ah, tôi thấy bạn đến từ đâu. Nhiệm vụ thiêng liêng từ những sinh vật ít hơn. –

0

Bạn có thể tải xuống dự án mẫu từ here hoặc sao chép dán mã bên dưới. Ở cuối mã là DDL SQL cho bảng giữ thông tin đăng nhập ..

using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using log4net; 
    using log4net.Config; 
    using NUnit.Framework; 
    using GenApp.Utils; 

    namespace ExampleConsoleApplication 
    { 


    class TestClass 
    { 

     private static readonly ILog logger = 
       LogManager.GetLogger (typeof (TestClass)); 


     static void Main (string[] args) 
     { 
     TestClass objTestClass = new TestClass(); 
    //log4net.Appender.ColoredConsoleAppender.Colors.HighIntensity 
     GenApp.Bo.UserSettings us = new GenApp.Bo.UserSettings(); 
     GenApp.Bo.User userObj = new GenApp.Bo.User() 
     { 

      UserSettings = us 

     }; 
     userObj.UserSettings.LogLevel = 4; 




     #region SetDynamicallyLogLevel 


     Logger.Debug (userObj, logger, " -- Debug msg -- "); 
     Logger.Info (userObj, logger, " -- Info msg -- "); 
     Logger.Warn (userObj, logger, " -- Warn msg -- "); 
     Logger.Error (userObj, logger, " -- Error msg -- "); 
     Logger.Fatal (userObj, logger, " -- Fatal msg -- "); 
     #endregion SetDynamicallyLogLevel 



     #region RemoveDynamicallyAppenders 
     Logger.SetThreshold ("LogFileAppender", log4net.Core.Level.Off); 

     //and echo again 
     Logger.Debug (userObj, logger, " -- Debug msg -- "); 
     Logger.Info (userObj, logger, " -- Info msg -- "); 
     Logger.Warn (userObj, logger, " -- Warn msg -- "); 
     Logger.Error (userObj, logger, " -- Error msg -- "); 
     Logger.Fatal (userObj, logger, " -- Fatal msg -- "); 



     #endregion RemoveDynamicallyAppenders 

     Console.WriteLine (" END HIT A KEY TO EXIT "); 
      Console.ReadLine(); 
      } //eof method 


    } //eof class 

    } //eof namespace 




    /* App.config CopyPaste 
    <?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="Program.log" /> 
    <param name="AppendToFile" value="true" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <!--<param name="Header" value="======================================" /> 
     <param name="Footer" value="======================================" />--> 
     <param name="ConversionPattern" value="%date{yyyy'.'MM'.'dd --- HH':'mm':'ss'.'fff} [%t] %-5p -- %m%n" /> 
    </layout> 
    </appender> 

    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> 
    <mapping> 
     <level value="ERROR" /> 
     <foreColor value="Red" /> 
    </mapping> 
    <mapping> 
     <level value="DEBUG" /> 
     <foreColor value="HighIntensity" /> 
    </mapping> 
    <mapping> 
     <level value="INFO" /> 
     <foreColor value="Green" /> 
    </mapping> 
    <mapping> 
     <level value="WARN" /> 
     <foreColor value="Yellow" /> 
    </mapping> 
    <mapping> 
     <level value="FATAL" /> 
     <foreColor value="White" /> 
     <backColor value="Red" /> 
    </mapping> 

    <layout type="log4net.Layout.PatternLayout"> 
     <!-- You could change here the date format --> 
     <conversionPattern value="%date{yyyy'.'MM'.'dd --- HH':'mm':'ss'.'fff} [%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="@domainName" /> 
     <dbType value="String" /> 
     <size value="255" /> 
     <layout type="log4net.Layout.PatternLayout" value="%user" /> 
    </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="%message" /> 
    </parameter> 
    </appender> 
    <root> 
    <level value="ALL" /> 
    <appender-ref ref="LogFileAppender" /> 
    <appender-ref ref="AdoNetAppender" /> 
    <appender-ref ref="ColoredConsoleAppender" /> 
    </root> 
</log4net> 
</configuration> 
    */ 
    #region TheReferencesInThecsprojFile 
    //<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" /> 
    #endregion TheReferencesInThecsprojFile 


namespace GenApp.Bo 
{ 
    public class User 
    { 

    public int LogLevel { get; set; } 
    public UserSettings UserSettings { get; set; } 


    } //eof class 

    public class UserSettings 
    { 
    public int LogLevel; 
    } 

} //eof namespace 

namespace GenApp.Utils 
{ 
    ///<version> 1.1 </version> 
    ///<author> Yordan Georgiev </author> 
    ///<summary> Wrapper around log4net with dynamically adjustable verbosity</summary> 
    public class Logger 
    { 

    private static Logger inst = new Logger(); 
    public static Logger Inst() 
    { 
     inst.ConfigureLogging(); 
     return inst; 
    } 


    public 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 
    } 

    public static void Debug (GenApp.Bo.User userObj, ILog logger, string msg) 
    { 
     DebugLevel debugLevel = (DebugLevel)userObj.UserSettings.LogLevel; 
     string strLogLevel = Logger.GetLogTypeString (debugLevel); 
     inst.SetLogingLevel (strLogLevel); 
     logger.Debug (msg); 

    } //eof method 


    public static void Info (GenApp.Bo.User userObj, ILog logger, string msg) 
    { 
     DebugLevel debugLevel = (DebugLevel)userObj.UserSettings.LogLevel; 
     string strLogLevel = Logger.GetLogTypeString (debugLevel); 
     inst.SetLogingLevel (strLogLevel); 
     logger.Info (msg); 

    } //eof method 


    public static void Warn (GenApp.Bo.User userObj, ILog logger, string msg) 
    { 
     DebugLevel debugLevel = (DebugLevel)userObj.UserSettings.LogLevel; 
     string strLogLevel = Logger.GetLogTypeString (debugLevel); 
     inst.SetLogingLevel (strLogLevel); 
     logger.Warn (msg); 

    } //eof method 


    public static void Error (GenApp.Bo.User userObj, ILog logger, string msg) 
    { 
     DebugLevel debugLevel = (DebugLevel)userObj.UserSettings.LogLevel; 
     string strLogLevel = Logger.GetLogTypeString (debugLevel); 
     inst.SetLogingLevel (strLogLevel); 
     logger.Error (msg); 
    } //eof method 


    public static void Fatal (GenApp.Bo.User userObj, ILog logger, string msg) 
    { 
     DebugLevel debugLevel = (DebugLevel)userObj.UserSettings.LogLevel; 
     string strLogLevel = Logger.GetLogTypeString (debugLevel); 
     inst.SetLogingLevel (strLogLevel); 
     logger.Fatal (msg); 
    } //eof method 


    /// <summary> 
    /// Activates debug level 
    /// </summary> 
    /// <sourceurl>http://geekswithblogs.net/rakker/archive/2007/08/22/114900.aspx</sourceurl> 
    private void SetLogingLevel (string strLogLevel) 
    { 

     this.ConfigureLogging(); 
     string strChecker = "WARN_INFO_DEBUG_ERROR_FATAL"; 

     if (String.IsNullOrEmpty (strLogLevel) == true || strChecker.Contains (strLogLevel) == false) 
     throw new ArgumentOutOfRangeException (" 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]; 
    } 

    ///<summary> 
    ///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 
    ///</summary> 
    private static string GetLogTypeString (DebugLevel debugLevel) 
    { 

     string srtLogLevel = String.Empty; 
     switch (debugLevel) 
     { 
     case DebugLevel.Fatal_Msgs: 
      srtLogLevel = "FATAL"; 
      break; 
     case DebugLevel.Fatal_Error_Msgs: 
      srtLogLevel = "ERROR"; 
      break; 
     case DebugLevel.Fatal_Error_Warn_Msgs: 
      srtLogLevel = "WARN"; 
      break; 
     case DebugLevel.Fatal_Error_Warn_Info_Msgs: 
      srtLogLevel = "INFO"; 
      break; 
     case DebugLevel.Fatal_Error_Warn_Info_Debug_Msgs: 
      srtLogLevel = "DEBUG"; 
      break; 
     default: 
      srtLogLevel = "FATAL"; 
      break; 
     } //eof switch 
     return srtLogLevel; 

    } //eof GetLogTypeString 


    /// <summary> 
    /// The path where the configuration is read from. 
    /// This value is set upon a call to ConfigureLogging(). 
    /// </summary> 
    private string configurationFilePath; 
    public void ConfigureLogging() 
    { 
     lock (this) 
     { 
     bool configured = false; 


     #region ConfigureByThePathOfTheEntryAssembly 
     // Tells the logging system the correct path. 
     Assembly a = Assembly.GetEntryAssembly(); 

     if (a != null && a.Location != null) 
     { 
      string path = a.Location + ".config"; 

      if (File.Exists (path)) 
      { 
      log4net.Config.DOMConfigurator.Configure (
       new FileInfo (path)); 
      configurationFilePath = path; 
      configured = true; 
      } 
      else 
      { 
      path = FindConfigInPath (Path.GetDirectoryName (a.Location)); 
      if (File.Exists (path)) 
      { 
       log4net.Config.DOMConfigurator.Configure (
       new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
      } 
      } 
     } 
     #endregion ConfigureByThePathOfTheEntryAssembly 


     #region ConfigureByWeb.config 
     //// Also, try web.config. 
     //if (!configured) 
     //{ 
     // if (HttpContext.Current != null && 
     // HttpContext.Current.Server != null && 
     // HttpContext.Current.Request != null) 
     // { 
     // string path = HttpContext.Current.Server.MapPath (
     //  HttpContext.Current.Request.ApplicationPath); 

     // path = path.TrimEnd ('\\') + "\\Web.config"; 

     // if (File.Exists (path)) 
     // { 
     //  log4net.Config.DOMConfigurator.Configure (
     //  new FileInfo (path)); 
     //  configurationFilePath = path; 
     //  configured = true; 
     // } 
     // } 
     //} 
     #endregion ConfigureByWeb.config 


     #region ConfigureByThePathOfTheExecutingAssembly 
     if (!configured) 
     { 
      // Tells the logging system the correct path. 
      a = Assembly.GetExecutingAssembly(); 

      if (a != null && a.Location != null) 
      { 
      string path = a.Location + ".config"; 

      if (File.Exists (path)) 
      { 
       log4net.Config.DOMConfigurator.Configure (
       new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
      } 
      else 
      { 
       path = FindConfigInPath (Path.GetDirectoryName (a.Location)); 
       if (File.Exists (path)) 
       { 
       log4net.Config.DOMConfigurator.Configure (
        new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
       } 
      } 
      } 
     } 
     #endregion ConfigureByThePathOfTheExecutingAssembly 


     #region ConfigureByThePathOfTheCallingAssembly 
     if (!configured) 
     { 
      // Tells the logging system the correct path. 
      a = Assembly.GetCallingAssembly(); 

      if (a != null && a.Location != null) 
      { 
      string path = a.Location + ".config"; 

      if (File.Exists (path)) 
      { 
       log4net.Config.DOMConfigurator.Configure (
       new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
      } 
      else 
      { 
       path = FindConfigInPath (Path.GetDirectoryName (a.Location)); 
       if (File.Exists (path)) 
       { 
       log4net.Config.DOMConfigurator.Configure (
        new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
       } 
      } 
      } 
     } 
     #endregion ConfigureByThePathOfTheCallingAssembly 


     #region ConfigureByThePathOfTheLibIsStored 
     if (!configured) 
     { 
      // Look in the path where this library is stored. 
      a = Assembly.GetAssembly (typeof (Logger)); 

      if (a != null && a.Location != null) 
      { 
      string path = FindConfigInPath (Path.GetDirectoryName (a.Location)); 
      if (File.Exists (path)) 
      { 
       log4net.Config.DOMConfigurator.Configure (
       new FileInfo (path)); 
       configurationFilePath = path; 
       configured = true; 
      } 
      } 
     } 
     #endregion ConfigureByThePathOfTheLibIsStored 



     } //eof lock 
    } //eof method 



    /// <summary> 
    /// Searches for a configuration file in the given path. 
    /// </summary> 
    private string FindConfigInPath (
     string path) 
    { 
     string[] files = Directory.GetFiles (path); 

     if (files != null && files.Length > 0) 
     { 
     foreach (string file in files) 
     { 
      if (Path.GetExtension (file).Trim ('.').ToLower (
      CultureInfo.CurrentCulture) == "config") 
      { 
      return file; 
      } 
     } 
     } 

     // Not found. 
     return string.Empty; 
    } //eof method 



    /// <summary> 
    /// Remove dynamically appenders 
    /// </summary> 
    /// <param name="appenderName"></param> 
    /// <param name="threshold"></param> 
    public static void SetThreshold (string appenderName, Level threshold) 
    { 
     foreach (AppenderSkeleton appender in LogManager.GetRepository().GetAppenders()) 
     { 
     if (appender.Name == appenderName) 
     { 
      appender.Threshold = threshold; 
      appender.ActivateOptions(); 

      break; 
     } 
     } 
    } //eof method 



    } //eof class 


} //eof namespace 

USE [DBGA_DEV] 
GO 

/****** Object: Table [ga].[tb_Data_Log] Script Date: 05/20/2009 12:16:01 ******/ 
SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

SET ANSI_PADDING ON 
GO 

CREATE TABLE [ga].[tb_Data_Log](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Date] [datetime] NOT NULL, 
    [Thread] [varchar](255) NOT NULL, 
    [Level] [varchar](20) NOT NULL, 
    [Logger] [varchar](255) NOT NULL, 
    [Message] [varchar](4000) NOT NULL 
) ON [PRIMARY] 

GO 

SET ANSI_PADDING ON 
GO 
Các vấn đề liên quan