Moving data from log file to database when connected

Topics: Logging Application Block
Feb 12, 2013 at 6:24 PM
I have a WPF client/server application that uses a rolling flat file trace listener. Currently the log files are saved on each client machine. The application isn't always connected to the database when it's in use. So, when there is connection, I'd like to read the log file, save the data to the database and then clear the log file. The problem is that the log file is 'in use' while the application is running. Can anyone offer any guidance on the best approach to accomplish this.
Feb 13, 2013 at 9:30 PM
Edited May 1, 2013 at 9:50 PM
To read the log file while it is locked see Reading from log files for an example.

However, since the file is locked you won't be able to save changes to the file or delete the file. The solution to this would be to Dispose the LogWriter to release the locks.

In this example, I read the file name from configuration, write a message, read the file, clear the file, and then start writing to the file again.
// Get LogWriter
var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();

// Write a message
logWriter.Write("test", "General");

// Get fileName -- assuming that there is only one flat file trace listener defined
IConfigurationSource configSource = ConfigurationSourceFactory.Create();
var logSettings = configSource.GetSection(LoggingSettings.SectionName) as LoggingSettings;

var listenerData = logSettings.TraceListeners
    .Where(t => t is FlatFileTraceListenerData)
    .Cast<FlatFileTraceListenerData>().Single();

string fileName = listenerData.FileName;

// Read through lock if you wish -- this could also be done after releasing the lock
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var sr = new StreamReader(fs))
{
    while (!sr.EndOfStream)
    {
        // Write out data or transfer somewhere else (e.g. database)
        Console.WriteLine(sr.ReadLine());
    }
}

// Release Lock -- could now read the file as well
logWriter.Dispose();

// "Clear" file
File.Delete(fileName);

// Get new LogWriter instance
logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();

// Start logging new messages
logWriter.Write("test again!!", "General");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Feb 15, 2013 at 4:46 AM
Thanks Randy. I think this will work. Instead of the LogWriter class I'm using Logger instead which doesn't implement IDisposable. Is there any way to release the locks on Logger?
Feb 15, 2013 at 4:57 AM
Edited May 1, 2013 at 9:50 PM
Sure, you can use the Logger facade. The Logger class exposes the Writer property which does implement IDisposable. If you were using the Logger facade the code would look like this:
// Write a message
Logger.Write("test", "General");

// Get fileName -- assuming that there is only one flat file trace listener defined
IConfigurationSource configSource = ConfigurationSourceFactory.Create();
var logSettings = configSource.GetSection(LoggingSettings.SectionName) as LoggingSettings;

var listenerData = logSettings.TraceListeners
    .Where(t => t is FlatFileTraceListenerData)
    .Cast<FlatFileTraceListenerData>().Single();

string fileName = listenerData.FileName;

// Read through lock if you wish -- this could also be done after releasing the lock
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var sr = new StreamReader(fs))
{
    while (!sr.EndOfStream)
    {
        // Write out data or transfer somewhere else (e.g. database)
        Console.WriteLine(sr.ReadLine());
    }
}

// Release Lock -- could now read the file as well
Logger.Writer.Dispose();

// "Clear" file
File.Delete(fileName);

// Start logging new messages
Logger.Write("test again!!", "General");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Feb 15, 2013 at 12:02 PM
Works great Randy. Thanks again.