How to use static logger??? Logging Application Block

Topics: General discussion, Logging Application Block
Apr 30, 2013 at 3:41 PM
Edited Apr 30, 2013 at 3:45 PM
This is a question pertaining to version 6 and static logger.

In version 5.0, it's possible to just call Logger.Write(logEntry); where logEntry is a LogEntry object appropriately set. All configuration is done declaratively.

When attempting that with 6.0 an error is generated and it's not clear what to do.

The error is: The LogWriter has not been set for the Logger static class. Set it invoking the Logger.SetLogWriter method.


Logger.SetLogWriter() lo;ks to require an instantiated object.

Using Logger.SetLogWriter(Logger.Writer) doesn't work.

How can the static logger be used with entlib 6.0?
Apr 30, 2013 at 7:00 PM
Edited May 1, 2013 at 9:24 PM
The boostrapping behavior of Enterprise Library has changed in Version 6. The impact for the static Logger facade is that you need to set the internal LogWriter (for example at application start):
Logger.SetLogWriter(new LogWriterFactory().Create());
Logger.Write("test", "General");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
May 1, 2013 at 1:23 PM
Thanks that worked ... with some additional modification as described below.

There is one other issue, perhaps it's best put into a new question, but here it is ...

In our solution we have many projects/services using the logging application block and thus use redirection in the app.config files so we can have a single application configuration for the logging block. This is because when the application is running, there are numerous app.config files that will be in use at once (numerous processes).

Thus these are the specific settings as found in the app.config, which redirects to the main config (entlib.config) for enterprise library config settings:

<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="System Configuration Source">
<sources>
  <add name="System Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  <add name="File-based Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" filePath="C:\Pathtotheconfig\EntLib.config" />
</sources>
<redirectSections>
  <add sourceName="File-based Configuration Source" name="loggingConfiguration" />
  <add sourceName="File-based Configuration Source" name="exceptionHandling" />
</redirectSections>
</enterpriseLibrary.ConfigurationSource>

When the above (Logger.SetLogWriter(new LogWriterFactory().Create());) executes, the following exception is thrown:

System.InvalidOperationException was caught
HResult=-2146233079
Message=The configuration section for Logging cannot be found in the configuration source.
Source=Microsoft.Practices.EnterpriseLibrary.Logging
StackTrace:
   at Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterFactory.LogWriterConfigurationBuilder.Create()
   at Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterFactory.Create()
   at ...appspecificinfo...
InnerException:

To get around this, it's necessary to stop redirecting and put the config settings into each app.config file. I did modify the Version from 5.0.505.0 to 6.0.0.0 in the redirect settings as well as the entlib.config settings when generating the exception.

So the question is, "Does config file redirection still work with entlib 6?" If so, what's needed to be changed to make it work (using the above settings as the baseline whi8ch provides logging and exception handling settings redirect to a single source for these settings)?
May 1, 2013 at 7:36 PM
Edited May 1, 2013 at 9:24 PM
It looks like new LogWriterFactory() will default to use System.Configuration directly to attempt to get the config section.

One way to ensure that you hook into the Enterprise Library configuration is to use ConfigurationSourceFactory:
IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
Logger.SetLogWriter(logWriterFactory.Create());
            
Logger.Write("test", "General");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
May 7, 2013 at 10:54 AM
I have tried this, I still get the following error:

Database provider factory not set for the static DatabaseFactory. Set a provider factory invoking the DatabaseFactory.SetProviderFactory method or by specifying custom mappings by calling the DatabaseFactory.SetDatabases method.
May 7, 2013 at 4:12 PM
If you are using Database then you will need to set the database factory. For example:
DatabaseFactory.SetDatabaseProviderFactory(new DatabaseProviderFactory());
See this question/answer for a full example for logging to a database: http://entlib.codeplex.com/discussions/442387 .

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
May 8, 2013 at 4:02 PM
randylevy wrote:
It looks like new LogWriterFactory() will default to use System.Configuration directly to attempt to get the config section.

One way to ensure that you hook into the Enterprise Library configuration is to use ConfigurationSourceFactory:
IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
Logger.SetLogWriter(logWriterFactory.Create());
            
Logger.Write("test", "General");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
This worked. Thanks.
May 10, 2013 at 5:58 PM
To get this working for exception handling required a similar pattern:
            var exceptionHandlerFactory = new ExceptionPolicyFactory(configurationSource);
            ExceptionPolicy.SetExceptionManager(exceptionHandlerFactory.CreateManager());

