Log4net创建日志及简单扩展 (二)

6、Log4net的简单扩展

6.1通过重写布局Layout输出传入的 message对象的属性

6.1.1重写Layout类

通过继承log4net.Layout.PatternLayout类,使用log4net.Core.LoggingEvent类的方法得到了要输出的message类的名称,然后通过反射得到各个属性的值,使用PatternLayout类AddConverter方法传入得到的值。这里注意要引用用到的类的命名空间。

代码见附注8.2。

 

6.1.2配置相应的配置文件

配置文件其他地方不用改动,只是需要改动<appender>中的<layout>。例如:

<layout type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

        <param name="ConversionPattern"

 value="记录时间:%date    操作者ID:%property{Operator}             

操作类型:%property{Action}%n  消息描述:%property{Message}%n                    异常:%exception%n " />

      </layout>

其中<layout>的type由原来的log4net.Layout.PatternLayout换为自定义的TGLog.ExpandLayout2.ReflectionLayout(TGLog.ExpandLayout2为命名空间)。%property{Operator}输出的即为message类对象的属性Operator的值。数据库配置同样,相应的字段如果是自定义的,则输出选用自定义的<layout>。例:

<!--动作类型-->

  <parameter>

      <parameterName value="@action_type" />

      <dbType value="Int16" />

      <layout type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

         <conversionPattern value="%property{ActionType}" />

      </layout>

  </parameter>

6.1.3程序中如何使用

和一般使用方法基本相同,只是传入的参数是一个自定义的类,类的属性和配置文件中<layout>所有的%property{属性}是一致的,即%property{属性}在输出的时候就查找传入message类中有无对应的属性,如果有就输出值,没有则输出null。例:

log4net.ILog log = log4net.LogManager.GetLogger("ReflectionLayout");

try

            {

                log.Debug(new LogMessage(

1,

"操作对象:0",

 (int)TGLog.ActionType.Other,

 "这是四个参数测试")

);

            }

            catch(Exception ec)

            {

                log.Error(new LogMessage(

                                    1,

                                    "操作对象:0",

                                    (int)TGLog.ActionType.Other,

                                    "这是全部参数测试",

                                    "192.168.1.1",

                                    "MyComputer",

                                    "Maxthon(MyIE2)Fans"),

                         ec

);

      }

LogMessage的全部属性的构造方法如下:

public LogMessage(

            int operatorID,

            string operand,

            int ActionType,

            string message,

            string ip,

            string machineName,

            string browser

            )

     {

            this.ActionType = ActionType;

            this.Operator = operatorID;

            this.Message = message;

            this.Operand = operand;

            this.IP = ip;

            this.Browser = browser;

            this.MachineName = machineName;

}

6.2通过重新实现ILog接口来增加输入的参数

6.2.1重写LogImpl,LogManager类及实现ILog接口

这种方式是通过构造一个名为IMyLog接口,是继承Ilog接口而来,然后分别在MyLogImpl,MyLogManager重新实现IMyLog接口,增加了每种方法的参数。MyLogImpl,MyLogManager分别继承LogImpl,LogManager而来。

代码分别见8.3、8.4、8.5:

6.2.2配置相应的配置文件

配置文件其他地方不用改动,只是需要改动<appender>中的<layout>元素name为ConversionPattern的value中输出格式。例如:

<layout type=" log4net.Layout.PatternLayout ">

        <param name="ConversionPattern"

 value="记录时间:%date    操作者ID:%property{Operator}             

操作类型:%property{Action}%n  消息描述:%property{Message}%n                    异常:%exception%n " />

      </layout>

%property{参数}中的参数在MyLogImpl类中定义,如语句:

loggingEvent.Properties["Operator"] = operatorID;

就定义了Operator输出参数,即%property{Operator}输出的即为IMyLog中的参数operatorID的值。

数据库配置同样。例:

