Log4NET简介
log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台、文件、数据库等)的工具。
前提
最近做项目需要记录系统日志和用户操作日志,就想起来了log4net,但是业务需要需要加入自定义属性,并把自定义属性日志数据插入到数据库中,看好趁这个机会学习总结下。
详细步骤
一、首先下载:log4net.dll 下载地址:http://logging.apache.org/log4net/download_log4net.cgi
二、在项目中进行引用。这个不多说了,相信大家都很熟悉这个过程。
三、在web.config,加入以下代码:
1 <configSections> 2 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 3 </configSections>
四、然后在与web.config同目录下面新建个配置文件,我这建了个log4net.config,如下图
五、在log4net.config加入以下代码,里面注释和详细 ,大家可以看如下代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <configSections> 4 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/> 5 </configSections> 6 7 <log4net> 8 <logger name="myLogger"> 9 <level value="INFO"/> 10 <appender-ref ref="AdoNetAppender_SqlServer"/> 11 <!--sql server数据库1--> 12 <appender-ref ref="AdoNetAppender_SqlServer1"/> 13 <!--sql server数据库2--> 14 <appender-ref ref="AdoNetAppender_Sqllite"/> 15 <!--sqlite数据库--> 16 <appender-ref ref="InfoAppender"/> 17 <!--记录到文件--> 18 </logger> 19 20 <!--sql server数据库1--> 21 <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender"> 22 <!-- BufferSize 为缓冲区大小,只有日志记录超5 条才会一块写入到数据库 --> 23 <!-- 或写为<param name="BufferSize" value="10" /> --> 24 <bufferSize value="0"/> 25 <!-- 引用 --> 26 <!--2.0这是对应sql2008 如是2000或2005另外配置--> 27 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"/> 28 29 <!-- 连接数据库字符串 --> 30 <connectionString value="Data Source=.;Initial Catalog=Log;User ID=sa;Password=sa123;" /> 31 <!-- 插入到表Log --> 32 <commandText value = "INSERT INTO Mylogger ([EVENTTYPE],[TIMESTAMP],[EVENTCATEGORY],[EVENT_ID],[COMPUTERNAME],[MAC_ADDRESS],[USERNAME],[SOURCETYPE],[SOURCE],[DESCRIPTION],[COLLECTDATE]) VALUES (@Event_Type,@log_date, @EventCategory, @Event_ID, @ComputerName,@Mac_Address,@UserName,@SourceType,@Source,@Description,@CollectDate) "/> 33 34 <!-- 日志类型,这里均为3 --> 35 <parameter> 36 <parameterName value = "@Event_Type"/> 37 <dbType value = "Int32"/> 38 <!--<dbType value = "String"/> 39 <size value = "50"/>--> 40 <!-- LogComponent 是类所在的命名空间,MyLayout 是自定义属性所在的类,这是我们自己要写的部分,将在下面介绍。 --> 41 <layout type = "Log4netExpand.MyLayout,log4nettest"> 42 <!-- 当用到property 时,就表明这是用户自定义的字段属性啦,是log4net 中所没有提供的字段。 --> 43 <conversionPattern value = "%property{Event_Type} "/> 44 </layout> 45 </parameter> 46 47 <!-- 日志记录时间,RawTimeStampLayout 为默认的时间输出格式 --> 48 <parameter> 49 <parameterName value = "@log_date"/> 50 <dbType value = "DateTime"/> 51 <layout type = "log4net.Layout.RawTimeStampLayout"/> 52 <!-- /这里呢是获取log4net 中提供的日志时间 --> 53 </parameter> 54 55 <!-- 日志分类描述 --> 56 <parameter> 57 <parameterName value = "@EventCategory"/> 58 <dbType value = "String"/> 59 <size value = "50"/> 60 <layout type = "Log4netExpand.MyLayout,log4nettest"> 61 <conversionPattern value = "%property{EventCategory}"/> 62 </layout> 63 </parameter> 64 65 <!-- 日志分类号 --> 66 <parameter> 67 <parameterName value = "@Event_ID"/> 68 <dbType value = "Int32"/> 69 <layout type = "Log4netExpand.MyLayout,log4nettest"> 70 <conversionPattern value = "%property{Event_ID}"/> 71 </layout> 72 </parameter> 73 74 <!-- 计算机IP --> 75 <parameter> 76 <parameterName value = "@ComputerName"/> 77 <dbType value = "String"/> 78 <size value = "50"/> 79 <layout type = "Log4netExpand.MyLayout,log4nettest"> 80 <conversionPattern value = "%property{ComputerName}"/> 81 </layout> 82 </parameter> 83 84 <!-- 计算机Mac 信息 --> 85 <parameter> 86 <parameterName value = "@Mac_Address"/> 87 <dbType value = "String"/> 88 <size value = "50 "/> 89 <layout type = "Log4netExpand.MyLayout, log4nettest"> 90 <conversionPattern value = "%property{Mac_Address}"/> 91 </layout> 92 </parameter> 93 94 <!-- 登陆系统用户名 --> 95 <parameter> 96 <parameterName value = "@UserName"/> 97 <dbType value = "String"/> 98 <size value = "50"/> 99 <layout type = "Log4netExpand.MyLayout,log4nettest"> 100 <conversionPattern value = "%property{UserName}"/> 101 </layout> 102 </parameter> 103 104 <!-- 事件来源类型,这里默认为Rier --> 105 <parameter> 106 <parameterName value = "@SourceType"/> 107 <dbType value = "String"/> 108 <size value = "20"/> 109 <layout type = "Log4netExpand.MyLayout,log4nettest"> 110 <conversionPattern value = "%property{SourceType}"/> 111 </layout> 112 </parameter> 113 114 <!-- 事件来源 --> 115 <parameter> 116 <parameterName value = "@Source "/> 117 <dbType value = "String"/> 118 <size value = "50"/> 119 <layout type = "Log4netExpand.MyLayout,log4nettest"> 120 <conversionPattern value = "%property{Source}"/> 121 </layout> 122 </parameter> 123 124 <!-- 事件描述 --> 125 <parameter> 126 <parameterName value = "@Description "/> 127 <dbType value = "String"/> 128 <size value = "4000"/> 129 <layout type = "Log4netExpand.MyLayout, log4nettest"> 130 <conversionPattern value = "%property{Description}"/> 131 </layout> 132 </parameter> 133 134 <!-- 日志收集时间 --> 135 <parameter> 136 <parameterName value = "@CollectDate"/> 137 <dbType value = "DateTime"/> 138 <layout type="log4net.Layout.RawTimeStampLayout" /> 139 </parameter> 140 </appender> 141 142 <!--记录到文件--> 143 <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender"> 144 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 145 146 <param name="File" value="Log\\INFO\\"/> 147 <param name="AppendToFile" value="true"/> 148 <param name="MaxFileSize" value="10240" /> 149 <param name="MaxSizeRollBackups" value="100"/> 150 <param name="StaticLogFileName" value="false"/> 151 <param name="DatePattern" value="yyyyMMdd".txt""/> 152 <param name="RollingStyle" value="Date"/> 153 <layout type="log4net.Layout.PatternLayout"> 154 <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger 操作者ID:%property{Operator} 操作类型:%property{Action}%n 当前机器名:%property%n当前机器名及登录用户:%username %n 记录位置:%location%n 消息描述:%property{Message}%n 异常:%exception%n 消息:%message%newline%n%n" /> 155 </layout> 156 </appender> 157 158 <!--sql server数据库2--> 159 <appender name="AdoNetAppender_SqlServer1" type="log4net.Appender.AdoNetAppender"> 160 <bufferSize value="0"/> 161 <!--2.0这是对应sql2008 如是2000或2005另外配置--> 162 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"/> 163 164 <!-- 连接数据库字符串 --> 165 <connectionString value="Data Source=.;Initial Catalog=Log;User ID=sa;Password=sa123;" /> 166 167 <!-- 插入到表Log --> 168 <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message,@exception)"/> 169 170 <parameter> 171 <parameterName value="@log_date"/> 172 <dbType value="DateTime"/> 173 174 <layout type="log4net.Layout.PatternLayout"> 175 <conversionPattern value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}" /> 176 </layout> 177 <!-- <layout type="log4net.Layout.RawTimeStampLayout"/>--> 178 </parameter> 179 <parameter> 180 <parameterName value="@thread"/> 181 <dbType value="String"/> 182 <size value="255"/> 183 <!-- LogComponent 是类所在的命名空间,MyLayout 是自定义属性所在的类,这是我们自己要写的部分,将在下面介绍。 --> 184 <layout type="log4net.Layout.PatternLayout"> 185 <conversionPattern value="%thread"/> 186 </layout> 187 </parameter> 188 <parameter> 189 <parameterName value="@log_level"/> 190 <dbType value="String"/> 191 <size value="50"/> 192 <layout type="log4net.Layout.PatternLayout"> 193 <conversionPattern value="%level"/> 194 </layout> 195 </parameter> 196 <parameter> 197 <parameterName value="@logger"/> 198 <dbType value="String"/> 199 <size value="255"/> 200 <layout type="log4net.Layout.PatternLayout"> 201 <conversionPattern value="%logger"/> 202 </layout> 203 </parameter> 204 <parameter> 205 <parameterName value="@message"/> 206 <dbType value="String"/> 207 <size value="4000"/> 208 <layout type="log4net.Layout.PatternLayout"> 209 <conversionPattern value="%message"/> 210 </layout> 211 </parameter> 212 <parameter> 213 <parameterName value="@exception" /> 214 <dbType value="String" /> 215 <size value="2000" /> 216 <layout type="log4net.Layout.ExceptionLayout" /> 217 </parameter> 218 </appender> 219 220 <!--sqlite数据库--> 221 <appender name="AdoNetAppender_Sqllite" type="log4net.Appender.AdoNetAppender"> 222 <bufferSize value="0"/> 223 <!--2.0这是对应sql2008 如是2000或2005另外配置--> 224 <!--<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"/>--> 225 <connectionType value="System.Data.SQLite.SQLiteConnection, System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> 226 <!-- 连接数据库字符串 --> 227 <!--<connectionString value="Data Source=.;Initial Catalog=Log;User ID=sa;Password=123;" />--> 228 <connectionString value="C:\\Users\\Administrator\\Desktop\\log4net\\Log4netExpand\\Test.db3;" /> 229 <!-- 插入到表Log --> 230 <commandText value="INSERT INTO MAIN.[Log] ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message,@exception)"/> 231 232 <parameter> 233 <parameterName value="@log_date"/> 234 <dbType value="DateTime"/> 235 236 <layout type="log4net.Layout.PatternLayout"> 237 <conversionPattern value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}" /> 238 </layout> 239 <!-- <layout type="log4net.Layout.RawTimeStampLayout"/>--> 240 </parameter> 241 <parameter> 242 <parameterName value="@thread"/> 243 <dbType value="String"/> 244 <!--<size value="255"/>--> 245 <!-- LogComponent 是类所在的命名空间,MyLayout 是自定义属性所在的类,这是我们自己要写的部分,将在下面介绍。 --> 246 <layout type="log4net.Layout.PatternLayout"> 247 <conversionPattern value="%thread"/> 248 </layout> 249 </parameter> 250 <parameter> 251 <parameterName value="@log_level"/> 252 <dbType value="String"/> 253 <!--<size value="50"/>--> 254 <layout type="log4net.Layout.PatternLayout"> 255 <conversionPattern value="%level"/> 256 </layout> 257 </parameter> 258 <parameter> 259 <parameterName value="@logger"/> 260 <dbType value="String"/> 261 <!--<size value="255"/>--> 262 <layout type="log4net.Layout.PatternLayout"> 263 <conversionPattern value="%logger"/> 264 </layout> 265 </parameter> 266 <parameter> 267 <parameterName value="@message"/> 268 <dbType value="String"/> 269 <!--<size value="4000"/>--> 270 <layout type="log4net.Layout.PatternLayout"> 271 <conversionPattern value="%message"/> 272 </layout> 273 </parameter> 274 <parameter> 275 <parameterName value="@exception" /> 276 <dbType value="String" /> 277 <!--<size value="2000" />--> 278 <layout type="log4net.Layout.ExceptionLayout" /> 279 </parameter> 280 </appender> 281 </log4net> 282 283 <system.web> 284 <compilation debug="true" targetFramework="4.0" /> 285 </system.web> 286 287 </configuration>
我主要说下里面自定义属性的代码的分别代表意义:
<parameter>
96 <parameterName value = "@UserName"/>
97 <dbType value = "String"/>
98 <size value = "50"/>
99 <layout type = "Log4netExpand.MyLayout,log4nettest">
100 <conversionPattern value = "%property{UserName}"/>
101 </layout>
102 </parameter>
其中MyLayout,是我们自己定义的类,下面有介绍;Log4netExpand是这个类的命名空间;log4nettest这个代表是aspx页面的命名空间。注意在此区分。
六、自定义类,这些类呢包含将要插入数据库中的自定义字段
命名空间为 Log4netExpand包含3个类:LogContent.cs、 MyLayout.cs 、MyMessagePatternConverter .cs
1)第一个LogContent类如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Log4netExpand { /// <summary> /// 包含了所有的自定字段属性 /// </summary> public class LogContent { /// <summary> /// 时间类型 均为3 /// </summary> public int Event_Type { get; set; } /// <summary> /// 日志分类描述,自定义 /// </summary> public string EventCategory { get; set; } /// <summary> /// 日志分类号 /// </summary> public int Event_ID { get; set; } /// <summary> /// 计算机IP /// </summary> public string ComputerName { get; set; } /// <summary> /// 计算机Mac 地址 /// </summary> public string Mac_Address { get; set; } /// <summary> /// 系统登陆用户 /// </summary> public string UserName { get; set; } /// <summary> /// Rier /// </summary> public string SourceType { get; set; } /// <summary> /// Rier Recorder audit /// </summary> public string Source { get; set; } /// <summary> /// 日志描述信息 /// </summary> public string Description { get; set; } } }
2)第二个类MyLayout代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using log4net.Layout; 6 7 namespace Log4netExpand 8 { 9 class MyLayout : PatternLayout 10 { 11 public MyLayout() 12 { 13 this.AddConverter("property", typeof(MyMessagePatternConverter)); 14 } 15 } 16 }
3)第三个类MyMessagePatternConverter 代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Reflection; 6 using log4net.Layout.Pattern; 7 8 namespace Log4netExpand 9 { 10 public class MyMessagePatternConverter : PatternLayoutConverter 11 { 12 13 protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent) 14 { 15 16 if (Option != null) 17 { 18 19 // Write the value for the specified key 20 21 WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent)); 22 23 } 24 25 else 26 { 27 28 // Write all the key value pairs 29 30 WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); 31 32 } 33 34 //if (Option != null) 35 36 //{ 37 38 // // Write the value for the specified key 39 40 // WriteObject(writer, loggingEvent.Repository, loggingEvent.LookupProperty(Option)); 41 42 //} 43 44 //else 45 46 //{ 47 48 // // Write all the key value pairs 49 50 // WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); 51 52 //} 53 54 } 55 56 57 58 /// <summary> 59 60 /// 通过反射获取传入的日志对象的某个属性的值 61 62 /// </summary> 63 64 /// <param name="property"></param> 65 66 /// <returns></returns> 67 68 private object LookupProperty(string property, log4net.Core.LoggingEvent loggingEvent) 69 { 70 71 object propertyValue = string.Empty; 72 73 74 75 PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property); 76 77 if (propertyInfo != null) 78 79 propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null); 80 81 82 83 return propertyValue; 84 85 } 86 87 } 88 }
七、代码页,实现通过log4net把日志(含自定一生属性)添加到数据库
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 8 using System.Management; 9 using Log4netExpand; 10 11 namespace Log4netExpand 12 { 13 public partial class test : System.Web.UI.Page 14 { 15 protected void Page_Load(object sender, EventArgs e) 16 { 17 18 } 19 protected void Button1_Click(object sender, EventArgs e) 20 { 21 log4net.ILog log = log4net.LogManager.GetLogger("myLogger"); 22 23 LogContent logmodel = new LogContent(); 24 logmodel.Event_Type = 3; 25 logmodel.EventCategory = "登陆系统"; 26 logmodel.Event_ID = 1; 27 logmodel.ComputerName = Request.UserHostAddress; 28 logmodel.Mac_Address = GetMacAddress(); 29 logmodel.Source = "SS"; 30 logmodel.SourceType = "1"; 31 logmodel.UserName = "ADMIN"; 32 logmodel.Description = "TEST";//在记录数据库操作时,可以在petapoco底层将sql语句放入其中。 33 LogHelper.WriteLog(logmodel); 34 35 lbMsg.Text = "数据记录成功!"; 36 } 37 38 public string GetMacAddress() 39 { 40 string mac = ""; 41 try 42 { 43 //获取网卡硬件地址 44 ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); 45 ManagementObjectCollection moc = mc.GetInstances(); 46 47 List<string> list = new List<string>(); 48 49 foreach (ManagementObject mo in moc) 50 { 51 if ((bool)mo["IPEnabled"] == true) 52 { 53 mac = mo["MacAddress"].ToString(); 54 55 list.Add(mac); 56 } 57 } 58 moc = null; 59 mc = null; 60 61 mac = list[list.Count - 1]; 62 63 return mac; 64 } 65 catch 66 { 67 return "unknow"; 68 } 69 } 70 } 71 }
代码例子源代码: Demo下载