LogReceiverService & LogReceiverWebServiceTarget

1,419 views
Skip to first unread message

Mark Ward

unread,
Jun 6, 2013, 5:43:16 AM6/6/13
to nlog-...@googlegroups.com
Hi,

I have been given the job of writing a centralised logging tool for my company's development department and I have chosen NLog as the technology with which to deliver it. So far, I like NLog a lot. That said, I have been banging my head against a lack of useful documentation and of working examples involving the LogReceiverService and the associated LogReceiverWebServiceTarget. So far, I have written a WCF service that implements ILogReceiverService and confirmed that this will respond to manually provided calls. I have also written code that creates and configures a LogReceiverWebServiceTarget and I call it. That's where things stop though: a breakpoint in my (running) WCF service is not triggered and there is no evidence of any attempt by NLog to call into it. I have switched on NLog's internal logging and also configured it to raise exceptions, but the log produces nothing that helps me and NLog does not raise exceptions. Basically I'm stuck and my rudimentary knowledge of WCF isn't helping.

Can anyone point to a working example anywhere? I've found a few links on the web but they're all stale. The documentation provided is also inadequate (for me, at least). For example, the NLog configuration for a LogReceiverWebServiceTarget includes a ClientId property. Documentation simply states that this "Gets or sets the ClientId property" That's fine, but what is it? All of the documentation that I have found is like this unfortunately.

Although I have asked for working examples, I will supply some code (comments removed for brevity) just to show you where I am. I really need to get this working, so any help will be gratefully received.

BTW: I code in Visual Studio 2012, C# 4.5 on a Windows 7, 64-bit machine. I reference the 'NET framework 4.0 version of NLog.dll

Thanks

WCF SERVICE: Lifted from NLog documentation

namespace xyz
{
    using NLog;
    using NLog.LogReceiverService;

    public class LogReceiverServer : ILogReceiverServer

    {
        public void ProcessLogMessages(NLogEvents nevents)

        {
            var events = nevents.ToEventInfo();
            foreach (var eachEvent in events)
            {
                var logger = LogManager.GetLogger(eachEvent.LoggerName);
                logger.Log(eachEvent);
            }
        }
    }

}

WCF SERVICE HOST: Just a console app for now

namespace xyz
{
    using System;
    using System.ServiceModel;

    internal class Program

    {
        private static void Main(string[] args)

        {
            using (var host = new ServiceHost(typeof(LogReceiverServer)))

            {
                host.Open();

                Console.WriteLine("The service is ready. Press [Enter] to stop it.");
                Console.ReadLine();

                // Close the ServiceHost.
                host.Close();
            }
        }
    }

}

LOGGER CREATION: Done in code for various reasons

        // This is called from CTOR to create an "underlying NLog logger (I am wrapping NLog to loosen the coupling between our applications and NLog).
        // This works perfectly for other types of target and allows us to hold configuration in repositories other than files,
        // e.g. SQL Server for rapid response.
        private Logger CreateLogger()
        {
            // TODO: wrap this in an async wrapper?

            // Step 1. Create configuration object 
            var config = new LoggingConfiguration();

            // Step 2. Create targets and add them to the configuration
            var targetName = Guid.NewGuid().ToString();
            var target = new LogReceiverWebServiceTarget { Name = targetName };
            config.AddTarget(targetName, target);

            // Step 3. Set target properties
            target.EndpointConfigurationName = this.endpointConfigurationName; // BasicHttpBinding_ILogReceiverServer
            target.EndpointAddress = this.endpointAddress.AbsolutePath; // http://localhost:8733/GRETIL.Logging.Server/LogReceiverServer/
            target.UseBinaryEncoding = true;
            //TODO: find out what this (ClientId) is! target.ClientId = "??";
            target.IncludeEventProperties = true;

            // Add parameters? target.Parameters.Add();
            // I do wish to pass in a custom value via the eventinfo.Properties.

            // Step 4. Define rules (ALL logging is to go through this target)
            var rule = new LoggingRule("*", LogLevel.Trace, target);
            config.LoggingRules.Add(rule);

            var fullTaxonomy = this.GetFullTaxonomy(this.taxonomy); // => the full name of the class that owns the logger instance + .MachineName

            // Use a configured factory, not LogManager again, for various reasons. This work PERFECTLY elsewhere and, when I changed this method
            // to return a FileTarget rather than a LogReceiverWebServiceTarget, logging from the returned logger worked correctly.
            var factory = new LogFactory(configuration);
            var logger = factory.GetLogger(fullTaxonomy);

            return logger;
        }

