最近将项目的异常日志模块改造成log4net。在Asp.net MVC3 中的改造非常简单,我们只要继承HandleErrorAttribute类使用自定义类,
使用特性即可统一处理MVC controller 下的 所有的Action 方法的异常。无须try ... catch.... 详情请见我的这篇随笔
http://www.cnblogs.com/ryanding/archive/2010/11/16/1878168.html。我们只要在上文的CustomHandleErrorAttribute方法内植入Log4Net 即可。
具体的留给读者自己去实践了。本文主要讲解如何通过代码配置Log4Net。将程序的异常信息保存到相关文件以及SQLSERVER数据库。
这里需要提下,将异常存储在文件中的好处就是如果sqlserver出现异常或者网络出现异常。就无法确保将异常正常保存到数据库,
此时异常信息依然会被本地文件记录在案。对于Log4Net 这个开源库我们就不讨论其XML配置。这里着重讲解用代码如何启用Log4Net。
具体配置代码如下:
public static class Log4netHelper
{
//记录异常日志数据库连接字符串
private const string _ConnectionString = @"data source=your server;initial catalog=your db;integrated security=false;persist security info=True;User ID=sa;Password=1111";
/// <summary>
/// 使用SQLSERVER记录异常日志
/// </summary>
/// <Author>Ryanding</Author>
/// <date>2011-05-01</date>
public static void LoadADONetAppender()
{
LoadFileAppender();
log4net.Repository.Hierarchy.Hierarchy hier =
log4net.LogManager.GetLoggerRepository() as log4net.Repository.Hierarchy.Hierarchy;
if (hier != null)
{
log4net.Appender.AdoNetAppender adoAppender = new log4net.Appender.AdoNetAppender();
adoAppender.Name = "AdoNetAppender";
adoAppender.CommandType = CommandType.Text;
adoAppender.BufferSize = 1;
adoAppender.ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
adoAppender.ConnectionString = _ConnectionString;
adoAppender.CommandText = @"INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)";
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_date", DbType = System.Data.DbType.DateTime, Layout = new log4net.Layout.RawTimeStampLayout() });
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@thread", DbType = System.Data.DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%thread")) });
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_level", DbType = System.Data.DbType.String, Size = 50, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level")) });
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@logger", DbType = System.Data.DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger")) });
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@message", DbType = System.Data.DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%message")) });
adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@exception", DbType = System.Data.DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new ExceptionLayout()) });
adoAppender.ActivateOptions();
BasicConfigurator.Configure(adoAppender);
}
}
/// <summary>
/// 使用文本记录异常日志
/// </summary>
/// <Author>Ryanding</Author>
/// <date>2011-05-01</date>
public static void LoadFileAppender()
{
string currentPath = AppDomain.CurrentDomain.BaseDirectory;
string txtLogPath = string.Empty;
string iisBinPath = AppDomain.CurrentDomain.RelativeSearchPath;
if (!string.IsNullOrEmpty(iisBinPath))
txtLogPath = Path.Combine(iisBinPath, "ErrorLog.txt");
else
txtLogPath = Path.Combine(currentPath, "ErrorLog.txt");
log4net.Repository.Hierarchy.Hierarchy hier =
log4net.LogManager.GetLoggerRepository() as log4net.Repository.Hierarchy.Hierarchy;
FileAppender fileAppender = new FileAppender();
fileAppender.Name = "LogFileAppender";
fileAppender.File = txtLogPath;
fileAppender.AppendToFile = true;
PatternLayout patternLayout = new PatternLayout();
patternLayout.ConversionPattern = "记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline";
patternLayout.ActivateOptions();
fileAppender.Layout = patternLayout;
//选择UTF8编码,确保中文不乱码。
fileAppender.Encoding = Encoding.UTF8;
fileAppender.ActivateOptions();
BasicConfigurator.Configure(fileAppender);
}
/// <summary>
/// 异常处理
/// </summary>
/// <param name="methedType">出现异常方法的类型。例如:MethodBase.GetCurrentMethod().DeclaringType</param>
/// <param name="errorMsg">错误信息。例如:SaveBuildingPhoto方法出错。Author:开发者名称</param>
/// <param name="ex"></param>
public static void InvokeErrorLog(Type methedType, string errorMsg, Exception ex)
{
LoadADONetAppender();
ILog log = log4net.LogManager.GetLogger(methedType);
log.Info(errorMsg, ex);
}
}
在您的数据库执行以下脚本:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID (N ' [dbo].[Log] ' ) AND type in (N ' U ' )) BEGIN CREATE TABLE [ dbo ] . [ Log ] ( [ Id ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL , [ Date ] [ datetime ] NOT NULL , [ Thread ] [ varchar ] ( 255 ) NULL , [ Level ] [ varchar ] ( 50 ) NULL , [ Logger ] [ varchar ] ( 255 ) NULL , [ Message ] [ varchar ] ( 4000 ) NULL , [ Exception ] [ varchar ] ( 4000 ) NULL , PRIMARY KEY CLUSTERED ( [ Id ] ASC ) WITH (PAD_INDEX = OFF , IGNORE_DUP_KEY = OFF ) ON [ PRIMARY ] ) ON [ PRIMARY ] END Go
调用如下:
1 public bool Login( string userName, string password) 2 { 3 try 4 { 5 // TODO: 6 7 } 8 catch (Exception ex) 9 { 10 Log4netHelper.InvokeErrorLog(MethodBase.GetCurrentMethod().DeclaringType, " 登录方法Login出错-Author:ryanding " , ex); 11 return false ; 12 } 13 }