michelqa
michelqa

Reputation: 157

Enterprise librairy RollingFlatFileTraceListener unlock

We use the EnterpriseLibray to log error in our application. For some reason the log file stay locked until the pplication service is stopped.

Is there any option to leave the file unlocked when it's not in use? My goal is to create an external process (a kind of watchdog) that copy and zip the log file....but it's locked.

Any idea ?

This is what my app.config look like :

<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
    <listeners>
      <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fileName="Server.log" rollSizeKB="2024" footer="----------------------------------------" formatter="NovaLogFormatter" header="- NEW TRACE ----------------------------------------" rollFileExistsBehavior="Increment" maxArchivedFiles="20" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Culture=neutral, PublicKeyToken=31bf3856ad364e35" template="Timestamp: {timestamp(local)}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Severity: {severity}{newline}&#xA;Title: {title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;Extended Properties:{newline}{dictionary({key}{newline}{value}{newline})}" name="NovaLogFormatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </add>
      <add switchValue="All" name="Data" />
      <add switchValue="All" name="Security" />
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings" />
    </specialSources>
  </loggingConfiguration>

Upvotes: 0

Views: 195

Answers (1)

Randy Levy
Randy Levy

Reputation: 22655

The locking behavior is by design and inherited from the TraceListener base class.

There are a few options available to you:

  • Read through the lock
  • Since you are using RollingFlagFileTraceListener you could operate on archived files (which are no longer locked)
  • You could release the file lock after every write

Read Through the Lock

You can use code like this to read the contents of the file even though it's locked:

using(var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using(var sr = new StreamReader(fs))
{
    while(!sr.EndOfStream)
    {
        Console.WriteLine(sr.ReadLine());
    }
}  

This should allow the watchdog to copy the file contents but you may have to manage state so that the same log entries are not copied multiple times (if that's important to you).

Copy Archived Files

Another idea is to only zip files that have been archived by the RollingFlatFileTraceListener. These files will not be locked. However, archiving does not occur at regular intervals so this may not be a good fit.

Release Lock

Another option is to release the lock by disposing of the LogWriter after writing a LogEntry. This will work but has a performance overhead (opening and closing the file) and requires you to manage concurrency (to avoid closing the LogWriter when another thread is using it).

Bonus

I hesitate to mention it but you could write a custom trace listener that does whatever you want. Probably not a great use of time but it is an option.

Upvotes: 1

Related Questions