web-dev-qa-db-ja.com

断続的なlog4net RollingFileAppenderロックファイルの問題

開発マシンと本番マシンで断続的に問題が発生し、ログファイルにログが記録されません。

Visual Studioを使用して開発およびデバッグを実行すると、VS出力ウィンドウに次のlog4netエラーメッセージが表示されます。

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

プロセスは別のプロセスで使用されているため、ファイル 'C:\ folder\file.log'にアクセスできません。

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.

構成セクションは次のようになります。

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

この問題に対する現在の回避策は、最後のログファイルの名前を変更することです。もちろん、これは(前述のファイルロックのために)失敗すると予想されますが、通常は失敗しません。からのロックが原因で、名前の変更が1回または2回失敗しました aspnet_wp.exe プロセス。

Log4net構成セクションを以下に示します。

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

前述のように、これはマシン上で断続的に見られますが、問題が発生すると解決しません。

108
Richard Everett

追加してみてください

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

あなたの<appender />要素。これは、log4netがファイルをロックし、書き込みを行い、書き込み操作ごとにロックを解除することを意味するため、パフォーマンスへの影響があります(デフォルトの動作ではなく、長時間ロックを取得して保持します)。

デフォルトの動作の1つの意味は、同じマシンで実行されている複数のワーカープロセスで実行されているWebサイトで使用している場合、それぞれがそのロックを無期限に取得して保持しようとすることです。失うだけです。ロックモデルを最小ロックに変更すると、この問題を回避できます。

(デバッグ時、不当な終了と多くの新しいワーカープロセスの起動は、まさに起こりそうなタイプです。)

がんばろう!

160

log4net FAQ にも注意してください:

同じファイルに複数のプロセスを記録するにはどうすればよいですか?

提供されている代替手段のいずれかを試してみる前に、同じファイルに複数のプロセスのログを記録する必要があるかどうかを自問してください。そうしないでください;-)。

FileAppenderは、このユースケースにプラグ可能なロックモデルを提供しますが、既存の実装にはすべて問題と欠点があります。

デフォルトでは、FileAppenderはログファイルのロギング中に排他的な書き込みロックを保持します。これにより、他のプロセスがファイルに書き込むことができなくなります。このモデルは、Linux上のMono(少なくとも一部のバージョン)で故障することが知られており、別のプロセスがログファイルにアクセスしようとするとすぐにログファイルが破損する可能性があります。

MinimalLockは、ログの書き込み中にのみ書き込みロックを取得します。 これにより、パフォーマンスは大幅に低下しますが、複数のプロセスが同じファイルへの書き込みをインターリーブできます。

InterProcessLockはファイルをまったくロックしませんが、システム全体のMutexを使用して同期します。これは、すべてのプロセスが連携する(および同じロックモデルを使用する)場合にのみ機能します。書き込まれるログエントリごとにミューテックスを取得してリリースするとパフォーマンスが低下しますが、ミューテックスはMinimalLockを使用するよりも適切です。

RollingFileAppenderを使用すると、いくつかのプロセスが同時にログファイルのロールを開始しようとするため、事態はさらに悪化します。 RollingFileAppenderは、ファイルをローリングするときにロックモデルを完全に無視します。ローリングファイルはこのシナリオと互換性がありません。

より良い代替方法は、プロセスをRemotingAppendersに記録させることです。 RemoteLoggingServerPlugin(またはIRemoteLoggingSink)を使用して、プロセスはすべてのイベントを受信し、それらを単一のログファイルに記録できます。例の1つは、RemoteLoggingServerPluginの使用方法を示しています。

34

あなたが持っている場合

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

そして追加

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

ローリング中にエラーが発生します。最初のプロセスで新しいファイルが作成され、現在のファイルの名前が変更されます。次に、次のプロセスが同じことを行い、新しく作成されたファイルを取得し、新しく名前が変更されたファイルを上書きします。最終日のログフィールドが空になります。

6
Jonte