2010-05-18 16 views
6

J'utilise l'appender AD4.NET de log4net pour consigner les messages du rôle de travail Azure dans l'instance SQL Azure (le diagnostic par défaut ne correspond tout simplement pas). Pour une raison quelconque, lors de l'exécution du worker dans dev fabric, la journalisation fonctionne. Cependant, lorsque l'instance est déployée dans le cloud (avec exactement la même configuration), les erreurs ne sont pas consignées.log4net ADO.NET Appender fonctionne sur Dev Fabric, mais échoue silencieusement sur Azure

Configuration se produit dans le code en utilisant ce fichier:

<?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 est initialisé avec les valeurs propres, lorsque l'environnement est Autofac IoC initalized (par démarrage du rôle). Le code ressemble à ceci:

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

Le système d'exploitation Azure par défaut est utilisé. Les connexions SQL sont évidemment valides.

Quelqu'un peut-il, s'il vous plaît, penser à raison, pourquoi log4net enregistre les erreurs de la structure de développement, mais ne parvient pas à le faire à partir du système d'exploitation azure, en utilisant exactement les mêmes fichiers de configuration de service?

+0

une chance avec cela? J'ai le même problème. – Nick

+0

Pas beaucoup. Supprimé complètement log4net en faveur d'un simple enregistreur personnalisé. –

Répondre

0

Cela peut-il être un problème avec vos règles de pare-feu SQL Azure?

+0

Malheureusement, non. La même chaîne de connexion SQL Azure est utilisée par les gestionnaires de commandes CQRS dans le même rôle de travail sans aucun problème dans les scénarios dev fabric et azure. –

3

Je peux avoir un plomb dans ce problème. J'ai activé la consignation interne pour log4net comme décrit here. L'enregistrement fonctionnerait pendant un certain temps et s'arrêterait alors. L'erreur causant dans le journal log4net était:

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)

Il semble que log4net cesse d'essayer après avoir rencontré cette erreur. This article décrit une façon de traiter ce type d'exception en général et cela pourrait être utilisé pour étendre AdoNetAppender.

EDIT Ce qui peut aider est la mise en AdoNetAppender.ReconnectOnError = true, il est faux par défaut.

13

Je viens juste de tomber dessus et j'ai passé la meilleure partie de la journée à essayer de comprendre. Cela tenait au fait que SQL Azure requiert des index clusterisés sur vos tables. L'exemple de code SQL fourni par log4net pour créer la table Log n'a pas d'index clusterisé, ce qui est obligatoire pour SQL Azure. L'ajout de n'importe quelle donnée à la table échouera à moins d'avoir un index en cluster (au moment où cela est écrit). Essayez de faire une instruction d'insertion manuelle à l'aide de SQL Server Management Studio lors de la connexion à SQL Azure et il vous dira tout de suite si c'est le problème. Si tel est le cas, exécutez le code SQL suivant pour ajouter un index clusterisé sur la table (en supposant que vous ayez utilisé SQL direct depuis log4net), puis réessayez.

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

Merci d'avoir suggéré d'essayer un insert manuel! –