使用日志元件log4net記錄異常日志
到達效果:
在控制器層自動捕獲錯誤,并把錯誤儲存到資料庫,之後顯示希望使用者看到的錯誤頁面
1 首先安裝log4net
(1)“程式包管理器控制台”用指令安裝:先要打開控制台,在“工具”→“NuGet程式包管理器”→“程式包管理器控制台”這樣就可以打開程式包管理器控制台。

(2)也可以在項目中添加對log4net.dll的引用
2 配置日志檔案
1 。
如果是CS程式,則在預設的App.config檔案(沒有建立一個)中添加内容;如果是BS程式,則添加到Web.config檔案中
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
</log4net>
再按照以下添加檔案方式配置
2 添加日志的配置檔案Log4net.xml,再從後面通過Log4netHelper幫助類執行個體化
日志類型
Appenders
Appenders用來定義日志的輸出方式,
經常使用的輸出方式有:
AdoNetAppender 将日志記錄到資料庫中。可以采用SQL和存儲過程兩種方式。
FileAppender 将日志輸出到檔案。
代碼如下:
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
</appender>
定義日志的類型
可以按照本地檔案的日志記錄,比如
<log4net>
<!--錯誤日志類-->
<logger name="logerror"><!--日志類的名字-->
<level value="ALL" /><!--定義記錄的日志級别-->
<appender-ref ref="ErrorAppender" /><!--記錄到哪個媒體中去-->
</logger>
<!--資訊日志類-->
<logger name="loginfo">
<level value="ALL" />
<appender-ref ref="InfoAppender" />
</logger>
<!--錯誤日志附加媒體-->
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"><!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種媒體-->
<param name="File" value="Log\\LogError\\" /><!--日志輸出到exe程式這個相對目錄下-->
<param name="AppendToFile" value="true" /><!--輸出的日志不會覆寫以前的資訊-->
<param name="MaxSizeRollBackups" value="100" /><!--備份檔案的個數-->
<param name="MaxFileSize" value="10240" /><!--當個日志檔案的最大大小-->
<param name="StaticLogFileName" value="false" /><!--是否使用靜态檔案名-->
<param name="DatePattern" value="yyyyMMdd".htm"" /><!--日志檔案名-->
<param name="RollingStyle" value="Date" /><!--檔案建立的方式,這裡是以Date方式建立-->
<!--錯誤日志布局-->
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="<HR COLOR=red>%n異常時間:%d [%t] <BR>%n異常級别:%-5p <BR>%n異 常 類:%c [%x] <BR>%n%m <BR>%n <HR Size=1>" />
</layout>
</appender>
<!--資訊日志附加媒體-->
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\LogInfo\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="10240" />
<param name="MaxSizeRollBackups" value="100" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyyMMdd".htm"" />
<param name="RollingStyle" value="Date" />
<!--資訊日志布局-->
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="<HR COLOR=blue>%n日志時間:%d [%t] <BR>%n日志級别:%-5p <BR>%n日 志 類:%c [%x] <BR>%n%m <BR>%n <HR Size=1>" />
</layout>
</appender>
</log4net>
使用C#代碼初始化lo4net
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(Server.MapPath("~/Web.config")));
3,而我使用的是資料庫的方式,檔案如下:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<logger name="WebExceptionLog">
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
</logger>
<logger name="ServiceExceptionLog">
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
</logger>
<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="{connectionString}" />
<commandText value="INSERT INTO [Log4Net] ([Date],[Host],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @host, @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="@host" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{log4net:HostName}" />
</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="4000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
</log4net>
4 添加本地配置檔案讀取類,通過這個公共類很友善讀取本地配置XML檔案
public class ConfigContext
{
public IConfigService ConfigService { get; set; }
/// <summary>
/// 預設以檔案形式存取配置
/// </summary>
public ConfigContext() : this(new FileConfigService())
{
}
public ConfigContext(IConfigService pageContentConfigService)
{
this.ConfigService = pageContentConfigService;
}
public virtual T Get<T>(string index = null) where T : ConfigFileBase, new()
{
var result = new T();
this.VilidateClusteredByIndex(result, index);
result = this.GetConfigFile<T>(index);
return result;
}
public void Save<T>(T configFile, string index = null) where T : ConfigFileBase
{
this.VilidateClusteredByIndex(configFile, index);
configFile.Save();
var fileName = this.GetConfigFileName<T>(index);
this.ConfigService.SaveConfig(fileName, SerializationHelper.XmlSerialize(configFile));
}
private T GetConfigFile<T>(string index = null) where T : ConfigFileBase, new()
{
var result = new T();
var fileName = this.GetConfigFileName<T>(index);
var content = this.ConfigService.GetConfig(fileName);
if (content == null)
{
this.ConfigService.SaveConfig(fileName, string.Empty);
}
else if (!string.IsNullOrEmpty(content))
{
try
{
result = (T)SerializationHelper.XmlDeserialize(typeof(T), content);
}
catch
{
result = new T();
}
}
return result;
}
public virtual void VilidateClusteredByIndex<T>(T configFile, string index) where T : ConfigFileBase
{
//if (configFile.ClusteredByIndex && string.IsNullOrEmpty(index))
// throw new Exception("調用時沒有提供配置檔案的分區索引");
}
public virtual string GetConfigFileName<T>(string index = null)
{
var fileName = typeof(T).Name;
if (!string.IsNullOrEmpty(index))
fileName = string.Format("{0}_{1}", fileName, index);
return fileName;
}
}
添加log.xml
<?xml version="1.0" encoding="utf-16"?>
<Log xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Log>Data Source=Data Source;Initial Catalog=Catalog;uid=uid;pwd=pwd;MAX Pool Size=512;Min Pool Size=50;Connection Lifetime=30</Log>
</Log>
5.添加Log4netHelper類實列化配置檔案
public static class Log4NetHelper
{
static Log4NetHelper()
{
//初始化log4net配置
var config = CachedConfigContext.Current.ConfigService.GetConfig("log4net");
//重寫log4net配置裡的連接配接字元串
config = config.Replace("{connectionString}", CachedConfigContext.Current.Log);
var ms = new MemoryStream(Encoding.Default.GetBytes(config));
log4net.Config.XmlConfigurator.Configure(ms);
}
public static void Debug(LoggerType loggerType, object message, Exception e)
{
var logger = LogManager.GetLogger(loggerType.ToString());
logger.Debug(SerializeObject(message), e);
}
public static void Error(LoggerType loggerType, object message, Exception e)
{
var logger = LogManager.GetLogger(loggerType.ToString());
logger.Error(SerializeObject(message), e);
}
public static void Info(LoggerType loggerType, object message, Exception e)
{
var logger = LogManager.GetLogger(loggerType.ToString());
logger.Info(SerializeObject(message), e);
}
public static void Fatal(LoggerType loggerType, object message, Exception e)
{
var logger = LogManager.GetLogger(loggerType.ToString());
logger.Fatal(SerializeObject(message), e);
}
public static void Warn(LoggerType loggerType, object message, Exception e)
{
var logger = LogManager.GetLogger(loggerType.ToString());
logger.Warn(SerializeObject(message), e);
}
private static object SerializeObject(object message)
{
if (message is string || message == null)
return message;
else
return JsonConvert.SerializeObject(message, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
}
}
public enum LoggerType
{
WebExceptionLog,
ServiceExceptionLog
}
6寫一個所有controllb繼承的controllbase父類,所有通路的controller發生的異常在這裡處理并記錄
public class ControllerBase : Controller
{
/// <summary>
/// 發生異常寫Log
/// </summary>
/// <param name="filterContext"></param>
protected override void OnException(ExceptionContext filterContext)
{
base.OnException(filterContext);
var e = filterContext.Exception;
var str = "錯誤記錄";
Log4NetHelper.Error(LoggerType.WebExceptionLog, str, e);
}
}
7、在WebConfig中把過濾器配置啟動
<customErrors mode="On">
</customErrors>
8控制器的代碼報錯時,會跳轉到~/Views/Shared/Error.cshtml頁面。mode="Off"頁面不會跳轉直接顯示錯誤資訊。
9綁定異常過濾器(過濾範圍是在controller的action方法中。)
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}