<!--动作类型-->

  <parameter>

      <parameterName value="@action_type" />

      <dbType value="Int16" />

      <layout type=" log4net.Layout.PatternLayout ">

         <conversionPattern value="%property{ActionType}" />

      </layout>

  </parameter>

6.2.3程序中如何使用

先引用IMyLog ,MyLogManager所在的命名空间,创建一个IMyLog对象,myLog的5 个方法,每个方法都有四个重载,增加了多参数的重载。例:

IMyLog myLog = MyLogManager.GetLogger("ExpandILog");

try

            {

myLog.Debug("这是一个参数重载测试!");          

}

            catch(Exception ec)

            {

                log.Error(

                          1,

                          "操作对象:0",

                          (int)TGLog.ActionType.Other,

                          "这是全部参数测试",

                          "192.168.1.1",

                          "MyComputer",

                          "Maxthon(MyIE2)Fans",

                          ec

);

      }

7、总结

Log4net 功能很多,这里只是对已经尝试用过的功能总结一下,普通写日志已经足够。需要注意的是:

1.            Log4net本身也有一些缺陷,比如一个记录引起了log4net本身的异常,就会使后面的日志无法记录下来,尤其是在写入数据库时。例如使用6.1扩展后,int型的属性在<appender >的元素<bufferSize>设置不为1时,<dbTypevalue="Int32" />时,就不能输出到数据库,而<dbType value="Int16" />则没任何问题。

2.            Log4net本身出现了异常,比如配置文件出现错误,有些日志输出方式会记录下这些异常,例如应用程序控制台;有些则不会输出这些错误,如数据库与文件。

3.            扩展时也会留下一些问题。例如在使用6.1扩展输出字段时就会出现,在log.debug(object message)中,如果message是一个自定义的类,属性与配置文件中输出设置也一致,构造函数时也只构造一个参数的实例,写文件与写数据库都成功,而将message按没有扩展的方式直接传入一个字符串,即log.debug(“信息内容”)使用则只能写入文件,而数据库则没写入。自定义的Layout 就是继承默认的PatternLayout,本来不应该出错,但出现了问题。原因分析是自定义的message类有类型为int的属性,作为一个对象传入时在默认值0,而直接使用字符串则int型的字段得不到默认值,引发异常。所以建议在有扩展存在时,最好多设几个<logger>,区分清楚,按照统一的形式记录日志,不要混合使用。

4.            配置文件的设置一定要准确,在一点不正确就会导致日志不能正常输出,所以在配置时先从最简单的开始,同时输出方式选择一种能输出log4net本身异常的方式,成功后一点一点加在新配置,这样出错了也容易找到那个地方配置有问题。

5.            log4net扩展性很强,几乎所有的组件都可以重写,在配置文件中配置好就可以使用。

8、附注:

8.1PatterLayout格式化字符表

转换字符

效果

a

等价于appdomain

appdomain

引发日志事件的应用程序域的友好名称。(使用中一般是可执行文件的名字。)

c

等价于 logger

C

等价于 type

class

等价于 type

d

等价于 date

date

发生日志事件的本地时间。 使用 DE>%utcdate 输出UTC时间。date后面还可以跟一个日期格式,用大括号括起来。DE>例如:%date{HH:mm:ss,fff}或者%date{dd MMM yyyy HH:mm:ss,fff}。如果date后面什么也不跟,将使用ISO8601 格式 。

日期格式和.Net中DateTime类的ToString方法中使用的格式是一样。

另外log4net还有3个自己的格式Formatter。 它们是 "ABSOLUTE", "DATE"和"ISO8601"分别代表 AbsoluteTimeDateFormatter, DateTimeDateFormatter和Iso8601DateFormatter。例如: %date{ISO8601}或%date{ABSOLUTE}。

它们的性能要好于ToString。

exception

异常信息

日志事件中必须存了一个异常对象,如果日志事件不包含没有异常对象,将什么也不输出。异常输出完毕后会跟一个换行。一般会在输出异常前加一个换行,并将异常放在最后。

F

