第一步:在web项目的引用中添加log4net.dll,可以通过Nuget直接下载并安装;
第二步:在web项目的web.config配置文件的configuration节点内添加log4net节点,在configSections 节点内添加log4net.dll的配置,如:
<configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> </configSections>
<log4net debug="true">
<!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
<appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
<!--日志缓存写入条数 设置为0时只要有一条就立刻写到数据库-->
<bufferSize value="0" />
<!--日志数据库连接串-->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="DATABASE=GCP;SERVER=.;UID=sa;PWD=20180517;Connect Timeout=30;" />
<!--日志数据库脚本-->
<commandText value="INSERT INTO LogDetails ([LogDate],[LogThread],[LogLevel],[LogLogger],[LogActionClick],[LogMessage],[UserName],[UserIP]) VALUES (@log_date, @thread, @log_level, @logger, @ActionsClick, @message,@UserName,@UserIP)" />
<!--日志时间LogDate -->
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<!--线程号-->
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="100" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%t" />
</layout>
</parameter>
<!--日志类型LogLevel -->
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%p" />
</layout>
</parameter>
<!--日志名称-->
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="500" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="3000" />
<layout type="Log4NetApply.MyLayout">
<conversionPattern value="%property{Message}" />
</layout>
</parameter>
<parameter>
<parameterName value="@ActionsClick" />
<dbType value="String" />
<size value="4000" />
<layout type="Log4NetApply.MyLayout" >
<conversionPattern value = "%property{ActionsClick}"/>
</layout>
</parameter>
<!--自定义UserName -->
<parameter>
<parameterName value="@UserName" />
<dbType value="String" />
<size value="30" />
<layout type="Log4NetApply.MyLayout" >
<!--log4net.MDC.Set("UserName", "asdfasdf");
<conversionPattern value = "%X{UserName}"/>-->
<conversionPattern value = "%property{UserName}"/>
</layout>
</parameter>
<parameter>
<parameterName value="@UserIP" />
<dbType value="String" />
<size value="20" />
<layout type="Log4NetApply.MyLayout" >
<conversionPattern value = "%property{UserIP}"/>
</layout>
</parameter>
</appender>
<!-- setup the root category, add the appenders and set the default level -->
<root>
<!--<level value="Warn"/>-->
<!-- 定义记录的日志级别-->
<!--<level value="Info"/>-->
<level value="Debug"/>
<!--<level value="Fine"/>-->
<appender-ref ref="ADONetAppender" />
<!-- 记录到什么介质中-->
</root>
<!-- specify the level for some specific categories -->
<!--//关于上边root到logger这块,如果同时出现,有可能会出现重复插入记录的情况:-->
<!--<logger name="iNotes">
<level value="WARN"/>
<level value="INFO"/>
<level value="DEBUG"/>
<level value="FINE"/>
<appender-ref ref="ADONetAppender"/>
</logger>
<logger name="StellaLogger">
<level value="ALL"/>
<appender-ref ref="AdoNetAppender" />
</logger>-->
<appender name="ReflectionLayout" type="log4net.Appender.RollingFileAppender,log4net">
<!--日志文件路径,按文件大小方式输出时在这里指定文件名,并且前面的日志按天在文件名后自动添加当天日期形成文件-->
<param name="File" value="D:/Log/" />
<!--是否追加到文件-->
<param name="AppendToFile" value="true" />
<!--记录日志写入文件时,不锁定文本文件-->
<!--<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />-->
<!--Unicode编码-->
<!--<Encoding value="UTF-8" />-->
<!--最多产生的日志文件数,value="-1"为不限文件数-->
<!--<param name="MaxSizeRollBackups" value="10" />-->
<!--是否只写到一个文件中-->
<param name="StaticLogFileName" value="false" />
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<param name="RollingStyle" value="Composite" />
<!--按日期产生文件夹,文件名[在日期方式与混合方式下使用]-->
<param name="DatePattern" value="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<!--<param name="DatePattern" value="yyyy-MM-dd/" ReflectionLayout.log="" />-->
<!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd"-TimerServer.log"" />-->
<!--<param name="DatePattern" value="yyyyMMdd/"TimerServer/TimerServer.log"" />-->
<!--每个文件的大小。只在混合方式与文件大小方式下使用,超出大小的在文件名后自动增加1重新命名-->
<param name="maximumFileSize" value="500KB" />
<!--记录的格式。-->
<layout type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">
<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" />
</layout>
</appender>
</log4net>
上述配置代码parameter节点的其中四个参数【message,ActionsClick,UserName,UserIP】需要我们自己传递的日志数据,所以这四个节点对应的数据来自于我们自定义类型的属性,并需要对应的工具类去解析,<layout type="Log4NetApply.MyLayout" > ,MyLayout是自定义的工具解析类名称,Log4NetApply是MyLayout类型的命名空间;
第三步:新建日志实体类和解析工具类
namespace Log4NetApply { /// <summary> /// 包含了所有的自定字段属性 /// </summary> public class LogContent { public LogContent(string macAddress, string computerName, string actionsclick, string description) { UserIP = macAddress; UserName = computerName; ActionsClick = actionsclick; Message = description; } /// <summary> /// 访问IP /// </summary> public string UserIP { get; set; } /// <summary> /// 系统登陆用户 /// </summary> public string UserName { get; set; } /// <summary> /// 动作事件 /// </summary> public string ActionsClick { get; set; } /// <summary> /// 日志描述信息 /// </summary> public string Message { get; set; } } public class MyLayout : PatternLayout { public MyLayout() { this.AddConverter("property", typeof(LogInfoPatternConverter)); } } public class LogInfoPatternConverter : PatternLayoutConverter { protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent) { if (Option != null) { // Write the value for the specified key WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent)); } else { // Write all the key value pairs WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties()); } } /// <summary> /// 通过反射获取传入的日志对象的某个属性的值 /// </summary> /// <param name="property"></param> /// <returns></returns> private object LookupProperty(string property, log4net.Core.LoggingEvent loggingEvent) { object propertyValue = string.Empty; PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property); if (propertyInfo != null) propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null); return propertyValue; } } public class LogHelp { public static log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); } }
第四步:在文件Startup.cs中添加注册配置文件的代码
[assembly: OwinStartupAttribute(typeof(WebApplication2.Startup))] [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config", Watch = true)] namespace WebApplication2 { public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); } } }
第五步:在Global.asax文件中添加初始化log4net的代码
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); log4net.Config.XmlConfigurator.Configure(); }
第六步:测试
public ActionResult Index() { try { LogHelp.logger.Info(new LogContent("", "", "Test", "Test")); int i = int.Parse("s"); } catch (Exception ex) { LogHelp.logger.Error(new LogContent("", "", "Test", ex.Message + ";" + ex.StackTrace)); } return View(); }
上述所有的一切只为得到结果