How To Programmatically Obtain The FormattedTraceListenerBase Specific Listener Reference Type For A Logging Category And Exception Policy In Enterprise Library 5.0

Topics: Exception Handling Application Block, Logging Application Block
Aug 20, 2012 at 6:45 PM

Using the classes or reference type in the Microsoft Enterprise Library 5.0, is it programmatically possible to obtain the specific Reference Type or class for a Logging Target Listener Type Name used by a Logging Setting Category and the Exception Handling Policy?

For example, if I have a Logging Setting Category named "My FlatFile Logging", and the underlying specific Trace Listener subclass of FormattedTraceListenerBase for this Logging Category is FlatFileTraceListener, how can I get the actual type programmatically for "My FlatFile Logging" Logging Category Setting?  Likewise, how can I obtain the same Trace Listener subclass of FormattedTraceListenerBase in the same Logging Category Setting if the Category Setting is used explicitly by a given Exception Handling Policy as defined in the app.config file?  (e.g., the "My FlatFile Exception Policy" in the Exception Handling Application Block through the "My Flat File Exception Handler" uses the same Logging Category, "My FlatFile Logging" as defined in the Logging Settings application block).

Am I correct in thinking that this is achievable using the classes or reference types, methods, and interfaces defined in the Microsoft.Practices.EnterpriseLibrary.Common, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, and Microsoft.Practices.EnterpriseLibrary.Logging, and their related and required namespaces?  

As an alternative to writing my own utility classes that perform LINQ To XML Queries against the XML Nodes defined in the app.config file, I would think there should be, considering that a later version or release the Enterprise Library classes may internally use a different hierarchical application block and configuration access approach or syntax other than XML, such as JSON.  With this in mind, I would consider writing my own code to parse the app.config file a kin to re-inventing the wheel, which I have a  strong aversion to doing since in this case, I would think Microsoft would already have a rounder and more smoothly rollable wheel already inside the Enterprise Library framework.

Thank you in advance for your time and help, and I look forward to hearing from you soon.

Best Regards...

Aug 21, 2012 at 2:22 AM

You should be able to do what you want using the configuration classes.  Just be aware that they are not designed for querying the configuration but for representing the configuration so it can be a bit circuitous to arrive at the desired result.

So to get the trace listener configuration for the FlatFileTraceListener that is defined under a category called "My FlatFile Logging" you could use something like the following:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = @"app.exe.config";

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

LoggingSettings log = config.GetSection(LoggingSettings.SectionName) as LoggingSettings;

var traceSource = log.TraceSources.First(tsd => 
    string.Compare(tsd.Name, "My FlatFile Logging", StringComparison.Ordinal) == 0);

var traceListenerNames = traceSource.TraceListeners.Select(ts => ts.Name);
var targetTraceListener = log.TraceListeners.First(tl => 
    tl.Type == typeof(FlatFileTraceListener) && traceListenerNames.Contains(tl.Name));

The above assumes that there is only one (or that you are after the first).

For Exception Handling I think you could do something similar.  

That gets you the XML configuration information represented in an object model   My question is: why do you want that information?  Are you trying to manipulate the runtime behavior of the blocks?  If so, I'm not sure that is a good approach.

Randy Levy
Enterprise Library support engineer 

Aug 21, 2012 at 6:16 PM
Edited Aug 21, 2012 at 6:16 PM


Thank you very much for the quick follow-up.  I really appreciate your help and efforts.

In answer to your question as why do I want know the type of listener used for a given Logging Category Setting and / or Exception Policy definition, I am trying to find the best way to support the following behavior:

  • If an Exception of any type is caught by our application, by default, always log the Exception first to the SQL Server database tables as defined in the SQL Server Exception Logging Policy. (Note: The Log and Category database tables are on the same SQL Server instance in the same database which our application is using).
  • If the Exception logged to the SQL Server database is an instance of or a subclass of System.Data.DataException, log the exception to the additional Exception Logging Policies as defined in the app.config file Exception Logging Block, such as the EventViewer or FlatFile logging file.

  • Once an instance of or a subclass of System.Data.DataException has been caught and logged, for the life of the application process, log all Exceptions to the same Exception Logging Policies regardless of the Exception reference type.

Essentially, I'm looking to implement a "fail-over" policy for logging exceptions; All exceptions, regardless of type should be logged to the appropriate SQL Server database table, and once a single instance of or subclass of System.Data.DataException has been caught and logged, still log that exception and all subsequent Exceptions to the SQL Server database, and log the Exceptions to the other Exception Logging stores as defined in each Exception Logging Policy.
Please accept my apologies if I overlooked implementing this behavior correctly in my app.config file.  If this can be done through app.config definitions with little or no source code whatsoever, that would be ideal.

Again, my sincerest thanks for your time, help and patience.

Best Regards...

Aug 22, 2012 at 3:48 AM

Interesting question.  I'll try to explain my approach and hopefully it aligns with what you are thinking.

I don't think you can do this out of the box so there is going to be some custom code.

First, I would create two Logging Categories: Primary and Failover.  The Primary category would have a Database Trace Listener while the Failover category would have the Event Log Trace Listener and/or Flat File Trace Listener etc.

Then I would implement a custom IExceptionHandler to handle the custom logging requirements.  Inside the handler add the first category (Primary) and if the type matches type X then also add the second Failover category.  And also maintain state so you know whether or not you always want to add the Failover category.  The categories and type could be config driven so that it's fairly configurable.

Randy Levy
Enterprise Library support engineer