等价于 file

file

发生日志请求的源代码文件的名字。

警告:只在调试的时候有效。调用本地信息会影响性能。

identity

当前活动用户的名字(Principal.Identity.Name).

警告:会影响性能。(我测试的时候%identity返回都是空的。)

l

等价于 location

L

等价于 line

location

引发日志事件的方法(包括命名空间和类名),以及所在的源文件和行号。

警告:会影响性能。没有pdb文件的话,只有方法名,没有源文件名和行号。

level

日志事件等级

line

引发日志事件的行号

警告:会影响性能。

logger

记录日志事件的Logger对象的名字。

可以使用精度说明符控制Logger的名字的输出层级,默认输出全名。

注意,精度符的控制是从右开始的。例如:logger 名为 "a.b.c", 输出模型为 %logger{2} ,将输出"b.c"。

m

等价于 message

M

等价于 method

message

由应用程序提供给日志事件的消息。

mdc

MDC (旧为:ThreadContext.Properties) 现在是事件属性的一部分。 保留它是为了兼容性,它等价于 property。

method

发生日志请求的方法名(只有方法名而已)。

警告:会影响性能。

n

等价于 newline

newline

换行符

ndc

NDC (nested diagnostic context)

p

等价于 level

P

等价于 property

properties

等价于 property

property

输出事件的特殊属性。例如: %property{user} 输出user属性。属性是由loggers或appenders添加到时间中的。 有一个默认的属性"DE>log4net:HostName"总是会有。DE>

%property将输出所有的属性 。

(扩展后可以使用)

 

r

等价于 timestamp

t

等价于 thread

timestamp

从程序启动到事件发生所经过的毫秒数。

thread

引发日志事件的线程,如果没有线程名就使用线程号。

type

引发日志请求的类的全名。.

可以使用精度控制符。例如: 类名是 "log4net.Layout.PatternLayout", 格式模型是%type{1} 将输出"PatternLayout"。(也是从右开始的。)

警告:会影响性能。

u

等价于 identity

username

当前用户的WindowsIdentity。(类似:HostName\Username)

警告:会影响性能。

utcdate

发生日志事件的UTC时间。DE>后面还可以跟一个日期格式,用大括号括起来。DE>例如:%utcdate{HH:mm:ss,fff}或者%utcdate{dd MMM yyyy HH:mm:ss,fff}。如果utcdate后面什么也不跟,将使用ISO8601 格式 。

日期格式和.Net中DateTime类的ToString方法中使用的格式是一样。

另外log4net还有3个自己的格式Formatter。 它们是 "ABSOLUTE", "DATE"和"ISO8601"分别代表 AbsoluteTimeDateFormatter, DateTimeDateFormatter和Iso8601DateFormatter。例如: %date{ISO8601}或%date{ABSOLUTE}。

它们的性能要好于ToString。

w

等价于 username

x

等价于 ndc

X

等价于 mdc

%

%%输出一个百分号

关于调用本地信息(caller location information)的说明:

%type %file %line %method %location %class %C %F %L %l %M 都会调用本地信息。这样做会影响性能。本地信息使用System.Diagnostics.StackTrace得到。.Net 1.0 不支持System.Diagnostics.StackTrace 类。

本地信息在调试模式下可以正常获取,在非调试模式下可能获取不到,或只能获取一部分。(根据我的测试,其实是需要有一个程序数据库(.pdb)文件。)

%property属性要用代码来设置才能使用(也就是扩展一下),

默认属性log4net:HostName不用设置。

转义字符的修饰符:

Format modifier

left justify

minimum width

maximum width

comment

%20logger

false

20

none

如果logger名不足20个字符,就在左边补空格。

%-20logger

true

20

none

如果logger名不足20个字符,就在右边补空格。

%.30logger

NA

none

30

超过30个字符将截断。

%20.30logger

false

20

30

logger名要在20到30之间,少了在左边补空格,多了截断。

%-20.30logger

true

20

