2010-05-18 6 views
6

Ich verwende log4net Appender ADO.NET, um Nachrichten der Azure Worker Role in die SQL Azure-Instanz zu protokollieren (Standarddiagnose passt einfach nicht). Aus irgendeinem Grund funktioniert die Protokollierung, während der Worker in der Entwicklungsumgebung ausgeführt wird. Wenn die Instanz jedoch in der Cloud bereitgestellt wird (mit genau der gleichen Konfiguration), werden Fehler nicht protokolliert.log4net ADO.NET Appender funktioniert auf Dev Fabric, schlägt jedoch im Hintergrund auf Azure fehl

Konfiguration geschieht in dem Code mit dieser Datei:

<?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 wird mit den richtigen Werten initialisiert, wenn die Autofac IoC Umgebung (pro Rolle Start) initialisiert wird. Der Code sieht wie folgt aus:

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

Standard Azure OS verwendet wird. SQL-Verbindungen sind offensichtlich gültig.

Könnte irgendjemand, bitte, an den Grund denken, warum log4net Fehler vom Dev-Fabric protokolliert, aber das vom azure OS nicht tut, indem es exakt dieselben Service-Konfigurationsdateien verwendet?

+0

Glück dabei? Ich habe das gleiche Problem. – Nick

+0

Nicht viel. Komplett log4net zugunsten eines einfachen benutzerdefinierten Loggers fallengelassen. –

Antwort

0

Könnte es ein Problem mit Ihren SQL Azure Firewallregeln sein?

+0

Leider nein. Die gleiche SQL Azure-Verbindungszeichenfolge wird von CQRS-Befehlshandlern in derselben Worker-Rolle ohne Probleme sowohl in der Entwicklungsumgebung als auch in azure-Szenarien verwendet. –

3

Ich habe möglicherweise einen Hinweis auf dieses Problem. Ich habe die interne Protokollierung für log4net wie beschrieben here aktiviert. Das Logging würde für eine Weile funktionieren und würde dann aufhören. Der verursachende Fehler im log4net-Protokoll war:

log4net:ERROR [log4netDbAppender] Failed in DoAppend System.Data.SqlClient.SqlException (0x80131904): A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An established connection was aborted by the software in your host machine.) at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParserStateObject.WriteSni() at System.Data.SqlClient.TdsParserStateObject.ExecuteFlush() at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at log4net.Appender.AdoNetAppender.SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) at log4net.Appender.AdoNetAppender.SendBuffer(LoggingEvent[] events)
at log4net.Appender.BufferingAppenderSkeleton.Append(LoggingEvent loggingEvent) at log4net.Appender.AppenderSkeleton.DoAppend(LoggingEvent loggingEvent)

Es scheint wie log4net beendet versucht, nachdem dieser Fehler auftritt. This Artikel beschreibt eine Möglichkeit, mit dieser Art von Ausnahme im Allgemeinen umzugehen, und dies könnte verwendet werden, um AdoNetAppender zu erweitern.

EDIT Was kann helfen, setzt AdoNetAppender.ReconnectOnError = true, es ist falsch standardmäßig aktiviert.

13

Ich bin einfach reingelaufen und verbrachte den besseren Teil des Tages damit, es herauszufinden. Es kam darauf an, dass SQL Azure Clustered-Indizes für Ihre Tabellen benötigt. Der Beispiel-SQL-Code, der von log4net zum Erstellen der Protokolltabelle bereitgestellt wird, enthält keinen Clustered-Index, der für SQL Azure erforderlich ist. Das Hinzufügen von Daten überhaupt zu der Tabelle wird fehlschlagen, es sei denn, es hat einen gruppierten Index (zum Zeitpunkt der geschrieben wird).

Versuchen Sie, eine manuelle Einfügeanweisung mit SQL Server Management Studio auszuführen, während Sie mit SQL Azure verbunden sind, und es wird Ihnen sofort sagen, ob dies das Problem ist. Ist dies der Fall, führen Sie die folgende SQL-Anweisung aus, um einen gruppierten Index für die Tabelle hinzuzufügen (vorausgesetzt, Sie haben SQL direkt von log4net verwendet), und versuchen Sie es erneut.

CREATE UNIQUE CLUSTERED INDEX PK_Log ON [Log] 
    ([Id]) 
GO 
+0

Vielen Dank für den Vorschlag, eine manuelle Eingabe zu versuchen! –

Verwandte Themen