zoukankan      html  css  js  c++  java
  • Log4Net写入到数据库配置过程中的一些小问题备忘

    问题1: 在公司进行log4net写入服务器配置的时候,一切正常,但是在家里的机器上,就频繁出现这个问题:
    SQL Server 2008 报错:已成功与服务器建立连接,但是在登录前的握手期间发生错误 
    并且这种错误是随机性的,在log4net往数据库插入几条的时候,没问题,但是插入次数一多起来,就频繁报这个错误。后来没办法,网上搜罗了一圈,最终发现了解决方案:
     
    将相关的TCP参数都设置为启动之后,就再没遇到过问题。
     
     问题2,log4net配置都正确,但是一直无法写入数据库。
    这个问题困扰了好久,最终得以解决,大家就看看我的解决代码吧,我也懒得帖步骤了。
     
    配置文件如下:
     <log4net>
        <root>
          <level value="WARN"/>
          <level value="INFO"/>
          <level value="DEBUG"/>
          <level value="FINE"/>
          <!--<appender-ref ref="LogFileAppender" />-->
          <appender-ref ref="ADONetAppender" />
        </root>
        <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
          <!--文件名称-->
          <file value="log.txt" />
          <!--所有新的日志都进行追加-->
          <appendToFile value="true" />
          <!--文件名称格式-->
          <datePattern value="-yyyy.MM.dd" />
          <!--文件名按日期滚动-->
          <rollingStyle value="Date" />
          <maxSizeRollBackups value="10" />
          <!--文件名称不固定,可变-->
          <staticLogFileName value="false" />
          <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" />
          </layout>
        </appender>
        <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
          <!--BufferSize为缓冲区大小,只有日志记录超1条才会一块写入到数据库-->
          <bufferSize value="1"/>
          <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
          <connectionString value="Data Source=****;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***;MultipleActiveResultSets=True"/>
          <commandText value="INSERT INTO edu_log (Date,Thread,Level,Logger,Message,SchoolID,SysTypeID) values(@log_date,@thread,@log_level,@logger,@content,@s_id,@t_id)"/>
          <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="@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="@content" />
            <dbType value="String" />
            <size value="4000" />
            <layout type="FuNong.Framework.Logger.CustomLayout">
              <conversionPattern value="%property{content}" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@s_id" />
            <dbType value="String" />
            <size value="50" />
            <layout type="FuNong.Framework.Logger.CustomLayout">
              <conversionPattern value="%property{s_id}" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@t_id" />
            <dbType value="String" />
            <size value="50" />
            <layout type="FuNong.Framework.Logger.CustomLayout">
              <conversionPattern value="%property{t_id}" />
            </layout>
          </parameter>
        </appender>
      </log4net>
    


    注意上面配置代码中:log4net.Layout.PatternLayout 是log4net本身提供的配置模板,如果你有的字段需要用到其本身的模板字段的话,就可以使用。

    还需要注意这段话: <conversionPattern value="%property{s_id}" />,它表明,我们将会利用log4net提供的已有的property转义模板来识别我们的字段。

    但是如果你有自定义字段的话,你就需要自己写layout和converter了。在上面的配置文件中,content,s_id,t_id是我自定义的三个字段,如何让这三个字段也写入到数据库呢,我们一步一步来配置。

    首先,需要将三个自定义字段放到一个entity类中:

    namespace FuNong.Framework.Logger
    {
        public class LogContent
        {
            public LogContent(string content, string s_id, string t_id)
            {
                this.content = content;
                this.s_id = s_id;
                this.t_id = t_id;
            }
    
            public string content { get; set; }
    
            public string s_id { get; set; }
            public string t_id { get; set; }
        }
    }
    

     然后,定义我们自己的layout,由于我们使用了property字段模板,所以我们这里需要按照如下方式添加:

    namespace FuNong.Framework.Logger
    {
        public class CustomLayout:PatternLayout
        {
            public CustomLayout()
            {
                this.AddConverter("property", typeof(XPatternConverter));
            }
        }
    }
    

    最后,就是我们的Converter实现了:

    namespace FuNong.Framework.Logger
    {
        public class XPatternConverter : PatternLayoutConverter
        {
            protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
            {
                if (this.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;
    
                propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
                if (propertyInfo != null)
                {
                    propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
                }
                return propertyValue;
            }
    
        }
    }
    

     从上面代码,我们可以看到,log4net会通过反射来识别我们logContent这个entity中的字段,然后逐个赋值,再写到数据库的。

    下面我们稍微包装一下:

    namespace FuNong.Framework.Logger
    {
        public interface ILoggerService
        {
            void Debug(object message);
            void Error(object message);
            void Fatal(object message);
            void Info(object message);
            void Warn(object message);
        }
    }
    
    namespace FuNong.Framework.Logger
    {
        public class LoggerService:ILoggerService
        {
            public LoggerService()
            {
                log4net.Config.XmlConfigurator.Configure();
                logger = LogManager.GetLogger(typeof(LoggerService));
            }
    
            private readonly ILog logger;
    
            public void Info(object message)
            {
                logger.Info(message);
            }
            public void Warn(object message)
            {
                logger.Warn(message);
            }
            public void Debug(object message)
            {
                logger.Debug(message);
            }
            public void Error(object message)
            {
                logger.Error(message);
            }
            public void Fatal(object message)
            {
                logger.Fatal(message);
            }
           
        }
    }
    

    由于我用了autofac做ioc,所以我们就直接看使用方法吧:

      protected override void OnAuthorization(AuthorizationContext filterContext)
            {
                if (auth)
                {
                    var collection = cookie.GetCookieCollection("FuNong.UserInfo.Login");
                    if (collection == null)
                    {
                        logger.Warn(new LogContent("用户登陆信息提取失败,将会跳转到登陆界面...", "1", "2"));
                        filterContext.Result = new RedirectResult("Home/Login");
                    }
                    else
                    {
                        logger.Info(new LogContent("用户验证成功,请继续之前操作...","1","2"));
                    }
                }
            }
    

    这样,当我们运行起来后,我们就发现,程序已经将数据写入数据库了。

    整个配置不难,但是细节挺多,稍微不小心,就可能导致写入不到数据库。

  • 相关阅读:
    BootStrap练习
    表单控件练习
    K近邻算法原理
    CSS 边框和颜色
    SVG平移和旋转
    SVG进阶练习
    SVG路标(marker)
    SVG 曲线与文字
    python函数与异常处理
    if-elif-else分支判断语句(附加continue和break)---举例说明
  • 原文地址:https://www.cnblogs.com/scy251147/p/4456327.html
Copyright © 2011-2022 走看看