web-dev-qa-db-fra.com

Problème de fichier verrouillé intermittent log4net RollingFileAppender

Nous constatons un problème intermittent sur les machines de développement et de production dans lequel nos fichiers journaux ne sont pas enregistrés.

Lors de l'exécution dans le développement et le débogage à l'aide de Visual Studio, nous obtenons les messages d'erreur log4net suivants dans la fenêtre de sortie VS:

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

Le processus ne peut pas accéder au fichier "C:\dossier\fichier.log" car il est utilisé par un autre processus.

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 section de configuration devrait ressembler à:

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

Notre solution de contournement actuelle consiste à renommer le dernier fichier journal. Nous nous attendrions bien sûr à ce que cela échoue (en raison du verrouillage de fichier susmentionné), mais ce n'est normalement pas le cas. Une ou deux fois, le changement de nom a échoué en raison d'un verrou du aspnet_wp.exe processus.

Notre section de configuration log4net est illustrée ci-dessous:

<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>

Comme mentionné, nous voyons cela de manière intermittente sur les machines, mais une fois que le problème se produit, il persiste.

108
Richard Everett

Essayez d'ajouter

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

à ton <appender /> élément. Il y a un certain impact sur les performances car cela signifie que log4net verrouille le fichier, y écrit et le déverrouille pour chaque opération d'écriture (par opposition au comportement par défaut, qui acquiert et conserve le verrou pendant une longue période).

Une implication du comportement par défaut est que si vous l'utilisez sous un site Web exécuté sous plusieurs processus de travail exécutés sur la même machine, chacun essaiera d'acquérir et de conserver ce verrou indéfiniment, et deux d'entre eux sont va juste perdre. La modification du modèle de verrouillage au verrouillage minimal contourne ce problème.

(Lors du débogage, les terminaisons ingrates et la rotation de nombreux nouveaux processus de travail sont exactement le type de chose qui risque de se produire.)

Bonne chance!

160
Nicholas Piasecki

Soyez également conscient de la log4net FAQ :

Comment obtenir plusieurs processus pour se connecter au même fichier?

Avant même de commencer à essayer l'une des alternatives proposées, demandez-vous si vous avez vraiment besoin d'avoir plusieurs processus journalisés dans le même fichier, puis ne le faites pas ;-).

FileAppender propose des modèles de verrouillage enfichables pour cette utilisation, mais toutes les implémentations existantes ont des problèmes et des inconvénients.

Par défaut, FileAppender détient un verrou d'écriture exclusif sur le fichier journal pendant qu'il se connecte. Cela empêche d'autres processus d'écrire dans le fichier. Ce modèle est connu pour tomber en panne avec (au moins sur certaines versions de) Mono sur Linux et les fichiers journaux peuvent être corrompus dès qu'un autre processus tente d'accéder au fichier journal.

MinimalLock acquiert le verrou d'écriture uniquement pendant l'écriture d'un journal. Cela permet à plusieurs processus d'entrelacer les écritures dans le même fichier, mais avec une perte considérable de performances.

InterProcessLock ne verrouille pas du tout le fichier mais se synchronise à l'aide d'un Mutex à l'échelle du système. Cela ne fonctionnera que si tous les processus coopèrent (et utilisent le même modèle de verrouillage). L'acquisition et la publication d'un Mutex pour chaque entrée de journal à écrire entraînera une perte de performances, mais le Mutex est préférable à l'utilisation de MinimalLock.

Si vous utilisez RollingFileAppender, les choses deviennent encore pires car plusieurs processus peuvent essayer de lancer le roulement du fichier journal simultanément. RollingFileAppender ignore complètement le modèle de verrouillage lors du roulement de fichiers, le roulement de fichiers n'est tout simplement pas compatible avec ce scénario.

Une meilleure alternative consiste à faire en sorte que vos processus se connectent à RemotingAppenders. À l'aide de RemoteLoggingServerPlugin (ou IRemoteLoggingSink), un processus peut recevoir tous les événements et les enregistrer dans un seul fichier journal. L'un des exemples montre comment utiliser RemoteLoggingServerPlugin.

34
Ciprian Teiosanu

Si tu as

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

et ajouter

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

alors il y aura une erreur pendant le roulement. Le premier processus créera le nouveau fichier et renommera le fichier actuel. Ensuite, le prochain processus fera de même et prendra le fichier nouvellement créé et écrasera le fichier nouvellement renommé. Il en résulte que le journal de bord du dernier jour est vide.

6
Jonte