30

logger名要在20到30之间,少了在右边补空格,多了截断。

8.2Layout类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net.Layout;
using log4net.Layout.Pattern;
using System.Reflection;
using System.Collections;
using FastReflectionLib;
 
namespace TGLog.ExpandLayout2
{
    public class ReflectionLayout : PatternLayout
    {
        public ReflectionLayout()
        {
            this.AddConverter("property", typeof(ReflectionPatternConverter));
        }
    }
 
    public class ReflectionPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(
System.IO.TextWriter writer,
 log4net.Core.LoggingEvent loggingEvent
)
        {
            if (Option != null)
            {
                // 写入指定键的值
                WriteObject(
writer,
 loggingEvent.Repository,
 LookupProperty(Option,
 loggingEvent)
);
            }
            else
            {
                // 写入所有关键值对
                WriteDictionary(
writer,
loggingEvent.Repository,
 loggingEvent.GetProperties()
);
            }
        }
 
        /// <summary>
        /// 通过反射获取传入的日志对象的某个属性的值
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        private object LookupProperty(
string property,
 log4net.Core.LoggingEvent loggingEvent)
        {
            object propertyValue = string.Empty;
 
            PropertyInfo propertyInfo =
loggingEvent.MessageObject.GetType().GetProperty(property);
            if (propertyInfo != null)
            {
                propertyValue =
propertyInfo.GetValue(loggingEvent.MessageObject, null);
            }
            return propertyValue;
        }
    }
}


8.3 MyLogImpl类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net.Core;
 
namespace TGLog.ExpandILog
{
    public class MyLogImpl : LogImpl, IMyLog
    {
        /// <summary>
        /// The fully qualified name of this declaring type not the type of any subclass.
        /// </summary>
        private readonly static Type ThisDeclaringType = typeof(MyLogImpl);
 
        public MyLogImpl(ILogger logger)
            : base(logger)
        {       
        }
 
        #region Implementation of IMyLog
 
        public void Debug(int operatorID, string operand, int actionType,object message,
 string ip, string browser, string machineName)
        {
            Debug(operatorID,  operand,  actionType, message,
  ip,  browser, machineName, null);
        }
 
        public void Debug(int operatorID, string operand, int actionType,object message,
string ip, string browser, string machineName, System.Exception t)
        {
            if (this.IsDebugEnabled)
            {
                LoggingEvent loggingEvent =
new LoggingEvent(ThisDeclaringType, Logger.Repository,
                                       Logger.Name, Level.Info, message, t);
                loggingEvent.Properties["Operator"] = operatorID;
                loggingEvent.Properties["Operand"] = operand;
                loggingEvent.Properties["ActionType"] = actionType;
                loggingEvent.Properties["IP"] = ip;
                loggingEvent.Properties["Browser"] = browser;
                loggingEvent.Properties["MachineName"] = machineName;
                Logger.Log(loggingEvent);
            }
        }
 
        public void Info(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName)
        {
            Info(operatorID, operand, actionType, message, ip, browser, machineName, null);
        }
 
        public void Info(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName, System.Exception t)
        {
            if (this.IsInfoEnabled)
            {
                LoggingEvent loggingEvent =
 new LoggingEvent(ThisDeclaringType, Logger.Repository,
 Logger.Name, Level.Info, message, t);
                loggingEvent.Properties["Operator"] = operatorID;
                loggingEvent.Properties["Operand"] = operand;
                loggingEvent.Properties["ActionType"] = actionType;
                loggingEvent.Properties["IP"] = ip;
                loggingEvent.Properties["Browser"] = browser;
                loggingEvent.Properties["MachineName"] = machineName;
                Logger.Log(loggingEvent);
            }
        }
 
        public void Warn(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName)
        {
            Warn(operatorID, operand, actionType, message, ip, browser, machineName, null);
        }
 
