title: Log Buffering Through MSMQ to WCF Web Service
body: <p>I have an interesting situation on my hands. For a few years now we've had a WCF service that runs on an IIS box on our network that we use for logging. Applications use basicHttpBinding to send log messages and it logs them to a database. Most of the logging from all other applications is limited to a few dozen logs per operation. Recently we've ported another application to use this logging service. This application logs quite a bit more aggressively than any of the other clients for our logging service. It has an operation that during its course could log over 100,000 messages (this is for importing 100,000 records via CSV file).</p>
  
  <p>In trying to find a way to make this run more efficiently it was suggested that I try MSMQ to queue the log requests and forward them on to the service instead of having the application communicate directly with the logging service (the request <em>was</em> being sent in a separate thread for performance purposes). In this way the application isn't blocked while the log is being written. I have implemented a proof of concept for this MSMQ solution on my local machine but as I have never used MSMQ before, and as I am only now learning what its place is technologically, I'm finding myself with a lot of questions and few answers. I'm hoping someone can point me to some concise information on how MSMQ works so that I can better debug this proof of concept I have written.</p>
  
  <p>What I'm seeing after implementing MSMQ:</p>
  
  <ul>
  <li>My application that sends the logs to
  MSMQ returns almost immediately
  (rather than waiting for the log to
  be committed) which is what I want. </li>
  <li>Even though I sent 1000 logs to the
  MSMQ application in fewer than 30
  seconds, it takes several minutes for
  all 1000 logs to make it to the
  database. It appears as though my
  queue has some sort of throttling
  enabled where it is holding back the
  log requests but I don't know how / where to check that.</li>
  <li>If I use net.tcp on the server receiving the logs from the MSMQ service I get a ton of service timeout errors and only 90% (or so) of the logs make it to the database but if I use basicHttpBinding it works reliably.</li>
  </ul>
  
  <p>Here is the code in my MSMQ service:</p>
  
  <pre><code>public void QueueLog(Log log)
  {
      try
      {
          ServiceClient writeLog = getLoggingService();
  
          string exceptionText = log.Exception == null ? string.Empty : log.Exception.ToString();
          writeLog.WriteCompatibleLog(log.LoggerName, (LoggingService.Logging.LogType)log.LogType, exceptionText, log.Message, log.ApplicationName, Utility.GetAssemblyVersion(Assembly.GetCallingAssembly()),
              Utility.GetFirstIPAddress(), Utility.GetHostName(), log.Category);
      }
      catch (Exception ex)
      {
          Debug.WriteLine("LoggingServiceWrapper.DotNet Error\n\n" + ex.GetBaseException().Message + "\n\n" + ex.GetBaseException().StackTrace);
      }
  }
  
  private ServiceClient getLoggingService()
  {
      return new ServiceClient(new BasicHttpBinding(), new EndpointAddress("http://MyServer/Service.svc"));
  
  }
  </code></pre>
  
  <p>Here is the code of me creating the MSMQ service</p>
  
  <pre><code>if (!MessageQueue.Exists(Properties.Settings.Default.QueueName))
  {
      MessageQueue.Create(Properties.Settings.Default.QueueName, true);
  }
  
  ServiceHost serviceHost = new ServiceHost(typeof(LoggingServiceQueue.LoggingServiceQueue), new Uri(Properties.Settings.Default.Address));
  {
      serviceHost.Open();
  
      Console.ReadLine();
  
      serviceHost.Close();
  }
  </code></pre>
  
  <p>Here is the code in the application I use to call the MSMQ service:</p>
  
  <pre><code>LoggingServiceQueueClient client = new LoggingServiceQueueClient(new NetMsmqBinding(NetMsmqSecurityMode.None), new EndpointAddress("net.msmq://localhost/private/Logging"));
  
  client.QueueLog(new LoggingServiceQueue.Log
  {
      LoggerName = loggerName,
      LogType = (LoggingServiceQueue.LogType)logType,
      ApplicationName = applicationName,
      Category = category,
      Exception = exception,
      Message = message,
      SourceHostName = Utility.GetHostName(),
      SourceIp = Utility.GetFirstIPAddress(),
      Version = Utility.GetAssemblyVersion(callingAssembly)
  });
  </code></pre>
  
  <p>I appreciate any help someone can provide. I'm a little lost on exactly what set of features are available to me using MSMQ. I have done 6 or so hours of research via google. Most docs I have found are pretty old (2007) and are a tough read. Perhaps they are expecting me to have some baser level of knowledge on the subject.</p>