Jenney Zhao

导航

关于log4net

1 概述

log4net is a tool to help the programmer output log statements to a variety of output targets.

关于log4net详细的介绍请参见:

http://logging.apache.org/log4net/release/features.html

http://logging.apache.org/log4net/release/manual/introduction.html

优点:

It allows the developer to control which log statements are output with arbitrary granularity.

It is fully configurable at runtime using external configuration files.

It provides precise context about the execution of the application.

Once inserted into the code, the generation of logging output requires no human intervention.

Moreover, log output can be saved in persistent medium to be studied at a later time.

In addition to its use in the development cycle, a sufficiently rich logging package can also be viewed as an auditing tool.

缺点:

It can slow down an application. If too verbose, it can cause scrolling blindness.

2 结构

log4net主要包括3大组件:loggers, appenders and layouts.

2.1 logger

Logger是应用程序需要交互的主要组件,它用来产生日志消息。

Loggers are named entities. Logger names are case-sensitive and they follow the following hierarchical naming rule:

Named Hierarchy

A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.

The hierarchy works very much in the same way as the namespace and class hierarchy in .NET. This is very convenient as we shall soon see.

The root logger resides at the top of the logger hierarchy. It is exceptional in three ways:

  1. It always exists
  2. It cannot be retrieved by name
  3. It always has an assigned level

Loggers are retrieved using the static method from the log4net.LogManager class. The GetLogger methods take the name of the desired logger as a parameter. They are listed below:

namespace log4net
{
    public class LogManager
    {
        public static ILog GetLogger(string name);
        public static ILog GetLogger(Type type);
    }
}

The GetLogger methods that takes a Type parameter uses the fully qualified type name as the name of the logger to retrieve.

These GetLogger methods return an ILog interface. That is the representation of the Logger passed back to the developer. The ILog interface is defined below:

namespace log4net
{
    public interface ILog
    {
        /* Test if a level is enabled for logging */
        bool IsDebugEnabled { get; }
        bool IsInfoEnabled { get; }
        bool IsWarnEnabled { get; }
        bool IsErrorEnabled { get; }
        bool IsFatalEnabled { get; }
        
        /* Log a message object */
        void Debug(object message);
        void Info(object message);
        void Warn(object message);
        void Error(object message);
        void Fatal(object message);
        
        /* Log a message object and exception */
        void Debug(object message, Exception t);
        void Info(object message, Exception t);
        void Warn(object message, Exception t);
        void Error(object message, Exception t);
        void Fatal(object message, Exception t);
        
        /* Log a message string using the System.String.Format syntax */
        void DebugFormat(string format, params object[] args);
        void InfoFormat(string format, params object[] args);
        void WarnFormat(string format, params object[] args);
        void ErrorFormat(string format, params object[] args);
        void FatalFormat(string format, params object[] args);
        
        /* Log a message string using the System.String.Format syntax */
        void DebugFormat(IFormatProvider provider, string format, params object[] args);
        void InfoFormat(IFormatProvider provider, string format, params object[] args);
        void WarnFormat(IFormatProvider provider, string format, params object[] args);
        void ErrorFormat(IFormatProvider provider, string format, params object[] args);
        void FatalFormat(IFormatProvider provider, string format, params object[] args);
    }
}

Loggers may be assigned levels. Levels are instances of the log4net.Core.Level class. The following levels are defined in order of increasing priority:

  • ALL
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • OFF

If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level. More formally:

Level Inheritance

The inherited level for a given logger X, is equal to the first non-null level in the logger hierarchy, starting at X and proceeding upwards in the hierarchy towards the root logger.

To ensure that all loggers can eventually inherit a level, the root logger always has an assigned level. The default value for the root logger is DEBUG.

Logging requests are made by invoking one of the printing methods of a logger instance (through the log4net.ILog). These printing methods are Debug,Info, Warn, Error, and Fatal.

By definition, the printing method determines the level of a logging request. For example, if log is a logger instance, then the statement log.Info("..") is a logging request of level INFO.

A logging request is said to be enabled if its level is higher than or equal to the level of its logger. Otherwise, the request is said to be disabled. A logger without an assigned level will inherit one from the hierarchy. This rule is summarized below.

Basic Selection Rule

A log request of level L in a logger with (either assigned or inherited, whichever is appropriate) level K, is enabled if L >= K.

This rule is at the heart of log4net. It assumes that levels are ordered. For the standard levels, we have DEBUG < INFO < WARN < ERROR < FATAL.

Calling the log4net.LogManager.GetLogger method with the same name will always return a reference to the exact same logger object.

For example, in:

ILog x = LogManager.GetLogger("wombat");
ILog y = LogManager.GetLogger("wombat");

x and y refer to exactly the same logger object.

Thus, it is possible to configure a logger and then to retrieve the same instance somewhere else in the code without passing around references. In fundamental contradiction to biological parenthood, where parents always precede their children, log4net loggers can be created and configured in any order. In particular, a "parent" logger will find and link to its descendants even if it is instantiated after them.

2.2 Appenders