        public void Warn(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName, System.Exception t)
        {
            if (this.IsWarnEnabled)
            {
                LoggingEvent loggingEvent =
 new LoggingEvent(ThisDeclaringType, Logger.Repository,
Logger.Name, Level.Info, message, t);
                loggingEvent.Properties["Operator"] = operatorID;
                loggingEvent.Properties["Operand"] = operand;
                loggingEvent.Properties["ActionType"] = actionType;
                loggingEvent.Properties["IP"] = ip;
                loggingEvent.Properties["Browser"] = browser;
                loggingEvent.Properties["MachineName"] = machineName;
                Logger.Log(loggingEvent);
            }
        }
 
        public void Error(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName)
        {
            Error(operatorID, operand, actionType, message, ip, browser, machineName, null);
        }
 
        public void Error(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName, System.Exception t)
        {
            if (this.IsErrorEnabled)
            {
                LoggingEvent loggingEvent =
 new LoggingEvent(ThisDeclaringType, Logger.Repository,
 Logger.Name, Level.Info, message, t);
                loggingEvent.Properties["Operator"] = operatorID;
                loggingEvent.Properties["Operand"] = operand;
                loggingEvent.Properties["ActionType"] = actionType;
                loggingEvent.Properties["IP"] = ip;
                loggingEvent.Properties["Browser"] = browser;
                loggingEvent.Properties["MachineName"] = machineName;
                Logger.Log(loggingEvent);
            }
        }
 
        public void Fatal(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName)
        {
            Fatal(operatorID, operand, actionType, message, ip, browser, machineName, null);
        }
 
        public void Fatal(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName, System.Exception t)
        {
            if (this.IsFatalEnabled)
            {
                LoggingEvent loggingEvent =
 new LoggingEvent(ThisDeclaringType, Logger.Repository,
                                       Logger.Name, Level.Info, message, t);
                loggingEvent.Properties["Operator"] = operatorID;
                loggingEvent.Properties["Operand"] = operand;
                loggingEvent.Properties["ActionType"] = actionType;
                loggingEvent.Properties["IP"] = ip;
                loggingEvent.Properties["Browser"] = browser;
                loggingEvent.Properties["MachineName"] = machineName;
                Logger.Log(loggingEvent);
            }
        }
        #endregion Implementation of IMyLog
    }
}


 

8.4 MyLogManager类代码

#region Copyright & License
//
// Copyright 2001-2005 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
 
using System;
using System.Reflection;
using System.Collections;
using log4net;
using log4net.Core;
using log4net.Repository;
using log4net.Repository.Hierarchy;
 
namespace TGLog.ExpandILog
{
    public class MyLogManager
    {
        #region Static Member Variables
 
        /// <summary>
        /// The wrapper map to use to hold the <see cref="EventIDLogImpl"/> objects
        /// </summary>
        private static readonly WrapperMap s_wrapperMap = new WrapperMap(new WrapperCreationHandler(WrapperCreationHandler));
 
        #endregion
 
        #region Constructor
 
        /// <summary>
        /// Private constructor to prevent object creation
        /// </summary>
        private MyLogManager() { }
 
        #endregion
 
