使用Common.Logging 1.2实现Logging(一)Common.Logging、log4net

Common.Logging

Common.Logging是一个通用日志接口,具体实现可采用log4net、EntLib的日志、NLog等。

接口定义

Common.Logging.ILoggerFactoryAdapter接口

public interface ILoggerFactoryAdapter
{
ILog GetLogger(string name);
ILog GetLogger(Type type);
}

Common.Logging.ILog接口

public interface ILog
{
bool IsDebugEnabled { get; }
bool IsErrorEnabled { get; }
bool IsFatalEnabled { get; }
bool IsInfoEnabled { get; }
bool IsTraceEnabled { get; }
bool IsWarnEnabled { get; }

void Debug(object message);
void Debug(object message, Exception exception);
void Error(object message);
void Error(object message, Exception exception);
void Fatal(object message);
void Fatal(object message, Exception exception);
void Info(object message);
void Info(object message, Exception exception);
void Trace(object message);
void Trace(object message, Exception exception);
void Warn(object message);
void Warn(object message, Exception exception);
}

log4net

log4net是一个第三方开源组件,它设计的主要目的是组合,生成日志信息,同时将配置保存到各种存储介质或者展现平台中,在实际项目中,Log4net 可以保存系统运行情况,可以在系统出现异常时,根据保存的日志信息,查看当时系统的状态。
log4net是Log4j的.NET版本,用C#编写,它与Log4j一样,具有可配置性灵活、线程安全、对日志的级别管理方便等优点。

log4net的优点

几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后,就不太可能再利用专门的调试工具了。然而一个管理员可能需要有一套强大的日志系统来诊断和修复配置上的问题。
经验表明,日志记录往往是软件开发周期中的重要组成部分。它具有以下几个优点:它可以提供应用程序运行时的精确环境,可供开发人员尽快找到应用程序中的Bug;一旦在程序中加入了Log 输出代码,程序运行过程中就能生成并输出日志信息而无需人工干预。另外,日志信息可以输出到不同的地方(控制台,文件等)以备以后研究之用。
Log4net就是为这样一个目的设计的,用于.NET开发环境的日志记录包。

Log4net的结构

log4net 有四种主要的组件,分别是Logger(记录器), Repository(库), Appender(附着器)以及 Layout(布局).

  • Logger是应用程序需要交互的主要组件,它用来产生日志消息。产生的日志消息并不直接显示,还要预先经过Layout的格式化处理后才会输出。 Logger提供了多种方式来记录一个日志消息,你可以在你的应用程序里创建多个Logger,每个实例化的Logger对象都被log4net框架作为命名实体(named entity)来维护。这意味着为了重用Logger对象,你不必将它在不同的类或对象间传递,只需要用它的名字为参数调用就可以了。log4net框架使用继承体系,继承体系类似于.NET中的名字空间。也就是说,如果有两个logger,分别被定义为a.b.c和a.b,那么我们说a.b是a.b.c的祖先。每一个logger都继承了祖先的属性
  • Repository主要用于负责日志对象组织结构的维护。在log4net的以前版本中,框架仅支持分等级的组织结构(hierarchical organization)。这种等级结构本质上是库的一个实现,并且定义在log4net.Repository.Hierarchy 名字空间中。要实现一个Repository,需要实现log4net.Repository.ILoggerRepository 接口。但是通常并不是直接实现该接口,而是以log4net.Repository.LoggerRepositorySkeleton为基类继承。体系库 (hierarchical repository )则由log4net.Repository.Hierarchy.Hierarchy类实现。如果你是个log4net框架的使用者,而非扩展者,那么你几乎不会在你的代码里用到Repository的类。相反的,你需要用到LogManager类来自动管理库和日志对象。
  • Appender定义输出介质。。一个好的日志框架应该能够产生多目的地的输出。比如说输出到控制台或保存到一个日志文件。log4net 能够很好的满足这些要求。它使用一个叫做Appender的组件来定义输出介质。正如名字所示,这些组件把它们附加到Logger日志组件上并将输出传递到输出流中。你可以把多个Appender组件附加到一个日志对象上。 Log4net框架提供了几个Appender组件。关于log4net提供的Appender组件的完整列表可以在log4net框架的帮助手册中找到。有了这些现成的Appender组件,一般来说你没有必要再自己编写了。但是如果你愿意,可以从log4net.Appender.AppenderSkeleton类继承。一个Appender 对象缺省地将所有的日志事件传递到输出流。Appender的过滤器(Appender Filters) 可以按照不同的标准过滤日志事件。在log4net.Filter的名字空间下已经有几个预定义的过滤器。使用这些过滤器,你可以按照日志级别范围过滤日志事件,或者按照某个特殊的字符串进行过滤。你可以在API的帮助文件中发现更多关于过滤器的信息。
  • Layout 组件用于向用户显示最后经过格式化的输出信息。输出信息可以以多种格式显示,主要依赖于我们采用的Layout组件类型。可以是线性的或一个XML文件。Layout组件和一个Appender组件一起工作。API帮助手册中有关于不同Layout组件的列表。一个Appender对象,只能对应一个Layout对象。要实现你自己的Layout类,你需要从log4net.Layout.LayoutSkeleton类继承,它实现了ILayout接口。

