Consecuitive logging with Microsoft Enterprise Library LogWriter

Topics: Building and extending application blocks, Logging Application Block
Dec 17, 2013 at 5:33 PM
Hi, I have asked the same question in stackowerflow also.

I have a C# .NET application using Enterprise Library 6.0 for logging. I have declared one trace listener for database logging and another trace listener for flat file logging. And prepared them for handling same log category "General".

In my application when i call LogWriter.Write("Test Log", "General"); everything is fine i see the "Test Log" in database and flat file as well.

But if one of them fails; For example when i call LogWriter.Write("Test Log", "General"); assume that the database is inaccessible. I expect from LogWriter just write the data into flat file.

Unfortunately i don't see any log written both in flat file and database. Is it usual? And is it possible to configure logging mechanism for consecutive logging? ( like if one of trace listeners fails continue with next trace listener)

Thanks :)

Here is my logging configuration:
public static LoggingConfiguration BuildConfig()
    string baseFilePath = @"C:\LogDirectory";
    DatabaseProviderFactory factory = new DatabaseProviderFactory(new SystemConfigurationSource(false).GetSection);
    DatabaseFactory.SetDatabaseProviderFactory(factory, false);

    // Formatters
    TextFormatter briefFormatter = new TextFormatter("Timestamp: {timestamp(local)}{newline}Message: {message}{newline}Category: {category}{newline}Priority: {priority}{newline}EventId: {eventid}{newline}ActivityId: {property(ActivityId)}{newline}Severity: {severity}{newline}Title:{title}{newline}");
    TextFormatter extendedFormatter = new TextFormatter("Timestamp: {timestamp}{newline}Message: {message}{newline}Category: {category}{newline}Priority: {priority}{newline}EventId: {eventid}{newline}Severity: {severity}{newline}Title: {title}{newline}Activity ID: {property(ActivityId)}{newline}Machine: {localMachine}{newline}App Domain: {localAppDomain}{newline}ProcessId: {localProcessId}{newline}Process Name: {localProcessName}{newline}Thread Name: {threadName}{newline}Win32 ThreadId:{win32ThreadId}{newline}Extended Properties: {dictionary({key} - {value}{newline})}");

    var databaseTraceListener = new FormattedDatabaseTraceListener(DatabaseFactory.CreateDatabase("DefaultDB"), "WriteLog", "AddCategory", extendedFormatter);
    var flatFileTraceListener = new FlatFileTraceListener(baseFilePath + @"\FlatFile.log", "----------------------------------------", "----------------------------------------", briefFormatter);

    LoggingConfiguration config = new LoggingConfiguration();

    //Log Sources

    //Match Trace Listeners For Log Sources

    return config;
Here is where i do logging in my app:
   public void DoSampleLogging()
        LogWriter defaultWriter;
        LoggingConfiguration loggingConfiguration;

        loggingConfiguration = LoggingHelper.BuildConfig();
        defaultWriter = new LogWriter(loggingConfiguration);

        defaultWriter.Write("Test Log", "General");
Dec 18, 2013 at 3:44 AM
The behavior you are describing is the way that the block currently functions. There is a work item for this: When trace listener fails further trace listeners are not processed in category.

One workaround to this would be to configure each trace listener to run asynchronously. When running asynchronously each trace listener in a category (LogSource) will be executed independently. Of course, the downside of the async approach is that it's easier to lose LogEntry's (e.g. buffer overflow, application shutdown).

Randy Levy
Enterprise Library support engineer
Support How-to
Dec 19, 2013 at 5:19 AM
Edited Dec 19, 2013 at 5:42 AM
Thank you very much Randy,
it is a weird case to search through internet :)
Using asynchronous approach will not be best practice in my project.

As another workaround i will create separate log categories for each log source like below:
    //Log Sources

    //Match Trace Listeners For Log Sources
and when i need logging i will call LogWriter.Write for each log source as below:
defaultWriter.Write("Test Log", "Database");
defaultWriter.Write("Test Log", "FlatFile");
So do you have any comment about this approach ?

Dec 27, 2013 at 5:14 AM
The approach you posted should work.

Instead of making two calls to Write you could create a LogEntry with both categories added and then make one call to Write. Either way you would probably want to centralize that code (either multiple writes or creation of the LogEntry) in a helper method.

Randy Levy
Enterprise Library support engineer
Support How-to