Tuesday, 18 December 2012

Updating Enterprise Logging Block config dynamically

We have a ClickOnce application that is using the Microsoft Enterprise Logging Block, its fairly easy to set up the blog from XML in the app.config, however we wanted out log path to be dynamic so that we could change it at runtime.

Here is our sample app.config.

  <!-- =================================== -->  
  <!-- logging configuration        -->  
  <!-- =================================== -->  
  <exceptionHandling>  
   <exceptionPolicies>  
    <add name="LoggingPolicy">  
     <exceptionTypes>  
      <add name="All Exceptions" type="System.Exception" postHandlingAction="ThrowNewException">  
       <exceptionHandlers>  
        <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging"  
         logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling"  
         formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"  
         priority="0" />  
       </exceptionHandlers>  
      </add>  
     </exceptionTypes>  
    </add>  
   </exceptionPolicies>  
  </exceptionHandling>  
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"  
   logWarningsWhenNoCategoriesMatch="false">  
   <listeners>  
 <!--  
    <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"  
     listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"  
     fileName="./Logs/Client.log" footer="" formatter="Text Formatter"  
     header="" rollSizeKB="20000" />  
 -->      
    <add name="XML Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.XmlTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"  
     listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.XmlTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"  
     fileName="trace-xml.log" traceOutputOptions="None" filter="Verbose" />  
    <add name="Event Log Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"  
     listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"  
     source="Application Error" formatter="Text Formatter" log="Application" filter="Information" />  
   </listeners>  
   <formatters>  
    <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"  
     template="{timestamp(local)} : {severity} : {keyvalue(namespace)} :{message}&#xA;"  
     name="Text Formatter" />  
   </formatters>  
   <categorySources>  
    <add switchValue="information" name="General">  
     <listeners>  
 <!--     <add name="Rolling Flat File Trace Listener" />-->  
      <add name="Event Log Trace Listener" />  
     </listeners>  
    </add>  
   </categorySources>  
   <specialSources>  
    <allEvents switchValue="All" name="All Events" />  
    <notProcessed switchValue=
"All" name="Unprocessed Category">  
     <listeners>  
      <add name="Rolling Flat File Trace Listener" />  
     </listeners>  
    </notProcessed>  
    <errors switchValue="Verbose" name="Logging Errors &amp; Warnings">  
     <listeners>  
      <add name="Rolling Flat File Trace Listener" />  
      <add name="Event Log Trace Listener" />  
     </listeners>  
    </errors>  
   </specialSources>  
  </loggingConfiguration>  

We can then dynamically update the config to add out new path :-

     private static DictionaryConfigurationSource ConfigureLoggingLocationForClickOnce()  
     {  
       string logFileName = @".\Logs\Client.log";  
       if (ApplicationDeployment.IsNetworkDeployed)  
       {  
         logFileName = ApplicationDeployment.CurrentDeployment.DataDirectory + @"\Logs\Client.log";  
       }  
   
       //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", logFileName, "", "",  
                20000, "MM/dd/yyyy", RollFileExistsBehavior.Increment,  
                RollInterval.Day, TraceOptions.Callstack | TraceOptions.None,  
                "Text Formatter", SourceLevels.Information);  
   
   
       _rollingFileListener.MaxArchivedFiles = 1;  
   
       //Add trace listener to current config  
       logginConfigurationSection.TraceListeners.Add(_rollingFileListener);  
   
       //Configure the category source section of config for rolling file  
       var _rollingFileCategorySource = logginConfigurationSection.TraceSources.Get("General");  
   
       //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  
       logginConfigurationSection.TraceSources.Add(_rollingFileCategorySource);  
   
       //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();  
       configBuilder.UpdateConfigurationWithReplace(configSource);  
   
       //Set the Enterprise Library Container for the inner workings of EntLib to use when logging  
       EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);  
   
       return configSource;  
     }  
   

Finally if using Unity and Prism you can setup both loggers like so:-


       this.Container.AddNewExtension<EnterpriseLibraryCoreExtension>();  
   
       var configurator = new UnityContainerConfigurator(Container);  
       // Read the configuration files and set up the container.  
       var configSource = ConfigureLoggingLocationForClickOnce();  
       EnterpriseLibraryContainer.ConfigureContainer(configurator, configSource);  
   
       // Set up logging with both IOC containers...  
       var oldLogger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();  
       if (oldLogger != null)  
         oldLogger.Dispose();  
         
       var newLogger = Container.Resolve<LogWriter>();  
       EnterpriseLibraryContainer.Current = ServiceLocator.Current;  
   
   
       this.Container.RegisterType<ILoggerFacade, LoggingService>(new ContainerControlledLifetimeManager());  
       LoggingService logger = (LoggingService)this.Container.Resolve<ILoggerFacade>();  
       this.Container.RegisterInstance<ILoggingService>(logger, new ContainerControlledLifetimeManager());  
       this.Container.AddNewExtension<EnterpriseLibraryCoreExtension>();  
   

No comments:

Post a Comment