异常对于程序来说是非常重要的,方便我们程序员发现异常、并能够快速的找到异常;本文介绍使用Log4net实现获取程序的错误信息,并将错误信息写入Sql Server数据库。
第一步:引用Log4Net包 PM>Install-Package log4net -Version 2.0.8
第二步:创建log4net.config文件
<?xml version="1.0" encoding="utf-8"?>
<!--***********************************日志相关配置*************************************-->
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<!--Log4net的配置-->
<log4net>
<!--本地Text文件-->
<appender name="LogFileAppender" type="log4net.Appender.FileAppender" >
<param name="File" value="c:\Log4\DBLog.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" />
</layout>
</appender>
<!--SQL数据库-->
<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" />
<!--读取Web.config中的数据库连接字符串-->
<connectionStringName value="CoreDb"></connectionStringName>
<!--数据库连接字符串-->
<!--<connectionString value="Data Source=.;Initial Catalog=Test;Integrated Security=True" />-->
<commandText value="INSERT INTO AuditLogs ([ExecutionTime],[Thread],[ExecutionDuration],[Level],[ExceptionMessage],[Exception],[ClientIpAddress],[ClientName],[MethodName],[ServiceName],[BrowserInfo],[Parameters],[MemberId])
VALUES (@executionTime, @thread, @executionDuration, @log_level, @exceptionMessage, @exception,@clientIpAddress,@clientName,@methodName,@serviceName,@browserInfo,@parameters,@memberId)" />
<parameter>
<parameterName value="@executionTime" />
<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="@clientIpAddress" />
<dbType value="String" />
<size value="64" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{ClientIpAddress}" />
</layout>
</parameter>
<parameter>
<parameterName value="@clientName" />
<dbType value="String" />
<size value="128" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{ClientName}" />
</layout>
</parameter>
<parameter>
<parameterName value="@methodName" />
<dbType value="String" />
<size value="128" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MethodName}" />
</layout>
</parameter>
<parameter>
<parameterName value="@serviceName" />
<dbType value="String" />
<size value="256" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{ServiceName}" />
</layout>
</parameter>
<parameter>
<parameterName value="@browserInfo" />
<dbType value="String" />
<size value="256" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{BrowserInfo}" />
</layout>
</parameter>
<parameter>
<parameterName value="@parameters" />
<dbType value="String" />
<size value="256" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{Parameters}" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="5000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{Exception}" />
</layout>
</parameter>
<parameter>
<parameterName value="@exceptionMessage" />
<dbType value="String" />
<size value="5000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{ExceptionMessage}" />
</layout>
</parameter>
<parameter>
<parameterName value="@memberId" />
<dbType value="String" />
<size value="11" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MemberId}" />
</layout>
</parameter>
<parameter>
<parameterName value="@executionDuration" />
<dbType value="String" />
<size value="11" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{ExecutionDuration}" />
</layout>
</parameter>
</appender>
<root>
<!-- Set this to "ERROR" before release -->
<!--Highest: OFF->FATAL->RROR->WARN->INFO->DEBUG->ALL :Lowest -->
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
<!-- <appender-ref ref="SmtpAppender" /> -->
<!--<appender-ref ref="FileAppender" /> -->
</root>
<logger name="iNotes">
<level value="INFO"/>
<appender-ref ref="AdoNetAppender" />
</logger>
</log4net>
<!--***********************************日志相关配置*************************************-->
</configuration>
第三步:AssemblyInfo.cs类中添加
//日志系统应用程序配置文件
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
第四步:Global.asax 读取lognet中的配置文件
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(Server.MapPath("~/Log4Net.config")));
第五步:创建Log4NetFilterAttribute特性类并继承ActionFilterAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Module, AllowMultiple = true)]
public class Log4NetFilterAttribute : ActionFilterAttribute
{
Stopwatch stop = null;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
stop = new Stopwatch();
stop.Start();
base.OnActionExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
try
{
stop.Stop();
long milliseconds = stop.ElapsedMilliseconds;
//登录会员ID
var memberId = filterContext.HttpContext.Session["MemberId"];
//请求参数post
string request = filterContext.HttpContext.ApplicationInstance.Request.Form.ToString();
//请求参数 get
var query = filterContext.HttpContext.ApplicationInstance.Request.QueryString.ToString();
//客户端信息
var browser = filterContext.HttpContext.Request.Browser;
int? nullId = null;
LogHelper.logHelper.Write(new AuditLogInfo()
{
MemberId = memberId == null ? nullId : Convert.ToInt32(memberId),
ExecutionDuration = milliseconds,
ClientIpAddress = Net.Ip,
ClientName = Net.Host,
MethodName = filterContext.RequestContext.RouteData.Values["action"].ToString(),
ServiceName = filterContext.Controller.GetType().ToString(),
BrowserInfo = $"{ browser.Type} / {browser.Version} / {browser.Platform}",
ExceptionMessage = filterContext.Exception?.Message,
Exception = filterContext.Exception?.StackTrace,
Parameters = query
});
}
catch (Exception ex)
{
string path = AppDomain.CurrentDomain.BaseDirectory;
byte[] myByte = Encoding.UTF8.GetBytes(ex.Message + ex.StackTrace);
using (FileStream fsWrite = new FileStream(path + "/errer.txt", FileMode.Append))
{
fsWrite.Write(myByte, 0, myByte.Length);
}
}
finally
{
base.OnActionExecuted(filterContext);
}
}
}
获取IP地址类:Net
public class Net
{
#region Ip(获取Ip)
/// <summary>
/// 获取Ip
/// </summary>
public static string Ip
{
get
{
var result = string.Empty;
if (HttpContext.Current != null)
result = GetWebClientIp();
if (string.IsNullOrWhiteSpace(result))
result = GetLanIp();
return result;
}
}
/// <summary>
/// 获取Web客户端的Ip
/// </summary>
/// <returns></returns>
private static string GetWebClientIp()
{
var ip = GetWebRemoteIp();
foreach (var hostAddress in Dns.GetHostAddresses(ip))
{
if (hostAddress.AddressFamily == AddressFamily.InterNetwork)
return hostAddress.ToString();
}
return string.Empty;
}
/// <summary>
/// 获取Web远程Ip
/// </summary>
/// <returns></returns>
private static string GetWebRemoteIp()
{
return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
/// <summary>
/// 获取局域网IP
/// </summary>
/// <returns></returns>
private static string GetLanIp()
{
string ip = string.Empty;
foreach (var hostAddress in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (hostAddress.AddressFamily == AddressFamily.InterNetwork)
//return hostAddress.ToString();
ip = ip + ";" + hostAddress.ToString();
}
if (!string.IsNullOrEmpty(ip) && ip.Contains(";"))
{
ip = ip.Substring(1);
}
return ip;
}
#endregion
#region Host(获取主机名)
/// <summary>
/// 获取主机名
/// </summary>
public static string Host
{
get
{
return HttpContext.Current == null ? Dns.GetHostName() : GetWebClientHostName();
}
}
/// <summary>
/// 获取Web客户端主机名
/// </summary>
/// <returns></returns>
private static string GetWebClientHostName()
{
if (!HttpContext.Current.Request.IsLocal)
return string.Empty;
var ip = GetWebRemoteIp();
var result = Dns.GetHostEntry(IPAddress.Parse(ip)).HostName;
if (result == "localhost.localdomain")
result = Dns.GetHostName();
return result;
}
#endregion
#region Browser(获取浏览器信息)
/// <summary>
/// 获取浏览器信息
/// </summary>
public static string Browser
{
get
{
if (HttpContext.Current == null)
return string.Empty;
var browser = HttpContext.Current.Request.Browser;
return string.Format("{0} {1}", browser.Browser, browser.Version);
}
}
#endregion
}
第六步:创建Log4Net帮助类
public class LogHelper
{
public static string configFilePath = AppDomain.CurrentDomain.BaseDirectory + @"log4net.config";
public static LogHelper logHelper = new LogHelper();
public LogHelper()
{
XmlConfigurator.Configure();
}
public bool Write(AuditLogInfo logInfo)
{
//自定义添加的属性
string propertiesMemberId = "MemberId";
string propertiesServiceName = "ServiceName";
string propertiesMethodName = "MethodName";
string propertiesParameters = "Parameters";
string propertiesClientIpAddress = "ClientIpAddress";
string propertiesClientName = "ClientName";
string propertiesBrowserInfo = "BrowserInfo";
string propertiesException = "Exception";
string propertiesExceptionMessage = "ExceptionMessage";
string propertiesCustomData = "CustomData";
string pathlog4net = configFilePath;
XmlConfigurator.Configure(new FileInfo(pathlog4net));
try
{
GlobalContext.Properties[propertiesMemberId] = logInfo.MemberId;
GlobalContext.Properties[propertiesServiceName] = logInfo.ServiceName;
GlobalContext.Properties[propertiesMethodName] = logInfo.MethodName;
GlobalContext.Properties[propertiesParameters] = logInfo.Parameters;
GlobalContext.Properties[propertiesClientIpAddress] = logInfo.ClientIpAddress;
GlobalContext.Properties[propertiesClientName] = logInfo.ClientName;
GlobalContext.Properties[propertiesBrowserInfo] = logInfo.BrowserInfo;
GlobalContext.Properties[propertiesCustomData] = logInfo.CustomData;
GlobalContext.Properties[propertiesException] = logInfo.Exception == null ? "" : logInfo.Exception;
GlobalContext.Properties[propertiesExceptionMessage] = logInfo.ExceptionMessage == null ? "" : logInfo.ExceptionMessage;
if (string.IsNullOrWhiteSpace(logInfo.ExceptionMessage))
{
LogEncapsulation.Info(logInfo);
}
else
{
LogEncapsulation.Error(logInfo);
}
return true;
}
catch (Exception e)
{
string path = AppDomain.CurrentDomain.BaseDirectory;
byte[] myByte = System.Text.Encoding.UTF8.GetBytes(e.Message);
using (FileStream fsWrite = new FileStream(path + "/errer.txt", FileMode.Append))
{
fsWrite.Write(myByte, 0, myByte.Length);
}
return false;
}
}
}
public class LogEncapsulation
{
public static LogEncapsulation logEncapsulation = new LogEncapsulation();
static LogEncapsulation()
{
string path = LogHelper.configFilePath;
log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
}
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static void Debug(string message)
{
if (log.IsDebugEnabled)
{
log.Debug(message);
}
}
public static void Debug(System.Exception ex1)
{
if (log.IsDebugEnabled)
{
log.Debug(ex1.Message.ToString() + ex1.Source.ToString() + ex1.TargetSite.ToString() + ex1.StackTrace.ToString());
}
}
public static void Error(Object message)
{
if (log.IsErrorEnabled)
{
log.Error(message);
}
}
public static void Fatal(Object message)
{
if (log.IsFatalEnabled)
{
log.Fatal(message);
}
}
public static void Info(Object message)
{
if (log.IsInfoEnabled)
{
log.Info(message);
}
}
public static void Warn(Object message)
{
if (log.IsWarnEnabled)
{
log.Warn(message);
}
}
}
运行项目即可,可以看到,数据已经添加进去了
如果未插入进去,说明出现异常,可调试查询错误,并处理;如有其它问题,请评论下方;