65.9K
CodeProject 正在变化。 阅读更多。
Home

对 LOG4NET 日志框架的增强包装器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.77/5 (15投票s)

2005年3月26日

CPOL

7分钟阅读

viewsIcon

103062

downloadIcon

1157

一篇关于增强版LOG4NET日志框架包装器的文章。

An example logging output inside a console window

引言

(最新变更请参阅下方历史记录部分)

在本文中,我将向您展示一个类,它在过去几年中简化了我的生活,用于记录.NET应用程序的(错误)消息,无论它是Windows GUI应用程序、Windows服务还是Windows Web应用程序。

通过使用本文所述的单一类,您应该能够以最小的努力和最大的灵活性,在应用程序的每个状态下提供有意义的日志信息。

背景

再次(像我其他一些文章一样),我并没有从头开始编写日志部分,而是将我自己的代码添加到了流行且经过充分测试的优秀日志框架LOG4NET中。

主要的日志类是LogCentral类。我试图将所有LOG4NET类和接口隐藏在我的类中,以便LogCentral类的用户永远不会直接接触LOG4NET服务。这样做的原因是允许最大的灵活性,如果我想将底层的日志引擎更改为另一个引擎,除了LogCentral类本身内部的代码之外,不需要进行任何代码更改。

请注意:隐藏LOG4NET的一个可能负面影响是,LogCentral类的用户无法使用所有LOG4NET的扩展功能。在实际中,这在我小型到中型的项目中从来不是问题,但如果您尝试进行极限日志记录,则可能会成为问题。在这种情况下,直接使用LOG4NET这样的日志框架,而不是使用LogCentral类,可能会更好。

支持的功能

LogCentral类提供以下功能

日志的单一入口点

要记录一条消息,您只需使用静态属性LogCentral.Current来访问日志类的始终可用的实例。

通过简单的函数调用记录不同类型的消息

LogCentral类通过提供几种日志类型的重载,方便地访问实际日志记录消息。

示例:以下调用记录了一条信息性消息。

...
 
LogCentral.Current.LogInfo( 
    "This is an informational message." );
 
...

以下函数定义在LogCentral类中(为便于阅读,省略了参数)

  • public void LogInfo() - 记录一条信息性消息。
  • public void LogError() - 记录一条错误消息,例如在catch块中。
  • public void LogDebug() - 记录一条调试消息,不应出现在发布版本中(这取决于您通过配置文件正确配置该类,以便调试消息在发布版本中确实不被记录)。
  • public void LogWarn() - 记录一条警告消息。
  • public void LogFatal() - 记录一条致命消息。

通过已知的LOG4NET XML配置模式进行标准配置

尽管我曾说过LogCentral类从类用户那里隐藏了所有LOG4NET代码,但我没有提供自己的配置文件语法。因此,LogCentral类的配置与LOG4NET本身完全相同。所有配置LOG4NET框架的文档都适用于LogCentral类。

您的标准应用程序配置文件中的示例配置(即Windows可执行文件的“YourExeName.exe.config”或Web服务和Web应用程序的“Web.config”)可能如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section 
      name="log4net" 
      type="System.Configuration.IgnoreSectionHandler" />
  </configSections>
  
  <log4net>
    <appender 
      name="RollingLogFileAppender" 
      type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Test.log" />
      <param name="AppendToFile" value="true" />
      <param name="MaxSizeRollBackups" value="9" />
      <param name="MaximumFileSize" value="10MB" />
      <param name="RollingStyle" value="Size" />
      <param name="StaticLogFileName" value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param 
          name="Header" 
          value="\r\n\r\n---------------------------------------------\r\n" />
        <param 
          name="Footer" 
          value="\r\n---------------------------------------------\r\n\r\n" />
        <param name="ConversionPattern" value="%d [%t] %-5p - %m%n" />
      </layout>
    </appender>
  
    <appender 
      name="ColoredConsoleAppender" 
      type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="ERROR" />
        <foreColor value="White" />
        <backColor value="Red" />
      </mapping>
      <mapping>
        <level value="DEBUG" />
        <backColor value="Green" />
      </mapping>
      <mapping>
        <level value="INFO" />
        <foreColor value="White" />
      </mapping>
  
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%-5p: %m%n" />
      </layout>
    </appender>
  
    <root>
      <level value="ALL" />
      <appender-ref ref="RollingLogFileAppender" />
      <appender-ref ref="ColoredConsoleAppender" />
    </root>
  </log4net>
</configuration>

自动记录到其他目的地

除了配置文件中定义的日志目标(“appender”)之外,LogCentral类还尝试将每条消息记录到以下目标:

用于在消息被记录之前添加额外文本的事件处理程序

我应用程序中的一个常见要求是根据应用程序的当前上下文,为实际记录的消息提供额外信息。例如,当SQL查询失败时,我想记录实际的SQL查询,而不仅仅是SQL查询执行期间引发的异常。

