团队开发框架实战—日志记录
log4net简介
几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后,就不太可能再利用专门的调试工具了。然而一个管理员可能需要有一套强大的日志系统来诊断和修复配置上的问题。
经验表明,日志记录往往是软件开发周期中的重要组成部分。它具有以下几个优点:它可以提供应用程序运行时的精确环境,可供开发人员尽快找到应用程序中的Bug;一旦在程序中加入了Log 输出代码,程序运行过程中就能生成并输出日志信息而无需人工干预。另外,日志信息可以输出到不同的地方(控制台,文件等)以备以后研究之用。
Log4net就是为这样一个目的设计的,用于.NET开发环境的日志记录包。
log4net是一个功能著名的开源日志记录组件。利用log4net可以方便地将日志信息记录到文件、控制台、Windows事件日志和数据库(包括MS SQL Server, Access, Oracle9i,Oracle8i,DB2,SQLite)中。并且我们还可以记载控制要记载的日志级别,可以记载的日志类别包括:FATAL(致命错误)、ERROR(一般错误)、WARN(警告)、INFO(一般信息)、DEBUG(调试信息)。
Log level
Log level: 日志记录等级,有DEBUG, INFO, WARN, ERROR or FATAL5个。
- Error 记录错误日志
- Fatal 记录严重错误
- Info 记录一般信息
- Debug 记录调试信息
- Warn 记录警告信息
LogSeverity.cs
namespace Tdf.Logging
{
public enum LogSeverity
{
/// <summary>
/// Debug.
/// </summary>
Debug,
/// <summary>
/// Info.
/// </summary>
Info,
/// <summary>
/// Warn.
/// </summary>
Warn,
/// <summary>
/// Error.
/// </summary>
Error,
/// <summary>
/// Fatal.
/// </summary>
Fatal
}
}
IHasLogSeverity.cs
namespace Tdf.Logging
{
public interface IHasLogSeverity
{
LogSeverity Severity { get; set; }
}
}
配置log4net参数
本实例中是控制台应用程序,配置如下(附各配置的说明):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
</configSections>
<appSettings>
</appSettings>
<log4net debug="false">
<!--按日期分割日志文件 一天一个-->
<appender name="LogFileAppenderByDate" type="log4net.Appender.RollingFileAppender" >
<!--是否续写-->
<param name="AppendToFile" value="true" />
<!--最小锁定模型以允许多个进程可以写入同一个文件-->
<param name="LockingModel" value="log4net.Appender.FileAppender.MinimalLock" />
<param name="StaticLogFileName" value="true" />
<!--保存路径-->
<param name="File" value="d:\Log\\" />
<param name="DatePattern" value="yyyy-MM-dd.LOG" />
<param name="StaticLogFileName" value="false" />
<param name="RollingStyle" value="Date" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="时间:%d %n级别:%level %n类名:%c%n文件:%F 第%L行%n日志内容:%m%n-----------------------------------------%n%n" />
</layout>
</appender>
<!--按日志容量分割日志文件 10KB一个-->
<appender name="LogFileAppenderBySize" type="log4net.Appender.RollingFileAppender" >
<!--是否续写-->
<param name="AppendToFile" value="true" />
<!--最小锁定模型以允许多个进程可以写入同一个文件-->
<param name="LockingModel" value="log4net.Appender.FileAppender.MinimalLock" />
<param name="StaticLogFileName" value="true" />
<!--按照文件的大小进行变换日志文件-->
<param name="RollingStyle" value="Size" />
<param name="File" value="log.txt" />
<!--单个文件最大数量 好像只有在 按Size分割时有效-->
<param name="MaximumFileSize" value="200KB"/>
<!--保留的log文件数量 超过此数量后 自动删除之前的 好像只有在 按Size分割时有效-->
<param name="MaxSizeRollBackups" value="2" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="发生时间:%d %n事件级别:%level %n相关类名:%c%n程序文件:%F 第%L行%n日志内容:%m%n-----------------------------------------%n%n" />
</layout>
</appender>
<!--记录日志到数据库-->
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<!--缓冲大小-->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=.\SQLEXPRESS;Initial Catalog=CVDS;User ID=sa;Password=sasa" />
<commandText value="INSERT INTO Log([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="INFO" />
<!--启用按日期分割-->
<appender-ref ref="LogFileAppenderByDate" />
<!--启用按容量分割-->
<!--<appender-ref ref="LogFileAppenderBySize" />-->
<!--启用保存到数据库-->
<!--<appender-ref ref="AdoNetAppender" />-->
</root>
</log4net>
</configuration>
日志记录类LogHelper
完成配置之后就可以进行在程序中调用了,为了方便调用,我定义了一个日志记录类LogHelper,具体代码如下:
using log4net;
using System;
// 注意下面的语句一定要加上,指定log4net使用.config文件来读取配置信息
// 如果是WinForm(假定程序为Tdf.ConsoleApplication.exe,则需要一个Tdf.ConsoleApplication.exe.config文件)
// 如果是WebForm,则从web.config中读取相关信息
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Tdf.Logging
{
public class LogHelper
{
private ILog logger;
public LogHelper(ILog log)
{
this.logger = log;
}
public void Info(object message)
{
this.logger.Info(message);
}
public void Info(object message, Exception e)
{
this.logger.Info(message, e);
}
public void Debug(object message)
{
this.logger.Debug(message);
}
public void Debug(object message, Exception e)
{
this.logger.Debug(message, e);
}
public void Warning(object message)
{
this.logger.Warn(message);
}
public void Warning(object message, Exception e)
{
this.logger.Warn(message, e);
}
public void Error(object message)
{
this.logger.Error(message);
}
public void Error(object message, Exception e)
{
this.logger.Error(message, e);
}
public void Fatal(object message)
{
this.logger.Fatal(message);
}
public void Fatal(object message, Exception e)
{
this.logger.Fatal(message, e);
}
public class LogFactory
{
static LogFactory()
{
}
public static LogHelper GetLogger(Type type)
{
return new LogHelper(LogManager.GetLogger(type));
}
public static LogHelper GetLogger(string str)
{
return new LogHelper(LogManager.GetLogger(str));
}
}
}
}
Program.cs
程序文件Program.cs具体代码如下:
using System;
using System.Reflection;
using Tdf.Logging;
namespace Tdf.ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
// 创建日志记录组件实例
LogHelper log = LogHelper.LogFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// 记录错误日志
log.Error("error", new Exception("发生了一个异常"));
// 记录严重错误
log.Fatal("fatal", new Exception("发生了一个致命错误"));
// 记录一般信息
log.Info("info");
// 记录调试信息
log.Debug("debug");
//记录警告信息
log.Warning("warn");
Console.WriteLine("日志记录完毕。");
Console.Read();
}
}
}
运行结果
控制台上的输出