Problema di file bloccato con log4net RollingFileAppender intermittente


113

Stiamo riscontrando un problema intermittente sulle macchine di sviluppo e produzione per cui i nostri file di registro non vengono registrati.

Durante l'esecuzione in sviluppo e debug utilizzando Visual Studio, vengono visualizzati i seguenti messaggi di errore di log4net nella finestra di output di VS:

log4net:ERROR [RollingFileAppender] Unable to acquire lock on file C:\folder\file.log.

Il processo non può accedere al file "C: \ cartella \ file.log" perché è utilizzato da un altro processo.

log4net:ERROR XmlConfigurator: Failed to find configuration section 'log4net' in the application's .config file.
Check your .config file for the <log4net> and <configSections> elements.

La sezione di configurazione dovrebbe essere simile a:

<section
  name="log4net"
  type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

La nostra soluzione attuale per il problema è rinominare l'ultimo file di registro. Ovviamente ci aspetteremmo che ciò fallisse (a causa del blocco dei file sopra menzionato), ma normalmente non è così. Una o due volte la ridenominazione non è riuscita a causa di un blocco dal processo aspnet_wp.exe .

La nostra sezione di configurazione di log4net è mostrata di seguito:

<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="C:\folder\file.log"/>
    <appendToFile value="true" />
    <datePattern value="yyyyMMdd" />
    <rollingStyle value="Date" />
    <maximumFileSize value="10MB" />
    <maxSizeRollBackups value="100" />
    <layout type="log4net.Layout.PatternLayout">
      <header value="[Header]&#xA;"/>
      <footer value="[Footer]&#xA;"/>
      <conversionPattern value="%date %-5level %logger ${COMPUTERNAME} %property{UserHostAddress} [%property{SessionID}] - %message%newline"/>
    </layout>
  </appender>
  <root>
    <level value="INFO"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>

Come accennato, lo vediamo in modo intermittente sulle macchine, ma una volta che il problema si verifica, persiste.

Risposte:


172

Prova ad aggiungere

<lockingModel type = "log4net.Appender.FileAppender + MinimalLock" />

al tuo <appender />elemento. C'è un certo impatto sulle prestazioni perché questo significa che log4net bloccherà il file, vi scriverà e lo sbloccherà per ogni operazione di scrittura (al contrario del comportamento predefinito, che acquisisce e mantiene il blocco per lungo tempo).

Un'implicazione del comportamento predefinito è che se lo si utilizza in un sito Web che viene eseguito in più processi di lavoro in esecuzione sulla stessa macchina, ognuno proverà ad acquisire e mantenere quel blocco a tempo indeterminato, e due di loro sono perderò. La modifica del modello di blocco al blocco minimo risolve questo problema.

(Durante il debug, le terminazioni sgraziate e l'avvio di molti nuovi processi di lavoro è esattamente il tipo di cosa che è probabile che accada.)

In bocca al lupo!


Mi ha risparmiato molti grattacapi sul motivo per cui il mio registratore funzionava a intermittenza. Ho aggiunto i processi di lavoro al pool di app, duh!
RhinoDevX64

Lo sto usando in un servizio e oltre a questa modifica, l'utente ha eseguito il servizio in base alle autorizzazioni necessarie per scrivere. Grazie!
LowTide

Grazie mille, risparmiato molto tempo.
Siva

2
Vorrei solo leggere il file, ma log4net si blocca anche per la lettura ... potrebbe bloccarsi solo per la scrittura e condividere la lettura
JobaDiniz

37

Tieni inoltre presente le domande frequenti su log4net :

Come posso ottenere più processi per accedere allo stesso file?

Prima ancora di iniziare a provare una qualsiasi delle alternative fornite, chiediti se hai davvero bisogno di avere più processi registrati nello stesso file, quindi non farlo ;-).

FileAppender offre modelli di blocco collegabili per questo caso d'uso, ma tutte le implementazioni esistenti presentano problemi e svantaggi.

Per impostazione predefinita, FileAppender mantiene un blocco di scrittura esclusivo sul file di registro durante la registrazione. Ciò impedisce ad altri processi di scrivere nel file. È noto che questo modello si rompe con (almeno su alcune versioni di) Mono su Linux e i file di registro potrebbero essere danneggiati non appena un altro processo tenta di accedere al file di registro.

MinimalLock acquisisce il blocco di scrittura solo durante la scrittura di un log. Ciò consente a più processi di intercalare le scritture sullo stesso file, sebbene con una notevole perdita di prestazioni.

InterProcessLock non blocca affatto il file ma si sincronizza utilizzando un Mutex a livello di sistema. Questo funzionerà solo se tutti i processi cooperano (e utilizzano lo stesso modello di blocco). L'acquisizione e il rilascio di un Mutex per ogni voce di log da scrivere comporterà una perdita di prestazioni, ma il Mutex è preferibile all'uso di MinimalLock.

Se si utilizza RollingFileAppender le cose peggiorano poiché diversi processi potrebbero tentare di avviare contemporaneamente il file di registro. RollingFileAppender ignora completamente il modello di blocco quando si spostano i file, i file in rotazione semplicemente non sono compatibili con questo scenario.

Un'alternativa migliore è che i tuoi processi vengano registrati in RemotingAppenders. Utilizzando RemoteLoggingServerPlugin (o IRemoteLoggingSink) un processo può ricevere tutti gli eventi e registrarli in un unico file di registro. Uno degli esempi mostra come utilizzare RemoteLoggingServerPlugin.


6

Se hai

<staticLogFileName value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />

e aggiungi

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

allora ci sarà un errore durante il rotolamento. Il primo processo creerà il nuovo file e rinominerà il file corrente. Quindi i processi successivi faranno lo stesso e prenderanno il file appena creato e sovrascriveranno il file appena rinominato. Il risultato è che il campo di log dell'ultimo giorno è vuoto.


1
Ciò è vero solo quando più processi accedono allo stesso file in sequenza. È sicuro all'interno dello stesso processo. hectorcorrea.com/blog/log4net-thread-safe-but-not-process-safe
Mike Chamberlain

@MikeChamberlain Secondo l'OP (vedi il suo commento per rispondere) ci saranno più lavoratori che lavoreranno contemporaneamente, usando log4net per accedere. Quindi questo problema è pertinente!
seebiscuit
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.