WCF Configuration

My client application contains the following in its app.config:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ILogReceiverServer" />
      </basicHttpBinding>
    </bindings>
    <client>
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ILogReceiverServer"
          contract="GRETILServerReference.ILogReceiverServer" name="BasicHttpBinding_ILogReceiverServer" />
    </client>
  </system.serviceModel>

I hope that's enough. If not, then please let me know and I'll supply more.

Thanks again.

Kim Christensen

unread,
Jun 6, 2013, 5:07:17 PM6/6/13
to nlog-...@googlegroups.com
Such a descriptive question, deserves nothing less than very good answer. I'll take a good look at the code as soon as possible, maybe tomorrow, latest Saturday. Hope this is okay, I have a lot on my plate at the moment.

Kim Christensen

unread,
Jun 8, 2013, 10:20:00 AM6/8/13
to nlog-...@googlegroups.com
Hi,

I've taken a look at you code, and tried to reproduce the error locally. I'm not getting exactly the same problem as you are.
But I'm wondering what the class "GRETILServerReference.ILogReceiverServer" is in the contract attribute of you client config. I've used NLog.LogReceiverService.ILogReceiverClient in my sample and it works, if I used the NLog.LogReceiverService.ILogReceiverServer I would get en exception when NLog is set to throw exceptions.
Please try to allow NLog to throw exceptions by setting LogManager.ThrowExceptions = true and post the exception if any

Mark Ward

unread,
Jun 10, 2013, 4:45:27 AM6/10/13
to nlog-...@googlegroups.com
Thank you: I await your reply with interest! I appreciate the time anyone takes for this: we are all busy.

Mark Ward

unread,
Jun 10, 2013, 5:26:55 AM6/10/13
to nlog-...@googlegroups.com
Hi Kim,

That was a good spot: I had left my own contract in place in the configuration by mistake. I have changed it to NLog.LogReceiverService.ILogReceiverClient but to no avail. Also, I checked LogManager.ThrowExceptions and it is true. I don't receive any exceptions however.

I wonder: could it be an error with my service host's config? I'm not strong on WCF. Here is my server host config's WCF section:

Service Host WCF Configuration

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="Gam.GRETIL.Logging.Server.LogReceiverServer">
        <endpoint address="" binding="basicHttpBinding" contract="NLog.LogReceiverService.ILogReceiverServer">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>

Thanks again for your time.

Kim Christensen

unread,
Jun 11, 2013, 3:52:43 AM6/11/13
to nlog-...@googlegroups.com
I'm not strong in WCF either, but you could try to remove the MEX endpoint. When I tested the WCF service I configured programmatically, when I'm back at my computer I'll try to configure it in the config file, and see what I can find.
Could you also try and enable the NLog internal logging, as described here, https://github.com/NLog/NLog/wiki/Logging-troubleshooting, when configured NLog from code use InternalLogger.LogToXXX.

Mark Ward

unread,
Jun 17, 2013, 11:53:21 AM6/17/13
to nlog-...@googlegroups.com
Sorry: I've been away from the office.

NLog internal logging and exception raising have been on from the beginning. No exceptions are raised and I can see nothing useful in the nlog log.

I'm going to have to start again!

By the way, do you know what the "ClientId" is in the nlog configuration? That's probably a dumb question, but I can't see what it's supposed to be!

Thanks again.

Mark Ward

unread,
Jun 17, 2013, 12:17:08 PM6/17/13
to nlog-...@googlegroups.com
DOH!

I've been on other things for the past week and so, haven't been looking at this. I finally got it working. In the end, the problem was that I was passing in a Uri and then using .AbsolutePath to configure the target (in code). I should, of course,  have used .AbsoluteUri. With the correct address (and a null ClientId, just for reference) the breakpoint on my service is now being hit.

Thanks for your time.

Kim Christensen