The exceptionHandlerFactory also has a create policy call, but not sure what it's used for. Searched the API for where to use it, and searched the documentation for how to use it and found nothing. But our code is working without it and exceptions are being handled.
            exceptionHandlerFactory.CreatePolicy("PolicyName");
Jul 23, 2013 at 6:40 PM
__Entlib 6.0 Custom Configuration Source is not working
__
Please see below issue detail-

I downloaded Entlib 6.0 from codeplex.com and created custom configuration source as Entlib.config and referred as a source in App.Config. And called the C# code to write logging. I got the below error message.

Error Message: "The configuration section for Logging cannot be found in the configuration source."

I. App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="fileSource"
parentSource="fileSource">
<sources>
  <add name="fileSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    filePath="C:\App_Data\Entlib.config" />
</sources>
<redirectSections>
  <add sourceName="fileSource" name="loggingConfiguration" />
</redirectSections>
</enterpriseLibrary.ConfigurationSource>
<startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

II. Entlib.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
<listeners>
  <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    source="Enterprise Library Logging" formatter="Text Formatter"
    log="Client" machineName="." traceOutputOptions="None" />
  <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    fileName="rolling.log" formatter="Text Formatter"
    rollInterval="Day" />
</listeners>
<formatters>
  <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
    name="Text Formatter" />
</formatters>
<categorySources>
  <add switchValue="All" name="General">
    <listeners>
      <add name="Event Log Listener" />
    </listeners>
  </add>
</categorySources>
<specialSources>
  <allEvents switchValue="All" name="All Events">
    <listeners>
      <add name="Event Log Listener" />
      <add name="Rolling Flat File Trace Listener" />
    </listeners>
  </allEvents>
  <notProcessed switchValue="All" name="Unprocessed Category" />
  <errors switchValue="All" name="Logging Errors &amp; Warnings">
    <listeners>
      <add name="Event Log Listener" />
    </listeners>
  </errors>
</specialSources>
</loggingConfiguration>
</configuration>

III. C# code on button event.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void btnLogging_Click(object sender, EventArgs e)
    {
        WriteLogEvent("Important", 1, "btnLogging_Click",TraceEventType.Information, 23);
    }

    public static string WriteLogEvent(string Category, int EventID, string Message, TraceEventType Severity, int Priority)
    {
        LogEntry LogEntry = null;
        string StatusMessage = string.Empty;
        try
        {
            IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
            LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
            LogEntry = new LogEntry();
            LogEntry.Categories.Add(Category);
            LogEntry.EventId = EventID;
            LogEntry.Message = Message;
            LogEntry.TimeStamp = DateTime.Now;
            LogEntry.Severity = Severity;
            LogEntry.Priority = Priority;
            LogEntry.GetProcessName();
            LogEntry.Title = "SmartClient Test Log";


           Logger.SetLogWriter(new LogWriterFactory().Create());

                Logger.Write(LogEntry);
                StatusMessage = "Successful";


        }
        catch (Exception ex)
        {

        }
        return null;
    }
}
Could you please provide help to resolve the issue.
Jul 24, 2013 at 12:19 PM
Solution by Randy is....

You need to use the LogWriterFactory that you initialized with the Enterprise Library configuration information and not a new default instance:
        IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
        LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
        Logger.SetLogWriter(logWriterFactory.Create()); // not new LogWriterFactory().Create();

Marked as answer by randylevy on 10/7/2013 at 11:08 PM
Feb 17 at 4:25 AM
Hi All,

I am using Ent Lib 6 for logging and got the error: "The LogWriter has not been set for the Logger static class. Set it invoking the Logger.SetLogWriter method.". To fix this, added below code:
IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
Logger.SetLogWriter(logWriterFactory.Create()); // not new LogWriterFactory().Create();
But, now i get a different error: "Must be implemented by subclasses."
Any idea what needs to be done to fix this?

Thanks,
Sai Abhilash Manikonda
Apr 18 at 1:36 PM
Sai,

I too got the same error. How did you resolve this one?
Apr 18 at 1:46 PM
It sounds like you probably have a custom TraceListener or Formatter that is not overriding the CoreBuildTraceListener or BuildFormatter methods respectively (could also be a LogFilter but that seems less likely). Can you post your configuration?