2010-05-18 5 views
6

Sto usando log4net appender ADO.NET per registrare i messaggi di Azure Worker Role nell'istanza di SQL Azure (la diagnostica predefinita non è adatta). Per qualche ragione, mentre si esegue il worker in dev fabric, la registrazione funziona. Tuttavia, quando l'istanza viene distribuita nel cloud (con esattamente la stessa configurazione) gli errori non vengono registrati.log4net ADO.NET Appender funziona su Dev Fabric, ma fallisce silenziosamente su Azure

configurazione avviene nel codice utilizzando questo file:

<?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 viene inizializzato con i valori corretti, quando l'ambiente Autofac CIO è initalized (per l'avvio di ruolo). Il codice è simile al seguente:

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

Viene utilizzato il sistema operativo di Azure predefinito. Le connessioni SQL sono ovviamente valide.

Qualcuno potrebbe, per favore, pensare alla ragione, perché log4net registra gli errori dal fabric di sviluppo, ma non riesce a farlo dal sistema operativo blu, usando esattamente gli stessi file di configurazione del servizio?

+0

sfortuna con questo? Sto avendo lo stesso problema. – Nick

+0

Non molto. Dropped completamente log4net in favore di un semplice logger personalizzato. –

risposta

0

Potrebbe essere un problema con le regole del firewall SQL Azure?

+0

Purtroppo no. La stessa stringa di connessione SQL di Azure viene utilizzata dai gestori di comandi CQRS all'interno dello stesso ruolo di lavoro senza problemi in entrambi gli scenari di elaborazione e azzeramento. –

3

Posso avere un vantaggio in questo problema. Ho abilitato la registrazione interna per log4net come descritto here. La registrazione funzionerebbe per un po 'e poi si fermerebbe. L'errore che causava il log log4net era:

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)

Sembra che log4net smetta di provare dopo aver riscontrato questo errore. L'articolo This descrive un modo per gestire questo tipo di eccezione in generale e questo potrebbe essere utilizzato per estendere AdoNetAppender.

EDIT Quello che può aiutare è l'impostazione AdoNetAppender.ReconnectOnError = vero, è falso per impostazione predefinita.

13

Mi sono imbattuto in questo e ho trascorso la maggior parte della giornata cercando di capirlo. Si è giunti al fatto che SQL Azure richiede indici cluster sulle tabelle. Il codice SQL di esempio fornito da log4net per creare la tabella Log non ha un indice cluster, che è un requisito per SQL Azure. L'aggiunta di tutti i dati alla tabella avrà esito negativo a meno che non abbia un indice cluster (al momento in cui questo viene scritto).

Provare a fare una istruzione di inserimento manuale utilizzando SQL Server Management Studio mentre si è connessi a SQL Azure e verrà indicato immediatamente se questo è il problema. In tal caso, eseguire il seguente SQL per aggiungere un indice cluster sulla tabella (presupponendo che sia stato utilizzato SQL direttamente da log4net) e quindi riprovare.

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

Grazie per aver suggerito di provare un inserto manuale! –