        #region Type Specific Manager Methods
 
        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the default hierarchy) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IMyLog Exists(string name)
        {
            return Exists(Assembly.GetCallingAssembly(), name);
        }
 
        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the specified domain) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IMyLog Exists(string domain, string name)
        {
            return WrapLogger(LoggerManager.Exists(domain, name));
        }
 
        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the specified assembly's domain) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IMyLog Exists(Assembly assembly, string name)
        {
            return WrapLogger(LoggerManager.Exists(assembly, name));
        }
 
        /// <summary>
        /// Returns all the currently defined loggers in the default domain.
        /// </summary>
        /// <remarks>
        /// <para>The root logger is <b>not</b> included in the returned array.</para>
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IMyLog[] GetCurrentLoggers()
        {
            return GetCurrentLoggers(Assembly.GetCallingAssembly());
        }
 
        /// <summary>
        /// Returns all the currently defined loggers in the specified domain.
        /// </summary>
        /// <param name="domain">the domain to lookup in</param>
        /// <remarks>
        /// The root logger is <b>not</b> included in the returned array.
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IMyLog[] GetCurrentLoggers(string domain)
        {
            return WrapLoggers(LoggerManager.GetCurrentLoggers(domain));
        }
 
        /// <summary>
        /// Returns all the currently defined loggers in the specified assembly's domain.
        /// </summary>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <remarks>
        /// The root logger is <b>not</b> included in the returned array.
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IMyLog[] GetCurrentLoggers(Assembly assembly)
        {
            return WrapLoggers(LoggerManager.GetCurrentLoggers(assembly));
        }
 
        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        ///
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(string name)
        {
            return GetLogger(Assembly.GetCallingAssembly(), name);
        }
 
        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        ///
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(string domain, string name)
        {
            return WrapLogger(LoggerManager.GetLogger(domain, name));
        }
 
        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        ///
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(Assembly assembly, string name)
        {
            return WrapLogger(LoggerManager.GetLogger(assembly, name));
        }
 
        /// <summary>
        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.
        /// </summary>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        /// <param name="type">The full name of <paramref name="type"/> will
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(Type type)
        {
            return GetLogger(Assembly.GetCallingAssembly(), type.FullName);
        }
 
        /// <summary>
        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.
        /// </summary>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="type">The full name of <paramref name="type"/> will
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(string domain, Type type)
        {
            return WrapLogger(LoggerManager.GetLogger(domain, type));
        }
 
        /// <summary>
        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.
        /// </summary>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="type">The full name of <paramref name="type"/> will
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IMyLog GetLogger(Assembly assembly, Type type)
        {
            return WrapLogger(LoggerManager.GetLogger(assembly, type));
        }
 
        #endregion
 
        #region Extension Handlers
 
        /// <summary>
        /// Lookup the wrapper object for the logger specified
        /// </summary>
        /// <param name="logger">the logger to get the wrapper for</param>
        /// <returns>the wrapper for the logger specified</returns>
        private static IMyLog WrapLogger(ILogger logger)
        {
            return (IMyLog)s_wrapperMap.GetWrapper(logger);
        }
 
        /// <summary>
        /// Lookup the wrapper objects for the loggers specified
        /// </summary>
        /// <param name="loggers">the loggers to get the wrappers for</param>
        /// <returns>Lookup the wrapper objects for the loggers specified</returns>
        private static IMyLog[] WrapLoggers(ILogger[] loggers)
        {
            IMyLog[] results = new IMyLog[loggers.Length];
            for (int i = 0; i < loggers.Length; i++)
            {
                results[i] = WrapLogger(loggers[i]);
            }
            return results;
        }
 
        /// <summary>
        /// Method to create the <see cref="ILoggerWrapper"/> objects used by
        /// this manager.
        /// </summary>
        /// <param name="logger">The logger to wrap</param>
        /// <returns>The wrapper for the logger specified</returns>
        private static ILoggerWrapper WrapperCreationHandler(ILogger logger)
        {
            return new MyLogImpl(logger);
        }
        #endregion
    }
}


8.5 IMyLog类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
 
namespace TGLog.ExpandILog
{
    public interface IMyLog : ILog
    {
        void Debug(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName);
        void Debug(int operatorID, string operand, int actionType,object message,
string ip, string browser, string machineName, Exception t);
 
        void Info(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName);
        void Info(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName, Exception t);
 
        void Warn(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName);
        void Warn(int operatorID, string operand, int actionType, object message,
 string ip, string browser, string machineName, Exception t);
 
        void Error(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName);
        void Error(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName, Exception t);
 
        void Fatal(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName);
        void Fatal(int operatorID, string operand, int actionType, object message,
string ip, string browser, string machineName, Exception t);
    }
}


你可能感兴趣的:(Log4net创建日志及简单扩展 (二))