Combining Fluent API and application Config

Topics: Logging Application Block
Jul 1, 2011 at 9:41 AM
Edited Jul 1, 2011 at 9:44 AM


I have a project where I use a centralized component that configures logging through the fluent API. In my project I want to add extra sections in the application configuration file in addition to the once created by the component. Is this possible?

Currently we use the UpdateConfigurationWithReplace in the component but this overwrites the complete logging section, so ignoring the configuration I added in the config file. I would need something like UpdateConfigurationWithMerge.

Any ideas how to solve or work around this?

Thx !



Jul 1, 2011 at 10:39 AM
Edited Jul 1, 2011 at 11:53 AM


Currently, the Fluent API doesn't have that functionality. The same functionality has been asked several times but haven't yet logged as feature request. You can log it here. As for the work around, you can retrieve the logging section first, then create a ConfigSourceBuilder then add your extra and logging section there before calling the UpdateConfigurationWithReplace.


Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.

Jul 1, 2011 at 1:29 PM


thank you for the quick reply! I will log the feature request, as I believe this is indeed a desirable feature.

As for the work around, I tried what you suggested but I run into an exception " System.ArgumentException: An item with the same key has already been added", on Builder.ConfigureLogging.

I think this is normal as I try to add two LoggingSection, but when I give my section comming from the config file a new name when adding the section, EntLib will not see it as a LoggingConfiguration.

What am I missing ?

 Dim source As IConfigurationSource = New FileConfigurationSource(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)

Dim loggingSection = source.GetSection("loggingConfiguration")
builder.AddSection(loggingSection.SectionInformation.Name, loggingSection)

'Add additional standard logging
builder.ConfigureLogging() _
       .WithOptions _
         .DoNotRevertImpersonation() _
       .LogToCategoryNamed("Heartbeat") _
         .SendTo.RollingFile("Heartbeat Log File") _
           .CleanUpArchivedFilesWhenMoreThan(5) _
           .RollEvery(Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollInterval.Midnight) _
           .FormatWith(New FormatterBuilder() _
             .TextFormatterNamed("Text Formatter") _
               .UsingTemplate("{timestamp(local:yyyy-MM-dd HH:mm:ss)} {message}")) _
               .WithHeader(String.Empty) _
               .WithFooter(String.Empty) _
             .ToFile(HeartbeatLogPath) _
        .LogToCategoryNamed("General") _
         .SendTo.FlatFile("General Log File") _
           .FormatWith(New FormatterBuilder() _
             .TextFormatterNamed("Text Formatter") _
               .UsingTemplate("{timestamp(local:yyyy-MM-dd HH:mm:ss)} {message}")) _
               .WithHeader(String.Empty) _
               .WithFooter(String.Empty) _
             .ToFile(GeneralLogPath) _
             .Filter(SourceLevels.Information) _
        .LogToCategoryNamed("Exception") _
         .SendTo.FlatFile("Exception Log File") _
           .FormatWith(New FormatterBuilder() _
             .TextFormatterNamed("Text Formatter") _
               .UsingTemplate("{timestamp(local:yyyy-MM-dd HH:mm:ss)} {message}")) _




Jul 4, 2011 at 8:14 AM

My apologies for misunderstanding but are you trying to add another logging section to your configuration? This wouldn't be possible since by design, you can only have one logging section. In your code above, you are actually trying to readd the logging section that you just retrieved. I'm not sure what are you trying to achieve but I guess you just want to reconfigure the logging section? Moving on, my suggestion is only applicable if you want to retain other configuration settings (ex: database configuration, caching configuration, etc) since calling UpdateConfigurationWithReplace will create a new configuration source.


Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.

Jul 4, 2011 at 9:39 AM


the cause of the misunderstanding was probably mine:

The code above is from a standard component I want to use in different applications. This component has some standard logging categories (heartbeat for example). In the applications that use this component there is sometimes need for extra logging categories. So what I was trying to accomplish is merge the config from the application and the standard config. I hoped that it was possible to read the Logging Configuration from the application.config of the application, add this to the EntLib Builder and afterwards adding the standard logging categories. However it appears that "ConfigureLogging" always wants to add a new logging section and doesn't check wether there is already a section and, in that case, just adds configuration.

Jul 4, 2011 at 11:06 AM

Unfortunately that's the current behavior of Fluent API. I am exploring another approach from this thread. I can't get it worked at first due to some exception with ILogFormatter. After some tweaking, I finally get it worked. I have an existing logging settings that writes to a flat file then at runtime I'll added another category pointing to a rolling flat file trace listener. Finally, I used those categories to write my message. Here is the code:

                //Create the config builder for the Fluent APIvar 
                var source = new FileConfigurationSource(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                ConfigurationSourceBuilder configBuilder = new ConfigurationSourceBuilder();

                //Get the existing logging config section                 
                var logginConfigurationSection = (LoggingSettings)source.GetSection("loggingConfiguration");

                logginConfigurationSection.RevertImpersonation = false;
                var _rollingFileListener = new RollingFlatFileTraceListenerData("Rolling Flat File Trace Listener", "rolling.log", "----------------------", "",
                                 10, "MM/dd/yyyy", RollFileExistsBehavior.Increment,
                                 RollInterval.Day, TraceOptions.Callstack | TraceOptions.DateTime | TraceOptions.LogicalOperationStack | TraceOptions.ProcessId | TraceOptions.ThreadId | TraceOptions.Timestamp,
                                 "Another Text Formatter", SourceLevels.All);

                _rollingFileListener.MaxArchivedFiles = 2;
                //Add trace listener to current config
                logginConfigurationSection.Formatters.Add(new TextFormatterData("Another Text Formatter",string.Empty));
                //Configure the category source section of config for flat file
                var _rollingFileCategorySource = new TraceSourceData("Another General", SourceLevels.All);

                //Must be named exactly the same as the flat file trace listener above.
                _rollingFileCategorySource.TraceListeners.Add(new TraceListenerReferenceData("Rolling Flat File Trace Listener"));

                //Add category source information to current config

                //Add the loggingConfiguration section to the config.
                configBuilder.AddSection("loggingConfiguration", logginConfigurationSection);

                //Required code to update the EntLib Configuration with settings set above.
                var configSource = new DictionaryConfigurationSource();

                //Set the Enterprise Library Container for the inner workings of EntLib to use when logging
                EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);

                LogWriter writer
                 = EnterpriseLibraryContainer.CreateDefaultContainer(configSource).GetInstance<LogWriter>();

                writer.Write("Test....",new string[]{"General", "Another General"});

Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.
Jul 5, 2011 at 3:50 PM

Just an update - as this code comes from code that I had started on the other thread:

You can't have a / in your string formatter (see above where there is "MM/dd/yyyy").
So for the rolling log file, you must use something other than characters that windows doesn't allow (/, :, ? etc).

Jul 6, 2011 at 6:11 AM

Thanks mainedev for pointing this out :)


Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.
Jul 6, 2011 at 12:52 PM

This worked perfectly !! Thx a lot.

I will file that request to adjust the fluent api to support this.

Thx again !