MSMQ TraceListener and WCF MSMQIntegrationBinding Problem

Topics: General discussion, Logging Application Block
Apr 22, 2009 at 10:29 AM
Hi,

I have a WCF application that uses MSMQ Integration binding. It basically reads the messages from a private queue and raises an event.
It works perfectly when the message is sent to the queue manually like this

MessageQueue queue = new MessageQueue(@"formatname:DIRECT=OS:.\private$\logqueue");

System.Messaging.Message msg = new System.Messaging.Message(logMessage, new BinaryMessageFormatter());

queue.Send(msg, MessageQueueTransactionType.Automatic);

But it fails (without any error!) when the message are sent to the queue using MSMQ TraceListener of Logging Application block. It just picks up the message from the queue, but it does not raise any event in WCF.

Any idea?

Thanks in advance.

Regards,

Andy
Apr 22, 2009 at 10:41 AM
Did you follow the instructions in the documentation on how to integrate logging with WCF?  It's under the Logging Application Block -> Developing Applications Using the Logging Application Block  section.


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Apr 22, 2009 at 11:15 AM
Hi,

Thanks for the reply. I did read that article, but that article seems to be related to Tracing.

I will try to explain my applications more.See, I have two application. A client and a serve application.

The client application uses Enterprise Lib MSMQ TraceListener to send the messages to a private queue. Thats it, the job of client application is over.

The server application is a WCF service. It uses the MSMQ Integration Binding to read the messages from the queue.

This does not work if I use Enterprise Lib MSMQ TraceListener to send the messages (LogEntry) to the private queue.

But, It works if in the client application I don't use MSMQ TraceListener and send the messages manually through C# like:

MessageQueue queue = new MessageQueue(@"formatname:DIRECT=OS:.\private$\logqueue");

System.Messaging.Message msg = new System.Messaging.Message(logMessage, new BinaryMessageFormatter());

queue.Send(msg, MessageQueueTransactionType.Automatic);

Apr 22, 2009 at 11:31 AM
So the logging works when using MSMQ TraceListener and the problem is you can't read the message from the queue?  Please clarify because in your initial post, you said that it picks up the message from the queue but does not raise any event in WCF.  


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Apr 22, 2009 at 11:46 AM
Okay I will try explain my sever application in more details:

Actually we get this MSMQ Distributor service with Enterprise Library 4.1. This service reads the message from the queue and processes them as per configuration.

So I have modified the source code of MSMQ Distributor service, so that it uses WCF MSMQ IntegrationBinding to read the messages from the queue.

So basically, I'm trying to add WCF Interface to the MSMQ Distrbutor service. This works if I the client sends the messages manually using the code posted above. But it does not work if the client uses MSMQ Trace Listener!

PS: In WCF MSMQ IntegrationBinding, we don't read the messases manually, rather WCF monitors the queue and raises an event as soon as it recieves the message from the queue.

Regards,

Andy
Apr 22, 2009 at 11:54 AM
Did you use BinaryFormatter for your MSMQ trace listener? This is required if you're going to use it with the Distributor Service.  


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Apr 22, 2009 at 1:37 PM
Hi,

Yes, the MSMQ trace listener is using Binary formatter.
I have created a sample client-server applications. Should I mail you the code for better understanding?

Regards,

Anand
Apr 23, 2009 at 7:28 AM
Edited Apr 23, 2009 at 4:26 PM
Yes, much appreciated. We'll be waiting.
Apr 23, 2009 at 10:55 AM
Hi, I have just sent the sample client-server applications to entlib.support@avanade.com.

The client application can send the messages in two different ways.
One is to send messages manually through C# and other is to send them using Ent. Lib MSMQ TraceListener.
Server application uses WCF MSMQ Integration Binding to read the messages.
It works perfectly if you send the messages manually through C#.
But it doesn't work for messsages sent using Ent. Lib MSMQ TraceListener.

Regards,

Andy
Apr 23, 2009 at 5:05 PM
Hi,