The ability to selectively enable or disable logging requests based on their logger is only part of the picture. Log4net allows logging requests to print to multiple destinations. In log4net speak, an output destination is called an appender. Appenders must implement the log4net.Appenders.IAppenderinterface.

The following appenders are defined in the log4net package:

TypeDescription
log4net.Appender.AdoNetAppender Writes logging events to a database using either prepared statements or stored procedures.
log4net.Appender.AnsiColorTerminalAppender Writes color highlighted logging events to a an ANSI terminal window.
log4net.Appender.AspNetTraceAppender Writes logging events to the ASP trace context. These can then be rendered at the end of the ASP page or on the ASP trace page.
log4net.Appender.BufferingForwardingAppender Buffers logging events before forwarding them to child appenders.
log4net.Appender.ColoredConsoleAppender Writes logging events to the application's Console. The events may go to either the standard our stream or the standard error stream. The events may have configurable text and background colors defined for each level.
log4net.Appender.ConsoleAppender Writes logging events to the application's Console. The events may go to either the standard our stream or the standard error stream.
log4net.Appender.DebugAppender Writes logging events to the .NET system.
log4net.Appender.EventLogAppender Writes logging events to the Windows Event Log.
log4net.Appender.FileAppender Writes logging events to a file in the file system.
log4net.Appender.ForwardingAppender Forwards logging events to child appenders.
log4net.Appender.LocalSyslogAppender Writes logging events to the local syslog service (UNIX only).
log4net.Appender.MemoryAppender Stores logging events in an in memory buffer.
log4net.Appender.NetSendAppender Writes logging events to the Windows Messenger service. These messages are displayed in a dialog on a users terminal.
log4net.Appender.OutputDebugStringAppender Writes logging events to the debugger. If the application has no debugger, the system debugger displays the string. If the application has no debugger and the system debugger is not active, the message is ignored.
log4net.Appender.RemoteSyslogAppender Writes logging events to a remote syslog service using UDP networking.
log4net.Appender.RemotingAppender Writes logging events to a remoting sink using .NET remoting.
log4net.Appender.RollingFileAppender Writes logging events to a file in the file system. The RollingFileAppender can be configured to log to multiple files based upon date or file size constraints.
log4net.Appender.SmtpAppender Sends logging events to an email address.
log4net.Appender.SmtpPickupDirAppender Writes SMTP messages as files into a pickup directory. These files can then be read and sent by an SMTP agent such as the IIS SMTP agent.
log4net.Appender.TelnetAppender Clients connect via Telnet to receive logging events.
log4net.Appender.TraceAppender Writes logging events to the .NET trace system.
log4net.Appender.UdpAppender Sends logging events as connectionless UDP datagrams to a remote host or a multicast group using a UdpClient.

More than one appender can be attached to a logger.

Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy. In other words, appenders are inherited additively from the logger hierarchy. For example, if a console appender is added to the root logger, then all enabled logging requests will at least print on the console. If in addition a file appender is added to a logger, say X, then enabled logging requests for X and X's children will print on a file and on the console. It is possible to override this default behavior so that appender accumulation is no longer additive by setting the additivity flag on the logger to false.

The rules governing appender additivity are summarized below.

Appender Additivity

The output of a log statement of logger X will go to all the appenders in X and its ancestors. This is the meaning of the term "appender additivity".

However, if an ancestor of logger X, say Y, has the additivity flag set to false, then X's output will be directed to all the appenders in X and it's ancestors up to and including Y but not the appenders in any of the ancestors of Y.

Loggers have their additivity flag set to true by default.

2.3 Filters

Appenders can filter the events that are delivered to them. The filters can be specified in the configuration to allow fine control of the events that are logged through different appenders.

The simplest form of control is to specify a Threshold on the appender. This works by logging only the events that have a level that is greater than or equal to the threshold.

More complex and custom event filtering can be done using the filter chain defined on each appender. Filters must implement the log4net.Filter.IFilterinterface.

The following filters are defined in the log4net package:

TypeDescription
log4net.Filter.DenyAllFilter Drops all logging events.
log4net.Filter.LevelMatchFilter An exact match to the event's level.
log4net.Filter.LevelRangeFilter Matches against a range of levels.
log4net.Filter.LoggerMatchFilter Matches against a the start of the logger name.
log4net.Filter.PropertyFilter Matches a substring from a specific property value.
log4net.Filter.StringMatchFilter Matches a substring from the event's message.

The filters can be configured to either accept or reject the event based upon the match.

2.4 Layouts

The layout is responsible for formatting the logging request according to the user's wishes, whereas an appender takes care of sending the formatted output to its destination. The PatternLayout, part of the standard log4net distribution, lets the user specify the output format according to conversion patterns similar to the C language printf function.

For example, the PatternLayout with the conversion pattern "%timestamp [%thread] %-5level %logger - %message%newline" will output something akin to:

176 [main] INFO  Com.Foo.Bar - Located nearest gas station.