unread,
Jun 17, 2013, 1:43:22 PM6/17/13
to nlog-...@googlegroups.com

No problem, glad you figured it out

Message has been deleted

pogorman

unread,
Jul 30, 2014, 11:31:52 PM7/30/14
to nlog-...@googlegroups.com
Hi,

I am trying to get a working prototype working based on the code above, but I am having problems with the application that is attempting to send the logs to the WCF service. I get the following error:

"Could not find endpoint element with name 'NetNamedPipeBinding_
ILogReceiverServer' and contract 'NLog.LogReceiverService.ILogReceiverClient' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element."

I'm not sure where the problem is, here is the complete solution: https://bitbucket.org/philipogorman/logreceiverserviceexample/src

Any suggestions?

Nlog target:

    <target xsi:type="LogReceiverService"
       
name="RemoteWcfLogger"
       
endpointConfigurationName="NetNamedPipeBinding_ILogReceiverServer"
       
endpointAddress="net.pipe://localhost/4565/LogReceiverServer"
       
useBinaryEncoding="True"
       
clientId="Layout"
       
includeEventProperties="True">
     
</target>

Client config:

<configuration>
   
<system.serviceModel>
       
<bindings>
           
<netNamedPipeBinding>
               
<binding name="NetNamedPipeBinding_ILogReceiverServer">
                   
<security mode="None" />
               
</binding>
           
</netNamedPipeBinding>
       
</bindings>
       
<client>
           
<endpoint address="net.pipe://localhost/4565/LogReceiverServer"
               
binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_ILogReceiverServer"
               
contract="NLog.LogReceiverService.ILogReceiverServer" name="NetNamedPipeBinding_ILogReceiverServer" />
       
</client>
   
</system.serviceModel>
</configuration>

Service config :

<configuration>
 
<system.serviceModel>
<!--
net.pipe://localhost/4565/LogReceiverServer
-->

   
<services>
     
<service name="LogReceiverService.LogReceiverServer" behaviorConfiguration="serviceBehavior">
       
<endpoint
         
binding="netNamedPipeBinding"
         
contract="NLog.LogReceiverService.ILogReceiverServer"
         
address="LogReceiverServer"
         
bindingConfiguration="Service_Binding" />
       
<endpoint
         
binding="mexNamedPipeBinding"
         
contract="IMetadataExchange"
         
address="mex" />
       
<host>
         
<baseAddresses>
           
<add baseAddress="net.pipe://localhost/4565/" />
         
</baseAddresses>
       
</host>
     
</service>
   
</services>

   
<bindings>
     
<netNamedPipeBinding>
       
<binding name="Service_Binding" closeTimeout="infinite" openTimeout="infinite"
           
receiveTimeout="infinite" sendTimeout="infinite">
         
<security mode ="None"/>
       
</binding>
     
</netNamedPipeBinding>
   
</bindings>

   
<behaviors>
     
<serviceBehaviors>
       
<behavior name="serviceBehavior">
         
<serviceMetadata httpGetEnabled="false" />
         
<serviceDebug includeExceptionDetailInFaults="true" />
       
</behavior>
     
</serviceBehaviors>
   
</behaviors>

 
</system.serviceModel>
</configuration>






pogorman

unread,
Jul 31, 2014, 12:38:37 AM7/31/14
to nlog-...@googlegroups.com
OK - got it working. My contract name in the client app.config was incorrect. I should have read the exception message more carefully :)
The correct one is:

         <client>
           
<endpoint address="net.pipe://localhost/4565/LogReceiverServer"
               
binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_ILogReceiverServer"

               
contract="NLog.LogReceiverService.ILogReceiverClient" name="NetNamedPipeBinding_ILogReceiverServer" />
       
</client>

Anyway I will leave the  working example for others at  :  https://bitbucket.org/philipogorman/logreceiverserviceexample/src

Steve Guo

unread,
Sep 18, 2016, 7:15:40 PM9/18/16
to NLog-Users
Hey,Pogorman
I do not know how to appreciate you. I am new to Nlog and WCF. That was so kind you post the src code which can help me walk through. Thanks. Can I ask you later when I have questons? 
Reply all
Reply to author
Forward
0 new messages