Programmatically access Enterprise Library Logging

2019-04-12 00:56发布

问题:

I'm using Enterprise Library 3.1 and want to programmatically access the Logging Block (runtime, object model) specifically its Trace Listeners and Sources.

For example, I want to access the Filename property of a trace listener object so I can know where the log file is located on disk.

Update: Looking for answers that use the runtime object model, not by parsing the XML configuration.

回答1:

You can access the logging configuration programmatically using the object model (used for configuration).

To get the specific data for the trace listener you should look at TraceListenerData (and the specific subclasses).

This example shows how to read in the configuration and then get the TraceListeners:

// Open config file
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = @"MyApp.exe.config";

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

// Get EL log settings
LoggingSettings log = config.GetSection("loggingConfiguration") as LoggingSettings;

// Get TraceListener info
foreach(TraceListenerData listener in log.TraceListeners)
{
    // Check for listener types you care about
    if (listener is RollingFlatFileTraceListenerData)
    {
        RollingFlatFileTraceListenerData data = listener as RollingFlatFileTraceListenerData;
        Console.WriteLine(string.Format("Found RollingFlatFileLIstener with Name={0}, FileName={1}, Header={2}, Footer={3}, RollSizeKB={4}, TimeStampPattern={5},RollFileExistsBehavior={6}, RollInterval={7}, TraceOutputOptions={8}, Formatter={9}, Filter={10}",
            data.Name, data.FileName, data.Header, data.Footer, data.RollSizeKB, 
            data.TimeStampPattern, data.RollFileExistsBehavior, data.RollInterval,
            data.TraceOutputOptions, data.Formatter, data.Filter);
    }
    else // other trace listener types e.g. FlatFileTraceListenerData 
    {
    }
}


回答2:

Apparently some needed info is privately encapsulated in a LogWriterStructureHolder instance (its field is named structureHolder) on the Enterprise Library Logger.Writer instance (of Type LogWriter).
So I'm effectively looking for: Logger.Writer.structureHolder (but that field is private).

I used reflection to pull it out....

These are the significant namespaces:

using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Logging;

This is reflection code to pull out the needed private data:

// Get the private field.
FieldInfo fiLogStructHolder 
    = typeof(LogWriter).GetField("structureHolder", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);

// Obtain field value to get the private data.
LogWriterStructureHolder structureHolder 
    = (LogWriterStructureHolder)fiLogStructHolder.GetValue(Logger.Writer);

// Access the value's .TraceSources property of Type Dictionary<string, LogSource>.
// The string is the name of the category from configuration. 
int numSources = structureHolder.TraceSources.Count;

// Furthermore, access the listeners of any logging source by specifying:
int numListeners = structureHolder.TraceSources[0].Listeners.Count
                                             // ^-- Note: Picked first source for example.

If anybody can find a non-private entry point for this same data please post it in an answer. Thanks.

Kudos to .NET Reflector for facilitating this answer.



回答3:

public static EmailTraceListenerData GetEmailLogConfiguration()
{
    var rootWebConfig1 = WebConfigurationManager.OpenWebConfiguration("/");
    var section = rootWebConfig1.GetSection("loggingConfiguration");
    var loggingSection = section as Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings;

    if (loggingSection != null) {
        // Reference to Microsoft.Practices.EnterpriseLibrary.Logging.dll and
        // Microsoft.Practices.EnterpriseLibrary.Common.dll required for the code below
        foreach (Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.TraceListenerData listener in loggingSection.TraceListeners) {
            var emailTraceListenerData = listener as EmailTraceListenerData;
            if (emailTraceListenerData != null) {
                // Can obtain FromAddress, ToAddress, SmtpServer and SmtpPort 
                // as property of  emailTraceListenerData;
                return emailTraceListenerData;
            }
        }
    }
    return null;
}

Web.config file is as follow:

For Windows application, you can open the .config file withSystem.Configuration.ConfigurationManager.OpenExeConfigurationinstead of WebConfigurationManager.



回答4:

The other answers seem very verbose, here is my solution:

    public static TraceListenerData GetTraceListener(string name)
    {
        var log = ConfigurationManager.GetSection("loggingConfiguration") as LoggingSettings;

        return log.TraceListeners.Single(tl => tl.Name == name);
    }

Once you've called this helper method you can cast the result to whatever type the listener is such as RollingFlatFileTraceListenerData, EmailTraceListenerData, FormattedEventLogTraceListenerData, FormattedDatabaseTraceListenerData