As far I have debugged, I found out that the MsmqTraceListener formats the LogEntry object as string then assigns it to the body of the Message. Unlike when you do the normal code, you just pass the LogEntry object as a parameter to the constructor of the Message. That could be a possible reason why the msmqIntegrationBinding does not detect the log from the msmqtracelistener. I'm not sure if this is by design. As a workaround, you can either edit the msmqtracelistener source code or you could implement your own Custom Trace Listener which will send the message to the queue. I tried to implement a custom trace listener and it works well with the solution that you've provided. Here is the sample code for the custom trace listener.

    [ConfigurationElementType(typeof(CustomTraceListenerData))]

    public class CustomMsmqTraceListener : CustomTraceListener

    {

 

        public override void Write(string message)

        {

            throw new NotImplementedException();

        }

 

        public override void WriteLine(string message)

        {

            throw new NotImplementedException();

        }

 

        public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, 
                System.Diagnostics.TraceEventType eventType,    int id, object data)

        {

            if (data is LogEntry && this.Formatter != null)

            {

                Write(data as LogEntry);

            }

            else

            {

                this.WriteLine(data.ToString());

            }

        }

 

        public override void Write(object o)

        {

            if (o is LogEntry)

            {

                MessageQueue queue = new MessageQueue(@"formatname:DIRECT=OS:.\private$\logqueue");

                Message message = new Message();

                message.Body = o as LogEntry;

                message.Formatter = new BinaryMessageFormatter();

                queue.Send(message, MessageQueueTransactionType.Automatic);

            }

        }

    }



Valiant Dudan
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Apr 27, 2009 at 11:17 AM
Hi,

Thank you very much. This works perfectly. :)

Regards,

Andy
Dec 18, 2009 at 9:47 PM

Hi ,I am building a MSMQ application. I am writing from an application to a queue in Text Format . And my windows service picks it up from the MSMQ and puts it in the database.

But the problem I am facing here is that the complete string in the MSMQ is going into the message.. ITs not getting splitted up into the text fomatter pattern. I would like to know what I am doing wrong.

Please help.
Please find the below attached files for reference.

 Did u find the solution for this problem. I am facing the same problem . Would be glad if you can help me out.  

Thanks 

MSMQLog Distributor MSMQ to Database App.config

 

<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="dataConfiguration"
				 type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null " />
		<section name="msmqDistributorSettings"
				 type="XXX.Logging.LogService.Configuration.MsmqDistributorSettings, ConsumerService_LoggingService" />
	</configSections>
	<loggingConfiguration name="Logging Application Block"
						  tracingEnabled="true"
						  defaultCategory="General"
						  logWarningsWhenNoCategoriesMatch="true">
		<listeners>
			<add databaseInstanceName="LogConnection"
				 writeLogStoredProcName="WriteLog"
				 addCategoryStoredProcName="AddCategory"
				 formatter="Text Formatter"
				 listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
				 traceOutputOptions="None"
				 filter="All"
				 type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
				 name="Database Trace Listener" />
		</listeners>
		<formatters>
			<add template="Timestamp:  {timestamp}&#xD;&#xA;Message:  {message}&#xD;&#xA;Category:  {category}&#xD;&#xA;Priority:  {priority}&#xD;&#xA;EventId:  {eventid}&#xD;&#xA;Severity:  {severity}&#xD;&#xA;Title:  {title}&#xD;&#xA;Brand:  {brand}&#xD;&#xA;Farm:  {farm}&#xD;&#xA;Machine:  {machine}&#xD;&#xA;Application Domain:  {appDomain}&#xD;&#xA;Process Id:  {processId}&#xD;&#xA;Process Name:  {processName}&#xD;&#xA;Win32 Thread Id:  {win32ThreadId}&#xD;&#xA;Thread Name:  {threadName}&#xD;&#xA;Extended Properties:  {dictionary({key} - {value}&#xD;&#xA;)}"
				 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="Database Trace Listener" />
				</listeners>
			</add>
			<add switchValue="All"
				 name="Information">
				<listeners>
					<add name="Database Trace Listener" />
				</listeners>
			</add>
			<add switchValue="All"
				 name="Error">
				<listeners>
					<add name="Database Trace Listener" />
				</listeners>
			</add>
		</categorySources>
		<specialSources>
			<allEvents switchValue="All"
					   name="All Events" />
			<notProcessed switchValue="All"
						  name="Unprocessed Category" />
			<errors switchValue="All"
					name="Logging Errors Warnings">
				<listeners>
					<add name="Database Trace Listener" />
				</listeners>
			</errors>
		</specialSources>
	</loggingConfiguration>

