基于Log4Net记录日志到SQLServer
本文记录通过log4net将日志信息记录到SQLServer数据库中。
1、新建控制台应用程序 Log4NetDemo;
2、通过NuGet安装Log4Net (项目版本2.0.8);
3、项目根目录下添加 log4net.config 配置文件;
<?xml version="1.0"?> <configuration> <!--声明一个名为“log4net”的自定义配置节--> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/> </configSections> <!--log4net配置信息--> <log4net> <logger name="WebLogger"> <level value="INFO"/><!--定义在这个级别之上的日志才会被记录--> <appender-ref ref="ADONetAppender" /><!--定义日志对象使用的Appender对象--> </logger> <!--Appenders用来定义日志的输出方式 --> <!--name = “AdoNetAppender” sql数据库--> <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender"> <!--缓冲区大小为10,缓存10条记录同时写入数据库,避免每次都去请求数据库连接写数据--> <bufferSize value="10"/> <!-- SQL数据源 ,本地安装SQL客户端--> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> <!-- SQL连接字符串,修改为自己的--> <connectionString value="Data Source=ali.xsd.com;Initial Catalog=test;Integrated Security=false;User ID=admin;Password=123456;" /> <!-- 数据库插入--> <commandText value="INSERT INTO AppOpLog ([ThreadId],[Level],[Message],[Exception],[LogTime],[UserPhone],[IP],[ControllerName],[ActionName],[ActionParam],[Url],[HttpHeader],[HttpMethod],[UserAgent],[StartTime],[EndTime],[RunTime]) VALUES ( @thread,@log_level, @message, @exception,@log_date, @UserPhone,@IP,@ControllerName,@ActionName,@ActionParam,@Url,@HttpHeader,@HttpMethod,@UserAgent,@StartTime,@EndTime,@RunTime)"/> <!--线程号--> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="100" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%t" /> </layout> </parameter> <!--日志记录时间,RawTimeStampLayout 为默认的时间输出格式--> <parameter> <parameterName value="@log_date"/> <dbType value="DateTime"/> <layout type="log4net.Layout.RawTimeStampLayout"/> </parameter> <!--日志等级--> <parameter> <parameterName value="@log_level"/> <dbType value="String"/> <size value="50"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level"/> </layout> </parameter> <!--异常 ExceptionLayout 默认的异常输出格式--> <parameter> <parameterName value="@exception"/> <dbType value="String"/> <size value="2000"/> <layout type="log4net.Layout.ExceptionLayout"/> </parameter> <parameter> <parameterName value="@message"/> <dbType value="String"/> <size value="4000"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> </parameter> <!--自定义成员--> <parameter> <parameterName value="@UserPhone" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%UserPhone" /> </layout> </parameter> <parameter> <parameterName value="@IP" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%IP" /> </layout> </parameter> <parameter> <parameterName value="@StartTime" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%StartTime" /> </layout> </parameter> <parameter> <parameterName value="@EndTime" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%EndTime" /> </layout> </parameter> <parameter> <parameterName value="@RunTime" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%RunTime" /> </layout> </parameter> <parameter> <parameterName value="@ControllerName" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%ControllerName" /> </layout> </parameter> <parameter> <parameterName value="@ActionName" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%ActionName" /> </layout> </parameter> <parameter> <parameterName value="@ActionParam" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%ActionParam" /> </layout> </parameter> <parameter> <parameterName value="@Url" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%Url" /> </layout> </parameter> <parameter> <parameterName value="@HttpMethod" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%HttpMethod" /> </layout> </parameter> <parameter> <parameterName value="@HttpHeader" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%HttpHeader" /> </layout> </parameter> <parameter> <parameterName value="@UserAgent" /> <dbType value="String" /> <layout type="Log4NetDemo.CustomLayout"> <conversionPattern value="%UserAgent" /> </layout> </parameter> </appender> </log4net> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration>
View Code
4、日志记录中添加自定义字段
public class CustomLayout : log4net.Layout.PatternLayout { public CustomLayout() { this.AddConverter("UserPhone", typeof(UserPhonePatternConverter)); this.AddConverter("IP", typeof(IPPatternConverter)); this.AddConverter("ControllerName", typeof(ControllerNamePatternConverter)); this.AddConverter("ActionName", typeof(ActionNamePatternConverter)); this.AddConverter("ActionParam", typeof(ActionParamPatternConverter)); this.AddConverter("Url", typeof(UrlPatternConverter)); this.AddConverter("HttpHeader", typeof(HttpHeaderPatternConverter)); this.AddConverter("HttpMethod", typeof(HttpMethodPatternConverter)); this.AddConverter("UserAgent", typeof(UserAgentPatternConverter)); this.AddConverter("StartTime", typeof(StartTimePatternConverter)); this.AddConverter("EndTime", typeof(EndTimePatternConverter)); this.AddConverter("RunTime", typeof(RunTimePatternConverter)); } } internal sealed class UserPhonePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.UserPhone); } } internal sealed class IPPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.IP); } } internal sealed class ControllerNamePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.ControllerName); } } internal sealed class ActionNamePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.ActionName); } } internal sealed class ActionParamPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.ActionParam); } } internal sealed class UrlPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.Url); } } internal sealed class HttpHeaderPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.HttpHeader); } } internal sealed class HttpMethodPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.HttpMethod); } } internal sealed class UserAgentPatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.UserAgent); } } internal sealed class StartTimePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.StartTime); } } internal sealed class EndTimePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.EndTime); } } internal sealed class RunTimePatternConverter : PatternLayoutConverter { override protected void Convert(TextWriter writer, LoggingEvent loggingEvent) { AppOpLog logMessage = loggingEvent.MessageObject as AppOpLog; if (logMessage != null) writer.Write(logMessage.RunTime); } }
View Code
//注册 log4net,注意这里的路径为绝对路径 log4net.Config.XmlConfigurator.Configure( new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\log4net.config") );
View Code
public class LogHelper { public static string LoggerName = "DbLogger"; private static ILog log = LogManager.GetLogger(LoggerName); /// <summary> /// 记录一般日志 /// </summary> public static void LogInfo(AppOpLog opLog) { if (log.IsInfoEnabled) { log.Info(opLog); } } /// <summary> /// 记录错误 /// </summary> public static void LogError(AppOpLog opLog, Exception ex) { if (log.IsErrorEnabled) { log.Error(opLog, ex); } } /// <summary> /// 记录严重错误 /// </summary> public static void LogFatal(AppOpLog opLog, Exception ex) { if (log.IsFatalEnabled) { log.Fatal(opLog, ex); } } /// <summary> /// 记录警告 /// </summary> public static void LogWarn(AppOpLog opLog) { if (log.IsWarnEnabled) { log.Warn(opLog); } } }
View Code
7、在程序中调用
static void Main(string[] args) { log4net.Config.XmlConfigurator.Configure( new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\log4net.config") ); AppOpLog opLog = new AppOpLog(); opLog.IP = "192.124.0.0"; opLog.ActionName = "action"; opLog.ControllerName = "controller"; opLog.ActionParam = "param"; opLog.Url = "url"; opLog.HttpHeader = "header"; opLog.HttpMethod = "get"; opLog.UserAgent = "useragent"; opLog.StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); opLog.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); opLog.RunTime = (Convert.ToDateTime(opLog.EndTime) - Convert.ToDateTime(opLog.StartTime)).TotalSeconds.ToString(); LogHelper.LogError(opLog,new Exception("error"));//调用 Console.ReadKey(); }
View Code
8、结果
注意:控制台程序调试的时候需要将 log4net.config属性设为始终复制;
附sql脚本
CREATE TABLE [dbo].[AppOpLog]( [IntId] [int] IDENTITY(1,1) NOT NULL, [UserCharId] [varchar](50) NULL, [UserPhone] [varchar](20) NULL, [LogTime] [datetime] NOT NULL, [IP] [varchar](20) NOT NULL, [ControllerName] [varchar](20) NOT NULL, [ActionName] [varchar](20) NOT NULL, [ActionParam] [varchar](max) NOT NULL, [Url] [varchar](max) NOT NULL, [HttpHeader] [varchar](max) NULL, [HttpMethod] [varchar](5) NULL, [UserAgent] [varchar](100) NULL, [StartTime] [datetime] NOT NULL, [EndTime] [datetime] NOT NULL, [RunTime] [varchar](50) NOT NULL, [Level] [varchar](10) NOT NULL, [ThreadId] [int] NOT NULL, [Message] [varchar](max) NULL, [CreateTime] [datetime] NULL )
View Code
AppOpLog.cs
public class AppOpLog { public string IP { get; set; } public string ControllerName { get; set; } public string ActionName { get; set; } public string ActionParam { get; set; } public string Url { get; set; } public string HttpHeader { get; set; } public string HttpMethod { get; set; } public string UserAgent { get; set; } public string StartTime { get; set; } public string EndTime { get; set; } public string RunTime { get; set; } }
View Code
log4net调试:当log4net日志插入失败时,在Web.Config配置文件里添加可以查看错误情况,这里注意对应的目录下要有写文件的权限
<appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings> <system.diagnostics> <trace autoflush="true"> <listeners> <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\log4net.txt" /> </listeners> </trace> </system.diagnostics>
View Code
测试Demo地址:https://github.com/zhrong92/Log4NetDemo