MVCQuick的Logging

Common.Logging、log4net通常使用xml进行配置,在MVCQuick中使用编程方式进行配置。

实现代码

using System;s

namespace MVCQuick.Framework.Logging
{
///<summary>
/// The 7 possible logging levels
///</summary>
///<author>Gilles Bayon</author>
public enum LogLevel
{
///<summary>
/// All logging levels
///</summary>
All = 0,
///<summary>
/// A trace logging level
///</summary>
Trace = 1,
///<summary>
/// A debug logging level
///</summary>
Debug = 2,
///<summary>
/// A info logging level
///</summary>
Info = 3,
///<summary>
/// A warn logging level
///</summary>
Warn = 4,
///<summary>
/// An error logging level
///</summary>
Error = 5,
///<summary>
/// A fatal logging level
///</summary>
Fatal = 6,
///<summary>
/// Do not log anything.
///</summary>
Off = 7,
}
}

 

using System;

namespace MVCQuick.Framework.Logging
{
public class Log4NetLogger : Common.Logging.ILog
{
private log4net.Core.ILogger _logger = null;
private static readonly Type declaringType = typeof(Log4NetLogger);
public bool IsInfoEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Info);
}
}
public bool IsWarnEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Warn);
}
}
public bool IsErrorEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Error);
}
}
public bool IsFatalEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Fatal);
}
}
public bool IsDebugEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Debug);
}
}
public bool IsTraceEnabled
{
get
{
return this._logger.IsEnabledFor(log4net.Core.Level.Trace);
}
}
internal Log4NetLogger(log4net.ILog log)
{
this._logger = log.Logger;
}
public void Info(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Info, message, e);
}
public void Info(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Info, message, null);
}
public void Debug(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Debug, message, e);
}
public void Debug(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Debug, message, null);
}
public void Warn(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Warn, message, e);
}
public void Warn(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Warn, message, null);
}
public void Trace(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Trace, message, e);
}
public void Trace(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Trace, message, null);
}
public void Fatal(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Fatal, message, e);
}
public void Fatal(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Fatal, message, null);
}
public void Error(object message, Exception e)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Error, message, e);
}
public void Error(object message)
{
this._logger.Log(Log4NetLogger.declaringType, log4net.Core.Level.Error, message, null);
}

}
}

 

using System;

namespace MVCQuick.Framework.Logging
{
public class Log4NetLoggerFactoryAdapter : Common.Logging.ILoggerFactoryAdapter
{
public Log4NetLoggerFactoryAdapter()
{

}

public Common.Logging.ILog GetLogger(string name)
{
return new Log4NetLogger(log4net.LogManager.GetLogger(name));
}

public Common.Logging.ILog GetLogger(Type type)
{
return new Log4NetLogger(log4net.LogManager.GetLogger(type));
}
}
}
using System;

