log4net ADO.NET Appender работает в Dev Fabric, но тихо завершает работу в Azure - PullRequest
6 голосов
/ 18 мая 2010

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

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

<?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 регистрирует ошибки из фабрики разработчиков, но не может это сделать из операционной системы Azure, используя точно такие же файлы конфигурации службы?

Ответы [ 3 ]

13 голосов
/ 27 ноября 2011

Я просто столкнулся с этим и провел большую часть дня, пытаясь понять это. Все сводилось к тому, что 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
3 голосов
/ 04 августа 2011

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

log4net: ОШИБКА [log4netDbAppender] не выполнена в DoAppend System.Data.SqlClient.SqlException (0x80131904): транспортный уровень произошла ошибка при отправке запроса на сервер. (Поставщик: Поставщик TCP, ошибка: 0 - установленное соединение было прервано программное обеспечение на вашем хост-компьютере.) в System.Data.SqlClient.SqlConnection.OnError (исключение SqlException, Boolean breakConnection) в System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning () в System.Data.SqlClient.TdsParserStateObject.WriteSni () в System.Data.SqlClient.TdsParserStateObject.ExecuteFlush () в System.Data.SqlClient.TdsParser.TdsExecuteRPC (_SqlRPC [] rpcArray, Тайм-аут Int32, логическое значение inSchema, запрос SqlNotificationRequest NotificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc) в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, RunBehavior runBehavior, логическое returnStream, логическое асинхронно) в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, логическое returnStream, строка метод, результат DbAsyncResult) в System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery (DbAsyncResult результат, String methodName, Boolean sendToPipe) в System.Data.SqlClient.SqlCommand.ExecuteNonQuery () в log4net.Appender.AdoNetAppender.SendBuffer (IDbTransaction dbTran, LoggingEvent [] events) в log4net.Appender.AdoNetAppender.SendBuffer (события LoggingEvent [])
в log4net.Appender.BufferingAppenderSkeleton.Append (LoggingEvent loggingEvent) в log4net.Appender.AppenderSkeleton.DoAppend (LoggingEvent loggingEvent)

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

EDIT Что может помочь, так это установка AdoNetAppender.ReconnectOnError = true, по умолчанию это false.

0 голосов
/ 18 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...