Logging using MSMQ Distributor

Topics: General discussion, Logging Application Block
Jan 28, 2010 at 8:13 PM

Hello, I am attemping to use the Logging Application Block to log messages to a flat line file using MSMQ. My code is as simple as this:

Logger.Write("Test", "General", 3, 1, TraceEventType.Error);

 

My app.config file looks like the following:

<configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
  </configSections>
 
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true" defaultCategory="General" logWarningsWhenNoCategoriesMatch="false">
    <listeners>
      <add fileName="C:\trace.log"
           header="----------------header------------------------"
           footer="----------------footer------------------------"
           formatter="Text Formatter"
           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
           traceOutputOptions="None"
           filter="All"
           type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
           name="Flat File Destination" />
      <add name="Msmq TraceListener"
           type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.MsmqTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.MsmqTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
           traceOutputOptions="None"
           filter="All"
           queuePath=".\Private$\MSMQTest"
           formatter="Text Formatter"
           messagePriority="Normal"
           timeToReachQueue="49710.06:28:15"
           timeToBeReceived="49710.06:28:15"
           recoverable="false"
           useAuthentication="false"
           useDeadLetterQueue="false"
           useEncryption="false"
           transactionType="None" />
    </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}
Message: {message}
Category: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title:{title}
Machine: {machine}
Application Domain: {appDomain}
Process Id: {processId}
Process Name: {processName}
Win32 Thread Id: {win32ThreadId}
Thread Name: {threadName}
Extended Properties: {dictionary({key} - {value}
)}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        name="Text Formatter" />
    </formatters>
    <logFilters>
      <add
                name="Category"
                type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
                categoryFilterMode="AllowAllExceptDenied">
        <categoryFilters>
          <add name="UI Events" />
        </categoryFilters>
      </add>
      <add
                name="Priority"
                type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.PriorityFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
                minimumPriority="2" />
      <add name="LogEnabled Filter"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
        enabled="true" />
    </logFilters>
    <categorySources>
      <add switchValue="All" name="Debug">
        <listeners>
          <add name="Msmq TraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="General">
        <listeners>
          <!--<add name="Flat File Destination" />-->
          <add name="Msmq TraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="Trace">
        <listeners>
          <add name="Flat File Destination" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <errors name="errors" switchValue="All">
        <listeners>
          <add name="Flat File Destination" />
          <!--<add name="Msmq TraceListener" />-->
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>

 

I went into MSMQ via Control Panel -> Administrative Tools -> Computer Management -> Services and Applications -> Message Queuing

Under Private Queues, I created a new MSMQ called MSMQTest and gave my user full permissions and selected the Authenticated checkbox.

I then edited my MSMQDistributor.exe.config file to look like the following:

<configuration>
  <configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null" />
    <section name="msmqDistributorSettings" type="Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.Configuration.MsmqDistributorSettings, MsmqDistributor" />
  </configSections>
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add fileName="C:\trace.log" header="----------------------------------------"
        footer="----------------------------------------" formatter="Text Formatter"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
        traceOutputOptions="Timestamp" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
        name="FlatFile TraceListener" />
    </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}{newline}Message: {message}{newline}Category: {category}{newline}Priority: {priority}{newline}EventId: {eventid}{newline}Severity: {severity}{newline}Title:{title}{newline}Machine: {machine}{newline}App Domain: {appDomain}{newline}ProcessId: {processId}{newline}Process Name: {processName}{newline}Thread Name: {threadName}{newline}Win32 ThreadId:{win32ThreadId}{newline}Extended Properties: {dictionary({key} - {value}{newline})}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="FlatFile TraceListener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="FlatFile TraceListener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <msmqDistributorSettings msmqPath=".\Private$\MSMQTest" queueTimerInterval="1000" serviceName="Enterprise Library Distributor Service" />
</configuration>

 

I ran the following via command prompt: installutil -i MSMQDistributor.exe and input the same user information as the user I gave permissions for when setting up the MSMQ private queue.

When I had finished, I ran my utility, but the trace.log file was not created with my log. I checked my private MSMQ and there was no queued messages existing. I validated my service is running under Services.