namespace MVCQuick.Framework.Logging
{
public class Logger
{
private Common.Logging.ILog log;

public Logger()
{

}

public static void ConfigureConsoleOut()
{
Common.Logging.LogManager.Adapter =
new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter();
}


public static void ConfigureTrace()
{
Common.Logging.LogManager.Adapter =
new Common.Logging.Simple.TraceLoggerFactoryAdapter();
}


public static void ConfigureLog4Net(string filelogPath,
LogLevel displayLogLevel, LogLevel saveLogLevel)
{
log4net.Repository.Hierarchy.Logger root =
((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root;

root.AddAppender(GetConsoleAppender(GetLog4NetLevel(displayLogLevel)));
root.AddAppender(GetTraceAppender(GetLog4NetLevel(displayLogLevel)));
root.AddAppender(GetSiteFileAppender(filelogPath, GetLog4NetLevel(saveLogLevel)));
root.Repository.Configured = true;

log4net.Repository.Hierarchy.Logger nhibernate =
(log4net.Repository.Hierarchy.Logger)log4net.LogManager.GetLogger("NHibernate").Logger;
nhibernate.AddAppender(GetNHibernateFileAppender(filelogPath, GetLog4NetLevel(saveLogLevel)));
nhibernate.Additivity = false;
nhibernate.Repository.Configured = true;

log4net.Repository.Hierarchy.Logger spring =
(log4net.Repository.Hierarchy.Logger)log4net.LogManager.GetLogger("Spring").Logger;
spring.AddAppender(GetSpringFileAppender(filelogPath, GetLog4NetLevel(saveLogLevel)));
spring.Additivity = false;
spring.Repository.Configured = true;


Common.Logging.LogManager.Adapter = new Log4NetLoggerFactoryAdapter();
}



public static Logger GetLogger(string name)
{
Logger logger = new Logger();
logger.log = Common.Logging.LogManager.GetLogger(name);

return logger;
}

public static Logger GetLogger(Type type)
{
Logger logger = new Logger();
logger.log = Common.Logging.LogManager.GetLogger(type);

return logger;
}

public void Debug(object message)
{
log.Debug(message);
}

public void Debug(object message, Exception exception)
{
log.Debug(message, exception);
}



public void Error(object message)
{
log.Error(message);
}

public void Error(object message, Exception exception)
{
log.Error(message, exception);
}

public void Fatal(object message)
{
log.Fatal(message);
}

public void Fatal(object message, Exception exception)
{
log.Fatal(message, exception);
}


public void Info(object message)
{
log.Info(message);
}

public void Info(object message, Exception exception)
{
log.Info(message, exception);
}

public void Warn(object message)
{
log.Warn(message);
}

public void Warn(object message, Exception exception)
{
log.Warn(message, exception);
}

#region log4net

private static log4net.Appender.ConsoleAppender GetConsoleAppender(
log4net.Core.Level consoleLogLevel)
{
log4net.Appender.ConsoleAppender appender = new log4net.Appender.ConsoleAppender();
appender.Name = "Console";
appender.Layout = new log4net.Layout.PatternLayout(
"%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n");
appender.Threshold = consoleLogLevel;
appender.ActivateOptions();

return appender;
}

private static log4net.Appender.TraceAppender GetTraceAppender(
log4net.Core.Level traceLogLevel)
{
log4net.Appender.TraceAppender appender = new log4net.Appender.TraceAppender();
appender.Name = "Trace";
appender.Layout = new log4net.Layout.PatternLayout(
"%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n");
appender.Threshold = traceLogLevel;
appender.ActivateOptions();

return appender;
}



private static log4net.Appender.FileAppender GetSiteFileAppender(
string filelogPath, log4net.Core.Level fileLogLevel)
{
log4net.Appender.RollingFileAppender appender = new log4net.Appender.RollingFileAppender();
appender.Name = "SiteLog";
appender.AppendToFile = true;
appender.File = filelogPath + "\\Site.log";
appender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Size;
appender.MaxSizeRollBackups = 10;
appender.MaximumFileSize = "10MB";
appender.StaticLogFileName = true;
appender.Layout = new log4net.Layout.PatternLayout(
"%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n");
appender.Threshold = fileLogLevel;
appender.ActivateOptions();

return appender;
}

private static log4net.Appender.FileAppender GetNHibernateFileAppender(
string filelogPath, log4net.Core.Level fileLogLevel)
{
log4net.Appender.RollingFileAppender appender = new log4net.Appender.RollingFileAppender();
appender.Name = "NHibernateLog";
appender.AppendToFile = true;
appender.File = filelogPath + "\\NHibernate.log";
appender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Size;
appender.MaxSizeRollBackups = 10;
appender.MaximumFileSize = "10MB";
appender.StaticLogFileName = true;
appender.Layout = new log4net.Layout.PatternLayout(
"%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n");
appender.Threshold = fileLogLevel;
appender.ActivateOptions();

return appender;
}

private static log4net.Appender.FileAppender GetSpringFileAppender(
string filelogPath, log4net.Core.Level fileLogLevel)
{
log4net.Appender.RollingFileAppender appender = new log4net.Appender.RollingFileAppender();
appender.Name = "SpringLog";
appender.AppendToFile = true;
appender.File = filelogPath + "\\Spring.log";
appender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Size;
appender.MaxSizeRollBackups = 10;
appender.MaximumFileSize = "10MB";
appender.StaticLogFileName = true;
appender.Layout = new log4net.Layout.PatternLayout(
"%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n");
appender.Threshold = fileLogLevel;
appender.ActivateOptions();

return appender;
}

private static log4net.Core.Level GetLog4NetLevel(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.All:
return log4net.Core.Level.All;
case LogLevel.Trace:
return log4net.Core.Level.Trace;
case LogLevel.Debug:
return log4net.Core.Level.Debug;
case LogLevel.Info:
return log4net.Core.Level.Info;
case LogLevel.Warn:
return log4net.Core.Level.Warn;
case LogLevel.Error:
return log4net.Core.Level.Error;
case LogLevel.Fatal:
return log4net.Core.Level.Fatal;
default:
throw new ArgumentOutOfRangeException("logLevel", logLevel, "unknown log level");
}

#endregion log4net
}
}
}

单元测试代码

using System;
using NUnit.Framework;
using MVCQuick.Framework.Logging;

namespace MVCQuick.Framework.Tests
{
[TestFixture]
public class LoggingTests
{
[Test]
public void LoggerTest()
{
Logger.ConfigureLog4Net("C:", LogLevel.Debug, LogLevel.Warn);

Logger logger = Logger.GetLogger(typeof(LoggingTests));
logger.Debug("Debug");
logger.Error("Error");
logger.Fatal("Fatal");
logger.Info("Info");
logger.Warn("warn");
}
}
}

测试结果



 

源代码下载:http://mvcquick.codeplex.com/  

posted @ 2011-10-17 10:43  GuYoung  阅读(4382)  评论(0编辑  收藏  举报