对于这种情况,我为应用程序添加了对提供事件处理程序的LogCentral类的支持,这些处理程序在消息实际被记录之前被调用。处理程序可以向正在记录的消息添加额外信息。

示例

以下代码添加了一个事件处理程序。通常在应用程序启动时进行此操作。

...
  
// Add handler.
LogCentral.Current.RequestMoreInformation += 
    new LogCentralRequestMoreInformationEventHandler(
    Current_RequestMoreInformation );  
...

实际的Current_RequestMoreInformation处理程序可以定义如下。在此示例中,变量this.counter是某个类成员,它会根据某些方法进行修改,并在记录严重消息时进行记录。

/// <summary>
/// This handler is called before a message is actually
/// being logged. Use this handler to provide more detailed 
/// information to the message being logged.
/// </summary>
private static void Current_RequestMoreInformation(
    object sender, 
    LogCentralRequestMoreInformationEventArgs e )
{
    // Only add for certain types.
    if ( e.Type==LogCentralRequestMoreInformationEventArgs.LogType.Error ||
    e.Type==LogCentralRequestMoreInformationEventArgs.LogType.Fatal ||
    e.Type==LogCentralRequestMoreInformationEventArgs.LogType.Warn )
    {
        // Add information that would otherwise not be visible
        // to the logging class.
        e.MoreInformationMessage += 
            string.Format(
            "The current counter value is '{0}'.",
            this.counter );
    }
}

现在,每当记录消息时,日志类都会调用Current_RequestMoreInformation处理程序。

提供的默认处理程序

LogCentral类本身在内部使用此事件来为以下项目提供上下文信息:

  • HTTP信息

    在Web上下文中运行时,将记录各种信息,如请求的URI、引用者URI、用户主机名、会话信息等。

  • 程序集信息

    将记录正在运行的应用程序的程序集信息。这些信息包括程序集路径、程序集日期、程序集版本等。

  • 环境信息

    将记录有关本地Windows环境的信息。这些信息包括当前登录用户、用户域、计算机名、CLR版本、当前工作目录等。

  • 网络信息

    将记录有关运行应用程序的计算机的主机名和IP地址的信息。

请注意:默认处理程序仅在消息类型为“warn”、“error”或“fatal”时添加上下文信息。

消息被记录后的事件处理程序

为完整起见,还有一个在日志发生之后引发的事件。您可以添加自己的处理程序来在消息被记录后执行杂项任务,例如清理资源或类似操作。

示例

以下代码添加了一个事件处理程序。通常在应用程序启动时进行此操作。

...
  
// Add handler.
LogCentral.Current.Log += 
    new LogCentralLogEventHandler(
    Current_Log );
  
...

实际的Current_Log处理程序可以定义如下。在此示例中,它只是将通知消息写入Debug输出。

/// <summary>
/// This handler is called after each call to one of the 
/// LogError, LogDebug, etc. function.
/// </summary>
private static void Current_Log(
    object sender, 
    LogCentralLogEventArgs e )
{
    System.Diagnostics.Debug.Write( "Log occured." );
}

其他功能简述

  • 密码保护

    每条被记录的消息都会被检查是否包含“password”或类似的潜在安全相关关键字。如果检测到此类关键字,则实际记录一条警告消息(“...包含非法单词...”),而不是消息本身。

  • 提供对配置文件路径的访问

    通过使用ConfigurationFilePath属性,您可以读取当前配置属性的完整路径,例如“C:\Inetpub\WwwRoot\MyWebApplication\Web.config”。有时这会很有用,例如,当您想从配置文件所在的完全相同的文件夹中读取其他文件时。

在您的项目中使用的代码

本文的代码下载包含一个小型示例项目以及库的预编译版本(.NET版本1.1,调试版和发布版)。要在您自己的项目中使用它,您至少有两种选择:

  1. 只需将“Release”文件夹中的内容(即“log4net.dll”和“ZetaLogger.dll”文件)复制到您选择的文件夹,然后使用Visual Studio .NET 2003中的“添加引用”命令添加引用。
  2. 复制并添加源文件“LogCentral.cs”到您的项目中,以便它与您的项目一起编译。请注意,您仍然需要添加对“log4net.dll”库的引用。

我建议您首先查看示例应用程序,然后再在您自己的项目中使用该库。

结论

在本文中,我向您展示了一个为您的应用程序添加日志功能的类。我使用这个类已经两年多了,偶尔会对其功能进行微小的增强。希望您也会发现这个类很有用。

如有任何问题、意见和建议,请使用本文底部的评论区。

参考文献

  1. LOG4NET框架主页.

历史

  • 2005-03-26

    创建了文章的第一个版本。

© . All rights reserved.