RECEIVED QUEUE MESSAGE METHOD in MSMQ log DISTRIBUTOR - MSMQ to Database Service 
    private void ReceiveQueuedMessages()
        {
            this.isCompleted = false;
            while (!IsQueueEmpty())
            {
                using (MessageQueue msmq = CreateMessageQueue())
                {
                    System.Messaging.Message message = msmq.Peek();

                    string serializedEntry = message.Body.ToString();
                    LogEntry logEntry = new LogEntry();
                    try
                    {
                        logEntry.Message = serializedEntry;
                    }
                    catch (FormatException formatException)
                    {
                        string logMessage = string.Format(
                            Resources.Culture,
                            Resources.ExceptionCouldNotDeserializeMessageFromQueue,
                            message.Id,
                            msmq.Path);

                        this.eventLogger.LogServiceFailure(
                            logMessage,
                            formatException,
                            TraceEventType.Error);

                        throw new LoggingException(logMessage, formatException);
                    }
                    catch (SerializationException serializationException)
                    {
                        string logMessage = string.Format(
                            Resources.Culture,
                            Resources.ExceptionCouldNotDeserializeMessageFromQueue,
                            message.Id,
                            msmq.Path);

                        this.eventLogger.LogServiceFailure(
                            logMessage,
                            serializationException,
                            TraceEventType.Error);

                        throw new LoggingException(logMessage, serializationException);
                    }

                    if (logEntry != null)
                    {
                        msmq.Formatter = new ActiveXMessageFormatter();
                        // Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(logEntry);
                        logWriter.Write(logEntry);

                        //logEntry.Title = "Consumer Service Log";
                        // logWriter.Write(logEntry);
                    }

                    message = msmq.Receive();

                    if (this.StopReceiving)
                    {
                        this.isCompleted = true;
                        return;
                    }
                }
            }
Application that writes to MSMQ App.config

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<configSections>
		<section name="loggingConfiguration"
				 type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
		<section name="dataConfiguration"
				 type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data" />
	</configSections>
	<loggingConfiguration name="Logging Application Block"
						  tracingEnabled="true"
						  defaultCategory="General"
						  logWarningsWhenNoCategoriesMatch="true">
		<listeners>
			<add name="Formatted EventLog TraceListener"
				 source="Enterprise Library Logging"
				 formatter="Text Formatter"
				 log="Application"
				 machineName=""
				 listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
				 traceOutputOptions="None"
				 filter="All"
				 type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
         />
			<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="Formatname:DIRECT=OS:XXX\private$\XXX"
				 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}&#xD;&#xA;Message:  {message}&#xD;&#xA;Category:  {category}&#xD;&#xA;Priority:  {priority}&#xD;&#xA;EventId:  {eventid}&#xD;&#xA;Severity:  {severity}&#xD;&#xA;Title:  {title}&#xD;&#xA;Brand:  {brand}&#xD;&#xA;Farm:  {farm}&#xD;&#xA;Machine:  {machine}&#xD;&#xA;Application Domain:  {appDomain}&#xD;&#xA;Process Id:  {processId}&#xD;&#xA;Process Name:  {processName}&#xD;&#xA;Win32 Thread Id:  {win32ThreadId}&#xD;&#xA;Thread Name:  {threadName}&#xD;&#xA;Extended Properties:  {dictionary({key} - {value}&#xD;&#xA;)}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        name="Text Formatter" />
    </formatters>
		<categorySources>
			<add switchValue="All"
				 name="Error">
				<listeners>
					<add name="Msmq TraceListener" />
				</listeners>
			</add>
			<add switchValue="All"
				 name="General">
				<listeners>
					<add name="Msmq TraceListener" />
				</listeners>
			</add>
			<add switchValue="All"
				 name="Information">
				<listeners>
					<add name="Msmq 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="Formatted EventLog TraceListener" />
					<add name="Msmq TraceListener" />
				</listeners>
			</errors>
		</specialSources>
	</loggingConfiguration>
</configuration>

 

Code that writes to MSMQ 

  Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry logEntry = new LogEntry();
            logEntry.EventId = 100;
            logEntry.Priority = 2;
            logEntry.Message = "DISTRIBUTOR TEST";
            logEntry.Brand = "Thrift";
            logEntry.Farm = "ZTZRBrands";

            DTG.Global.Object.Message message = new DTG.Global.Object.Message(5, "error trying to make a res");

 Logger.Write(logEntry);

 

 

Please help. 

 

Thanks 

Anjana 

 

 

 

 

 

Dec 21, 2009 at 3:26 AM

Replied to your other thread - http://entlib.codeplex.com/Thread/View.aspx?ThreadId=78597

 

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

Nov 21, 2014 at 9:05 PM
Any sample console applications (Client and Server) for testing issues about MSMQ private queues ?

Console application in Client to send message and read message from/to private queue in Server.

Console application in Server to send message and read message from/toprivate queue.


Client send Message A to private Queue in Server

Server read Message A from private queue

Server sendMessage B to private queue

Client read Message B from private queue.


Client logging to MSMQ, private queue in Server.

any full source code sample in github?