【问题标题】:Dynamical logging framework or technique动态日志框架或技术
【发布时间】:2017-12-24 07:03:49
【问题描述】:

我想要求一些具有特定功能的日志记录机制或框架。我已经在我的应用程序(dll 库)中登录了

Log.WriteLine("{0}.{1}()", System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType, System.Reflection.MethodInfo.GetCurrentMethod().Name);

Log 是静态类,可以使用 Streamwriter 写入文件

public void LogWriteLine(string text, params object[] args) {
  lock (this) {
      StreamWriter log = new StreamWriter(logFile, true);
      if (log != null) {
        log.WriteLine("{0:yyyy-MM-dd HH:mm:ss} {1}", DateTime.Now, String.Format(text, args));
        log.Flush();
        log.Close();
      }
  }
}

我的问题是,我的应用程序中没有 Log.WriteLine 调用,只是在应用程序的特定部分,因为它会创建非常大的文件。但现在,我构建了我的应用程序,并将其发布给开发人员,他们为此工作了几天。之后他们向我发送错误,但在我的版本中,错误不再存在(应用程序继续开发,因此可以修复它们)。

所以我想在应用程序中添加一些设置文件,告诉应用程序我需要更多日志,并且能够运行测试人员版本的应用程序,而无需使用不同的记录器设置来重建它。

简而言之:我如何告诉应用程序形成一些设置文件,只记录特定的内容,例如只记录一个类或一个方法?

