WedX - журнал о программировании и компьютерных науках

Log4Net, похоже, подключается к базе данных, но не вставляет

У меня включена отладка, поэтому я почти уверен, что он подключается к базе данных. Я говорю это потому, что, если я ошибаюсь в названии базы данных, она выводит ошибку.

Я не уверен, что делаю не так. Я знаю, что у меня есть параметры, которые еще не используются.

Я адаптировал это руководство в один проект. . Если вам нужно увидеть больше, дайте мне знать.

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>

Log4netLoggingService.cs

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);
        }
    }
}

  • Может быть, это только я, но, с одной стороны, связанное решение кажется слишком неуклюжим и переворачивает все с ног на голову: ведение журнала Imho должно быть максимально простым и быстрым, в то время как анализ журналов не повредит, если вам нужно немного ETL. Более того, похоже, вы не собираетесь использовать предлагаемые функции сериализации - несколько целей журналов и уровней журналов можно легко настроить без какого-либо кода. Если вы просто хотите войти в свою базу данных, блог сбивает вас с пути. 27.07.2017
  • Да, я начинаю думать, что это ошибочный подход. Меня привлекла его детализация, особенно потому, что я не был уверен, какими будут требования к ведению журнала сейчас и в будущем. 27.07.2017
  • Доверьтесь @George и мне: Log4Net и доступные приложения достаточно гибки для практически всего, что вы можете себе представить. Лучше всего начать с базовой настройки и добавить навороты позже. Если вы обнаружите, что не можете обойтись без очень специфических функций, лучше подумайте о разработке подходящего приложения, чем переделывайте существующий приложение, как показано в блоге. 27.07.2017

Ответы:


1

Хорошо, несколько заметок

  • Вы пробовали войти в свою базу данных как указанный пользователь и выполнить нужный запрос на вставку?
  • Вы пробовали включить режим отладки в log4net, чтобы увидеть, что происходит под капотом?
  • В связи с вышеизложенным используйте два регистратора в корне - один для базы данных, другой для файла. ужасная идея использовать только ведение журнала db, так как если db выйдет из строя, вы не получите журнал об этом. По крайней мере, ваша локальная среда разработки должна вести журнал в файл
  • beefycoder много написал о понимании log4net обратите внимание на многие части этого учебника
  • Я понятия не имею, почему вы делаете такие вещи, как if (_logger.IsInfoEnabled) - это то, что LogInfo уже делает.
  • С какой стати вы берете LogEntry в качестве типа параметра? Вся суть использования такого класса обслуживания состоит в том, чтобы избавиться от жесткой зависимости от log4net. Используя этот тип класса, вы только что создали жесткую зависимость от log4net у ваших потребителей. Просто передавайте по строкам. И так вам не понадобится вся эта logEntry.Level = Level.Warn.ToString(); ерунда
  • Жестко закодированная строка пути в вашем файле. Теперь это не будет работать на машинах других разработчиков.
  • Проверка стека в конструкторе - теперь вы значительно замедлили создание любых классов, которые его используют, и он даст вам разные результаты при построении в режиме RELEASE с включенным встраиванием. Вместо того, чтобы использовать класс обслуживания, просто создайте метод расширения или передайте объект, который вы хотите использовать для регистратора, в качестве параметра, который делает то же самое.
  • Конфигурация вашего кода переопределяет конфигурацию xml (я думаю ... правила log4net в порядке приоритета нечеткие - это большая причина, по которой я предпочитаю NLog)
  • SwitchOffLogTargets почему !? Просто измените файл конфигурации, если хотите такого поведения. Конфигурационный файл может определять любые цели, которые он хочет, и может быть изменен в любое время, но здесь вы просто предполагаете, что в нем есть определенные вещи.
27.07.2017
  • Я планирую поцарапать это и начать с чего-нибудь простого. Спасибо за полезный обзор этого подхода. 28.07.2017
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]