代码之家  ›  专栏  ›  技术社区  ›  Christopher Johnson

Log4Net似乎连接到数据库,但没有插入

  •  3
  • Christopher Johnson  · 技术社区  · 7 年前

    我已经打开了调试,所以我很确定它正在连接到db。我之所以这么说,是因为如果我拼错了数据库名称,它会将错误写入输出。

    我所做的是适应 this tutorial 整合到一个项目中。如果你需要看更多,请告诉我。

    Log4Net.config

    <?xml version="1.0" encoding="utf-8" ?>
    <log4net debug="true">
      <root>
        <level value="ALL"/>
        <appender-ref ref="AdoNetAppender"/>
        <appender-ref ref="DebugAppender"/>
      </root>
      <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" />
      <connectionString value="Data Source=server;Initial Catalog=db; User Id=user; Password=pass" />
      <commandText value="INSERT INTO LogException ([LogLevel],[LogMessage],[StackTrace],[Object],[CreateDateTime]) VALUES (@log_level, @message, @stacktrace, @exception, @date)" />
        <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="@message" />
          <dbType value="String" />
          <size value="4000" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@exception" />
          <dbType value="String" />
          <size value="2000" />
          <layout type="log4net.Layout.ExceptionLayout" />
        </parameter>
        <parameter>
          <parameterName value="@entryAssembly" />
          <dbType value="String" />
          <size value="200" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%property{entryAssembly}" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@callingAssembly" />
          <dbType value="String" />
          <size value="200" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%property{callingAssembly}" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@method" />
          <dbType value="String" />
          <size value="2000" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%property{method}" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@stacktrace" />
          <dbType value="String" />
          <size value="2000" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%stacktrace" />
          </layout>
        </parameter>
      </appender>
    </log4net>
    

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using Logging.Contracts.Log;
    using log4net;
    using log4net.Appender;
    using log4net.Config;
    using log4net.Filter;
    using log4net.Util;
    
    
    namespace Logging
    {
        public class Log4NetLoggingService : ILoggingService
        {
            private readonly ILog _logger;
    
            static Log4NetLoggingService()
            {
                var log4NetConfigFilePath = @"C:\Work\folder\Main\Logging\Log4Net.config";
    
                XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));
    
            }
    
            //targets reads from and enum to know where to save.
            public Log4NetLoggingService(LogTarget targets = LogTarget.All)
            {
                _logger = LogManager.GetLogger(new StackFrame(1).GetMethod().DeclaringType);
    #if DEBUG
                var error = LogManager.GetRepository().ConfigurationMessages.Cast<LogLog>();
    #endif
    
                if (targets.HasFlag(LogTarget.All))
                    return;
    
                SwitchOffLogTargets(targets);
            }
    
            protected ILog logger { get { return _logger; } }
    
            public void Fatal(ErrorLogEntry logEntry)
            {
                logEntry.Level = Level.Fatal.ToString();
                if (_logger.IsFatalEnabled)
                    _logger.Fatal(logEntry);
            }
    
            public void Error(ErrorLogEntry logEntry)
            {
                logEntry.Level = Level.Error.ToString();
                if (_logger.IsErrorEnabled)
                    _logger.Error(logEntry);
            }
    
            public void Warn(LogEntry logEntry)
            {
                logEntry.Level = Level.Warn.ToString();
                if (_logger.IsWarnEnabled)
                    _logger.Warn(logEntry);
            }
    
            public void Info(LogEntry logEntry)
            {
                logEntry.Level = Level.Info.ToString();
                if (_logger.IsInfoEnabled)
                    _logger.Info(logEntry);
            }
    
            public void Debug(LogEntry logEntry)
            {
                logEntry.Level = Level.Debug.ToString();
                if (_logger.IsDebugEnabled)
                    _logger.Debug(logEntry);
            }
    
            private void SwitchOffLogTargets(LogTarget targets)
            {
                var appenders = _logger.Logger.Repository.GetAppenders().ToList();
    
                if (!targets.HasFlag(LogTarget.Database))
                {
                    var db = appenders.FirstOrDefault(piA => piA is AdoNetAppender);
                    if (db != null)
                        ((AdoNetAppender)db).AddFilter(new DenyAllFilter());
                }
    
                if (!targets.HasFlag(LogTarget.TextFile))
                {
                    var file = appenders.FirstOrDefault(piA => piA is RollingFileAppender);
                    if (file != null)
                        ((RollingFileAppender)file).AddFilter(new DenyAllFilter());
                }
    
                if (!targets.HasFlag(LogTarget.Trace))
                {
                    var trace = appenders.FirstOrDefault(piA => piA is AspNetTraceAppender);
                    if (trace != null)
                        ((AspNetTraceAppender)trace).AddFilter(new DenyAllFilter());
                }
    
            }
        }
    }
    

    事实证明,我最近的尝试奏效了。我只是拼错了配置文件名。我希望这对将来的人有所帮助。我计划写一篇关于这个的博客文章。

    Log4Net.config

    <?xml version="1.0" encoding="utf-8" ?>
    <log4net>
      <root>
        <level value="ALL" debug="true"/>
        <!--Add the appenders you want to use here-->
        <appender-ref ref="AdoNetAppender"/>
        <!--to debug log4net. check the output window of Visual Studio-->
        <appender-ref ref="DebugAppender"/>
      </root>
      <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" />
        <connectionString value="data source=(localdb)\MSSQLLocalDB;initial catalog=log4NetTestDB;integrated security=false;persist security info=True;" />
        <commandText value="INSERT INTO LogException ([Message]) VALUES (@message)" />
          <parameter>
            <parameterName value="@message" />
            <dbType value="String" />
            <size value="4000" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%message" />
            </layout>
          </parameter>
      </appender>
    </log4net>
    

    ILoggingAdapter

    namespace Logging
    {
        public interface ILoggingAdapter
        {
            TimeSpan ExecutionTime { get; set; }
            int Counter { get; set; }
            void Info(string message);
            void Warn(string message);
    
        }
    }
    

    记录器

    namespace Logging
    {
        public sealed class Logger : ILoggingAdapter
        {
            private ILog _log = LogManager.GetLogger(typeof(Logger));
    
            public TimeSpan ExecutionTime { get; set; }
            public int Counter { get; set; }
            public string Info { get; set; }
            public string Warn { get; set; }
    
    
            void ILoggingAdapter.Info(string message)
            {
                throw new NotImplementedException();
            }
    
            void ILoggingAdapter.Warn(string message)
            {
                _log.Warn(message);
            }
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   George Mauer    7 年前

    好的,有几个注释

    • 您是否尝试以指定用户的身份登录到数据库并运行所需的插入查询?
    • enabling debug mode 在log4net中查看引擎盖下发生了什么?
    • 与上述内容相关,在根目录下使用两个记录器——一个用于数据库,另一个用于文件。这是一个 可怕的 只使用数据库日志记录的想法,因为如果数据库失败,您将不会得到关于它失败的日志。至少,您的本地开发环境应该记录到一个文件中
    • beefycoder has written a ton about understanding log4net
    • 我不知道你为什么要做这样的事情 if (_logger.IsInfoEnabled) -就是这样 LogInfo 已经
    • 你究竟为什么要 LogEntry 作为参数类型?使用这样的服务类的全部目的是打破对log4net的硬依赖。通过使用该类类型,您已经在您的消费者中创建了对log4net的硬依赖。只需输入字符串。这样你就不需要整个 logEntry.Level = Level.Warn.ToString();
    • 文件中的硬编码路径字符串。这在其他开发人员的机器上不起作用。
    • 构造器中的堆栈检查-您现在已经显著降低了使用该方法的任何类的构造速度, 当在内联打开的情况下以发布模式构建时,它会给你带来不同的结果。与其使用服务类,不如创建一个扩展方法,或者传入你希望记录器作为一个参数来源的对象,该参数做同样的事情。
    • SwitchOffLogTargets