【问题讨论】:

    标签: c# dynamic logging


    【解决方案1】:

    您可以查看 .NET Tracing。这是一个非常简短的介绍(1 页):

    http://www.codeguru.com/csharp/.net/net_debugging/tracing/article.php/c5919

    【讨论】:

      【解决方案2】:

      我会看看 Log4Net。 Log4Net 提供日志级别的 App.Config 配置,重定向到多个输出,允许同步或异步(缓冲)日志记录。

      这里有一篇好文章:http://www.codeproject.com/Articles/14819/How-to-use-log4net

      我写了一篇关于如何使用 Regex Find and Replace 来全面更改整个应用程序的日志记录以使用另一种语法的文章。请参阅this previous answerthis blog article

      【讨论】:

      • 是的,正如我所写,我会看看它,看看哪些套件最适合我。如果我也可以检查这个答案是否正确,我会这样做:)也许在尝试之后我会改变主意;)
      【解决方案3】:

      我需要做类似的事情。我就是这样做的。

      我创建了一个类别类,并在初始化日志对象时将其用作参数。

      /// <summary>
      /// Category object for logging
      /// </summary>
      public class Category
      {
          #region Private Members
          private bool    m_active;
          private string  m_name;
          private bool    m_excludeFromLogFile = false;
          #endregion
      
          /// <summary>
          /// Create a category and add it to the Logging category list
          /// </summary>
          /// <param name="name">The Name of the category</param>
          /// <param name="active">The active state of the category</param>
          /// <param name="exclude">If true any messages for this category will not be written to the log file</param>
          /// <param name="addedToList">If true then the new category will be added to the logging category list</param>
          public Category(string name, bool active, bool exclude, bool addedToList)
          {
              m_name = name;
              m_active = active;
              m_excludeFromLogFile = exclude;
      
              if(addedToList)
              {
                  Log.GetInstance().AddCategory(this);
              }
          }
      
          #region Public Accessor Methods
              // .. Add accessors as required 
          #endregion
      }
      

      从“Log.GetInstance().AddCategory(this);”行可以看出,我的日志记录对象是一个单例。

      单例,有一些添加和删除类别的方法

      /// <summary>
      /// Add a new category to the list of available categories
      /// </summary>
      /// <param name="newCat">The category object to add</param>
      public void AddCategory( Category newCat )
      {
          // Ensure that the category doesn't already exist in the list
          if( this.m_CategoryList.Contains( newCat ) == false )
          {
              // Add the new category to the list
              this.m_CategoryList.Add( newCat );
          }
      }
      
      /// <summary>
      /// Remove a category to the list of available categories
      /// </summary>
      /// <param name="catName">The name of the category to be removed</param>
      public void RemoveCategory( string catName )
      {
          Category toRemove = null;
      
          // Iterate through the categories looking for a match
          foreach( Category cat in this.m_CategoryList)
          {
              // Compare the category names (case insensitive)
              if( cat.Name.ToUpper() == catName.ToUpper() )
              {
                  // Assign the category to remove to a local variable and exit the loop
                  toRemove = cat;
                  break;
              }
          }
      
          // Remove the category if it's been located
          if( toRemove != null )
          {
              this.m_CategoryList.Remove( toRemove );
          }
      }
      

      在处理日志事件时,现在只需检查类别的活动状态以查看是否需要该消息。

      /// <summary>
      /// Create a log entry in the log file and then Fire an event for the log message to be handled
      /// </summary>
      /// <param name="category">The category to log the message against</param>
      /// <param name="args"> Message logging arguments used by the event</param>
      public void WriteLine(Category category, MessageEventArgs args)
      {
          // Ensure that the category specified exists in the array list
          if( this.m_CategoryList.Contains( category ) )
          {
              // Ensure the category is active 
              if(category.Active == true)
              {
                  if(!category.ExcludeFromLogFile)
                  {
                      // Try and log the message to the log file
                      this.WriteLineToFile( category, args );
                  }
      
                  // Ensure an event handler has been assigned
                  if(MessageEvent != null)
                  {
                      // This message event is handled by the UI thread for updating screen components.
                      MessageEvent(category, args);
                  }
              }
          }
      }
      

      最后,如果您希望消息显示在屏幕上,您需要在 UI 线程中处理消息事件。这是我的列表视图组件之一的示例...

      private void ListViewLogging_MessageEvent(Category category, MessageEventArgs args)
      {
          // Ensure the event was received in the UI thread
          if(this.InvokeRequired)
          {
              if(args.Message != null)
              {
                  // We aren't in the UI thread so reFire the event using the main thread
                  this.BeginInvoke(new MessageReceivedDelegate(this.ListViewLogging_MessageEvent), new object[]{category,args});
              }
          }
          else
          {
              // We are currently in the main thread.
              // Lock so no other thread can be handled until event processing has been finished
              lock(this)
              {
                  // Create a new ListView item for the new message 
                  ListViewItem newEntry = null;;
      
                  // Determine the category type
                  switch( category.Name )
                  {
                      case "Serious":
                      {
                          // Serious error detected
                          if( args.Message.Length > 0 )
                          {
                              newEntry = new ListViewItem( new string[]{category.Name, args.Occurred.ToLongTimeString(), args.Message} );
                              newEntry.BackColor = Color.Red;
                          }
                          break;
                      }
                      case "Warning":
                      {
                          // Warning detected.
                          if( args.Message.Length > 0 )
                          {
                              newEntry = new ListViewItem( new string[]{category.Name, args.Occurred.ToLongTimeString(), args.Message} );
                              newEntry.BackColor = Color.Orange;
                          }
                          break;
                      }
                      case "Progress":
                      {
                          // If a message has been specified, log it
                          if( args.Message.Length > 0 )
                          {
                              newEntry = new ListViewItem( new string[]{"", args.Occurred.ToLongTimeString(), args.Message} );
                          }
                          break;
                      }
                      case "Debug":
                      {
                          // Just a standard Debug event so just display the text on the screen
                          if( args.Message.Length > 0 )
                          {
                              newEntry = new ListViewItem( new string[]{category.Name, args.Occurred.ToLongTimeString(), args.Message} );
                              newEntry.BackColor = Color.LightGreen;
                          }
                          break;
                      }
                      case "Info":
                      default:
                      {
                          // Just a standard event so just display the text on the screen
                          if( args.Message.Length > 0 )
                          {
                              newEntry = new ListViewItem( new string[]{category.Name, args.Occurred.ToLongTimeString(), args.Message} );
                          }
                          break;
                      }
                  }
                  // Add the item if it's been populated
                  if( newEntry != null )
                  {
                      this.Items.Add( newEntry );
                      this.EnsureVisible( this.Items.Count-1 );
                  }
              }
          }
      }
      

      【讨论】:

      • 好的,知道如何在不更改和重建代码的情况下激活或停用特定事件的日志记录?
      • 您需要一个访问 Logging 对象中 Category 容器的访问器方法。找到类别并设置活动状态。另一种方法是默认设置一些静态类别(我使用 Serious、Warning、Info 和 Debug),然后拥有访问这些特定类别的方法。
      • 起初我想到了一些机制,我可以在设置文件中动态添加类名或方法名,然后运行可以读取设置文件的应用程序(在开始时)并决定记录什么...但是这种调试、警告等日志的“分层”也很有帮助,谢谢:)
      • 我不得不承认,我对 Log4Net 了解不多,但有一次它被包含在我们的一个项目中,它把一切都搞砸了,所以我们把它拿出来回去了使用我们的单例日志对象。
      【解决方案4】:

      您可以使用 log4net loggerfilter。见introduction article

      【讨论】:

        猜你喜欢
        • 2023-03-20
        • 2012-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-24
        • 2019-12-02
        • 2011-10-02
        相关资源
        最近更新 更多