I am wondering what I am missing to get my private MSMQ to write to my file? Thanks in advance for any assistance.

Jan 28, 2010 at 9:24 PM

I modified my MSMQ and unchecked the 'Authenticated' checkbox and now my messages are showing in my MSMQ queue, but not being written to my flat line file. Here is an updated copy of my MSMQDistributor.exe.config:

<configuration>
  <configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
    <section name="msmqDistributorSettings" type="Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.Configuration.MsmqDistributorSettings, MsmqDistributor" />
  </configSections>
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true" defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add fileName="C:\trace.log"
           header="----------------header------------------------"
           footer="----------------footer------------------------"
           formatter="Text Formatter"
           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
           traceOutputOptions="None"
           filter="All"
           type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
           name="Flat File Destination" />
    </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}
Message: {message}
Category: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title:{title}
Machine: {machine}
Application Domain: {appDomain}
Process Id: {processId}
Process Name: {processName}
Win32 Thread Id: {win32ThreadId}
Thread Name: {threadName}
Extended Properties: {dictionary({key} - {value}
)}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="Debug">
        <listeners>
          <add name="Flat File Destination" />
        </listeners>
      </add>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Flat File Destination" />
        </listeners>
      </add>
      <add switchValue="All" name="Trace">
        <listeners>
          <add name="Flat File Destination" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <errors name="errors" switchValue="All">
        <listeners>
          <add name="Flat File Destination" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <msmqDistributorSettings msmqPath=".\Private$\MSMQTest" queueTimerInterval="1000" serviceName="Enterprise Library Distributor Service" />
</configuration>

 

I am still confused as to why when I log to a flat line file directly and not through MSMQ it works, but when I use the MSMQ distributor, it does not log the messages.

Jan 28, 2010 at 9:58 PM

It looks like the MSMQ Distributor service keeps stopping. I presume I am missing something in my config or my MSMQ setup. I am fairly new to MSMQ.

 

Jan 29, 2010 at 12:49 AM

Did you copy EntLib's Common, Logging, and ObjectBuilder2 assemblies to where your msmqdistributor.exe.config is?  One more thing, to know why the distributor service keeps stopping, modify your msmq config and replace your flat file trace listener with a formattedeventlog trace listener under the "errors" source.  Start the service and if it stopped, check the event viewer for the error message.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jan 29, 2010 at 1:11 PM

Hey Sarah,

Thanks for the tip. I did not have to create a custom Formatted Event Log Trace Listener since the MSMQ Distributor was an installed windows service, it was writing the events to the Administrative Events section of the Event Viewer. I did see this error showing up for the service:

 

Exception Information Details:
======================================
Exception Type: Microsoft.Practices.EnterpriseLibrary.Logging.LoggingException
Message: Unable to deserialize message with id f299dfe2-e550-4190-b6df-42416a832028\9 from queue .\Private$\MSMQTest. Please make sure only LogEntries are traced and a BinaryFormatter is used to format the message. To resolve this error, please remove the message from the queue and start the Service again. The service will be stopped.
Data: System.Collections.ListDictionaryInternal
TargetSite: Void ReceiveQueuedMessages()
HelpLink: NULL
Source: MsmqDistributor

StackTrace Information Details:
======================================
   at Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.MsmqLogDistributor.ReceiveQueuedMessages()
   at Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.MsmqLogDistributor.CheckForMessages()
   at Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.MsmqListener.OnQueueTimedEvent(Object sender, ElapsedEventArgs args)

Exception Information Details:
======================================
Exception Type: System.FormatException
Message: Invalid character in a Base-64 string.
Data: System.Collections.ListDictionaryInternal
TargetSite: Byte[] FromBase64String(System.String)
HelpLink: NULL
Source: mscorlib

 

I was able to determine that I needed to use a BinaryFormatter for my formatter on my MSMQ Trace Listener. I added the following to my config:

<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.BinaryLogFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
           name="Binary Formatter" />

And set the formatter="Binary Formatter".

I had to delete the messages from my private MSMQ due to the data not being formatted correctly, but once I did that and re-ran the service/utility, the messages were being sent to my flat file log.

Thanks for the tip to look at the Event Viewer. I didn't even think to check there for any issues.