log4net ADO.NET Appender работает на Dev Fabric, но не работает в Azure.

Я использую приложение log4net ADO.NET для регистрации сообщений рабочей роли Azure в экземпляре SQL Azure (диагностика по умолчанию просто не подходит). По какой-то причине при запуске воркера в dev Fabric ведение журнала работает. Тем не менее, когда экземпляр развертывается в облаке (с точно такой же конфигурацией), ошибки не регистрируются.

Конфигурация происходит в коде с использованием этого файла:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <renderer renderingClass="{ExceptionRenderer}" renderedClass="System.Exception" />
  <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
    <layout type="log4net.Layout.PatternLayout">
      <!--<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />-->
      <conversionPattern value="%message%newline" />
    </layout>
  </appender>
  <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
    <bufferSize value="3" />
    <connectionType value="{ConnectionType}" />
    <connectionString value="{ConnectionString}" />
    <commandText value="INSERT INTO Salescast_Log ([Date],[Thread],[Version],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, '{Version}',@log_level, @logger, @message, @exception)" />
    <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="4000" />
      <layout type="{ExceptionLayoutType}" />
    </parameter>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="ERROR" />
      <levelMax value="FATAL" />
    </filter>
  </appender>
  <root>
    <level value="DEBUG" />
    <appender-ref ref="TraceAppender" />
    <appender-ref ref="AdoNetAppender" />
  </root>
</log4net>

log4net инициализируется с правильными значениями, когда инициализируется среда Autofac IoC (при запуске роли). Код выглядит так:

static ILogProvider BuildProvider(IComponentContext context)
{
  var connection = context
    .Resolve<IProvideBusSettings>()
    .GetString("SqlConnection")
    .ExposeException("Failed to get SQL string for logging");

  var xml = Properties.Resources.Logging
    .Replace("{ConnectionType}", typeof(SqlConnection).AssemblyQualifiedName)
    .Replace("{ConnectionString}", connection)
    .Replace("{ExceptionLayoutType}", typeof(LoggingTrimmedExceptionLayout).AssemblyQualifiedName)
    .Replace("{ExceptionRenderer}", typeof(LoggingExceptionRenderer).AssemblyQualifiedName)
    .Replace("{Version}", SystemDescriptor.Default.Version.ToString());

  var doc = new XmlDocument();
  doc.LoadXml(xml);
  XmlConfigurator.Configure(doc.DocumentElement);
  return new LoggingProvider();
}

Используется ОС Azure по умолчанию. Соединения SQL, очевидно, действительны.

Может ли кто-нибудь придумать причину, по которой log4net регистрирует ошибки из фабрики разработки, но не может сделать это из лазурной ОС, используя точно такие же файлы конфигурации службы?


person Rinat Abdullin    schedule 18.05.2010    source источник
comment
есть ли удача с этим? У меня такая же проблема.   -  person Nick    schedule 08.11.2010
comment
Немного. Отбросил полностью log4net в пользу простого кастомного логгера.   -  person Rinat Abdullin    schedule 08.11.2010


Ответы (3)


Я просто столкнулся с этим и потратил большую часть дня, пытаясь понять это. Дело дошло до того, что SQL Azure требует кластеризованных индексов в ваших таблицах. Пример кода SQL, предоставленный log4net для создания таблицы журнала, не имеет кластеризованного индекса, что является требованием для SQL Azure. Добавление каких-либо данных в таблицу не удастся, если у нее нет кластеризованного индекса (на момент написания).

Попробуйте выполнить инструкцию вставки вручную с помощью SQL Server Management Studio при подключении к SQL Azure, и он сразу скажет вам, является ли это проблемой. Если это так, запустите следующий SQL, чтобы добавить кластеризованный индекс в таблицу (при условии, что вы использовали SQL непосредственно из log4net), а затем повторите попытку.

CREATE UNIQUE CLUSTERED INDEX PK_Log ON [Log]
  ([Id])
GO
person Mike Taber    schedule 27.11.2011

У меня может быть зацепка по этому вопросу. Я включил внутреннее ведение журнала для log4net, как описано здесь. Запись будет работать некоторое время, а затем остановится. Причиной ошибки в журнале log4net была:

log4net: ОШИБКА [log4netDbAppender] Ошибка в DoAppend System.Data.SqlClient.SqlException (0x80131904): при отправке запроса на сервер произошла ошибка транспортного уровня. (поставщик: поставщик TCP, ошибка: 0 - установленное соединение было прервано программным обеспечением на вашем хост-компьютере.) в System.Data.SqlClient.SqlConnection.OnError (исключение SqlException, логическое breakConnection) в System.Data.SqlClient.TdsParser. Бросить исключение notificationRequest, TdsParserStateObject stateObj, булева isCommandProc) в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, runBehavior runBehavior, Boolean, Boolean returnStream асинхронном) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, runBehavior runBehavior, булевой returnStream , Метод String, результат DbAsyncResult) в System.Data.SqlClient.SqlCommand.In ternalExecuteNonQuery (результат DbAsyncResult, String methodName, логическое значение sendToPipe) в System.Data.SqlClient.SqlCommand.ExecuteNonQuery () в log4net.Appender.AdoNetAppender.SendBuffer (IDbTransaction dbventAndender.SendBuffer (IDbTransaction dbventAnddoing.logAppender.События LogAppender (события IDbTransaction dbventAnddo) (события LogAppender. [] события)
в log4net.Appender.BufferingAppenderSkeleton.Append (LoggingEvent loggingEvent) в log4net.Appender.AppenderSkeleton.DoAppend (LoggingEvent loggingEvent)

Похоже, что после появления этой ошибки log4net прекращает попытки. В этой статье описывается, как справиться с этим типом исключения в целом и с этим может использоваться для расширения AdoNetAppender.

РЕДАКТИРОВАТЬ. Может помочь установка AdoNetAppender.ReconnectOnError = true, по умолчанию - false.

person eulerfx    schedule 03.08.2011

Может быть, проблема в ваших правилах брандмауэра SQL Azure?

person user94559    schedule 18.05.2010
comment
К сожалению нет. Одна и та же строка подключения SQL Azure используется обработчиками команд CQRS в рамках одной и той же рабочей роли без каких-либо проблем как в сценариях структуры разработки, так и в сценариях Azure. - person Rinat Abdullin; 19.05.2010