The first field is the number of milliseconds elapsed since the start of the program. The second field is the thread making the log request. The third field is the level of the log statement. The fourth field is the name of the logger associated with the log request. The text after the '-' is the message of the statement.

The following layouts are included in the log4net package:

TypeDescription
log4net.Layout.ExceptionLayout Renders the exception text from the logging event.
log4net.Layout.PatternLayout Formats the logging event according to a flexible set of formatting flags.
log4net.Layout.RawTimeStampLayout Extracts the timestamp from the logging event.
log4net.Layout.RawUtcTimeStampLayout Extracts the timestamp from the logging event in Universal Time.
log4net.Layout.SimpleLayout Formats the logging event very simply: [level] - [message]
log4net.Layout.XmlLayout Formats the logging event as an XML element.
log4net.Layout.XmlLayoutSchemaLog4j Formats the logging event as an XML element that complies with the log4j event dtd.

2.5 Object Renderers

Just as importantly, log4net will render the content of the log message according to user specified criteria. For example, if you frequently need to logOranges, an object type used in your current project, then you can register an OrangeRenderer that will be invoked whenever an orange needs to be logged.

Object rendering follows the class hierarchy. For example, assuming oranges are fruits, if you register an FruitRenderer, all fruits including oranges will be rendered by the FruitRenderer, unless of course you registered an orange specific OrangeRenderer.

Object renderers have to implement the log4net.ObjectRenderer.IObjectRenderer interface.

Please note that ObjectRenderers are not used by the DebugFormat, InfoFormat, WarnFormat, ErrorFormat and FatalFormat methods.

3. log4net file example

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
 
  <root>
    <level value="DEBUG" />
    <appender-ref ref="ARollingLogFileAppender" />
  </root>

  <logger name="A">
    <level value="INFO" />
    <appender-ref ref="ARollingLogFileAppender" />
  </logger>

  <logger name="A.B">
    <level value="ERROR" />
    <appender-ref ref="EventLogAppender" />
    <!-- Uncomment Appenders to turn logging on
    <appender-ref ref="rollingFile" />
    <appender-ref ref="OutputDebugStringAppender" />-->
  </logger>

  <logger name="A.B.C">
    <level value="DEBUG" />
    <appender-ref ref="CRollingLogFileAppender" />
  </logger>

  <logger name="D">
    <level value="ERROR" />
    <appender-ref ref="EventLogAppender" />
    <!-- Uncomment Appenders to turn logging on
    <appender-ref ref="rollingFile" />
    <appender-ref ref="OutputDebugStringAppender" />-->
  </logger>

  <renderer renderingClass="ALogRendering" renderedClass="AException"/>
  <appender name="ARollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <threshold value="DEBUG"/>
    <file value="C:\Logs\ALog.txt" />
    <appendToFile value="true" />
    <rollingStyle value="Composite" />
    <datePattern value="yyyyMMdd" />
    <maxSizeRollBackups value="7" />
    <maximumFileSize value="1MB" />
    <layout type="ALayout" />
  </appender>
  
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender" >
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <!-- Rolling log files are created in exe's directory-->
    <param name="File" value="rollingFilelog.log" />
    <param name="AppendToFile" value="true" />
    <param name="RollingStyle" value="Composite" />
    <param name="MaxSizeRollBackups" value="10" />
    <param name="MaximumFileSize" value="10MB" />
    <param name="DatePattern" value="yyyy.MM.dd" />
    <param name="StaticLogFileName" value="true" />
    <!-- Layouts explained: -->
    <!-- http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html-->
    <layout type="log4net.Layout.PatternLayout, log4net">
      <param name="ConversionPattern" value="%date %appdomain:%thread %level %logger{1} %property %username - %message%newline%location%newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="FATAL" />
    </filter>
  </appender>
  
  <appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender" >
    <!-- Use the following utility to view log to the OutputDebugStringAppender -->
    <!-- http://www.sysinternals.com/Utilities/DebugView.html -->
    <layout type="log4net.Layout.PatternLayout, log4net">
      <param name="ConversionPattern" value="%date %appdomain:%thread %level %logger{1} %property %username - %message%newline%location%newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="FATAL" />
    </filter>
  </appender>
  
  <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
    <applicationName value="ApplicationName" />
    <layout type="log4net.Layout.PatternLayout, log4net">
      <param name="ConversionPattern" value="%date %appdomain:%thread %level %logger{1} %property %username - %message%newline%location%newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="FATAL" />
    </filter>
  </appender>

  <renderer renderingClass="CLogRender" renderedClass="CException"/>
  <appender name="CRollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <threshold value="DEBUG"/>
    <file value="C:\Logs\CLog.txt" />
    <appendToFile value="true" />
    <rollingStyle value="Composite" />
    <datePattern value="yyyyMMdd" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="5MB" />
    <staticLogFileName value="true" />
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="DEBUG" />
      <levelMax value="FATAL" />
    </filter>
    <layout type="CLayout" />
  </appender>
  
</log4net>

 

posted on 2013-08-04 22:43  Jenney Zhao  阅读(493)  评论(0编辑  收藏  举报