How to check when log service is unavailable

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to check when log service is unavailable

jortega
Hi,

I have a silverlight application (version 4.0) where I use NLog (version 2.0) to trace in the server where the application is deployed.
What I am doing is that when the NLog service isn't available, I want to store in the isolated storage of the client machine the traces.
My use case is the following:

- The log service is available when the application is loaded.
- In certain period of time, when I want to store a trace, the log service is suddenly unavailable.

For this case, I was looking for if NLog sends me any kind of error when the log service fails.
I noticed that the method LogReceiverWebServiceTarget.Send has:

            client.ProcessLogMessagesCompleted += (sender, e) =>
                {
                    // report error to the callers
                    foreach (var ev in asyncContinuations)
                    {
                        ev.Continuation(e.Error);
                    }

                    // send any buffered events
                    this.SendBufferedEvents();
                };

but the error is not raised more due to the method ExceptionHelper.MustBeRethrown doesn't raise communication exceptions.
To solve my problem, I have done the following modifications:

In NLog source code:

1-. I have defined in LogReceiverWebServiceTarget class a new event:

public event EventHandler<LogReceiverWebServiceTargetEventArgs> OnErrorRaised;

2-. I have created a specific arguments for this event:

    public class LogReceiverWebServiceTargetEventArgs : EventArgs
    {
        public Exception InnerException { get; set; }
    }

3-. In the LogReceiverWebServiceTarget.Send method:

            client.ProcessLogMessagesCompleted += (sender, e) =>
                {
                    // report error to the callers
                    foreach (var ev in asyncContinuations)
                    {
                        ev.Continuation(e.Error);
                    }

                    // send any buffered events
                    this.SendBufferedEvents();

                    //That's my new code: I raise up the error to the caller
                    if (e.Error != null && this.OnErrorRaised != null)
                    {
                        OnErrorRaised(this, new LogReceiverWebServiceTargetEventArgs() { InnerException = e.Error });
                    }
                };

In my application:

private void ConfigureLogging(ConfigData config)
        {
            LoggingConfiguration nLogConfig = new LoggingConfiguration();
            if (!config.LoggingEnabled)
                return;
           
            foreach (UDLoggingRule logRule in config.EnabledLoggingRules)
            {

                LogReceiverWebServiceTarget receiveService = new NLog.Targets.LogReceiverWebServiceTarget();

                receiveService.IncludeEventProperties = true;
                receiveService.EndpointAddress = logRule.EndPointTarget;
                receiveService.OnErrorRaised += receiveService_OnErrorRaised;
         
                NLog.LogLevel logLevel = NLog.LogLevel.FromString(logRule.LoggingLevel[0]);
                NLog.Config.LoggingRule loggingRule = new NLog.Config.LoggingRule(logRule.LoggerNamePattern, logLevel, receiveService);
                nLogConfig.LoggingRules.Add(loggingRule);
               
            }
            NLog.LogManager.Configuration = nLogConfig;
            NLog.LogManager.ThrowExceptions = true;
            NLog.LogManager.EnableLogging();
            NLog.LogManager.ReconfigExistingLoggers();
        }

        void receiveService_OnErrorRaised(object sender, NLog.Targets.Events.LogReceiverWebServiceTargetEventArgs e)
        {
            //Write trace error in isolated storage of the client machine
        }

My question is:

Can I achieve that without modifying your source code?If it's not possible, do you have thought to add this functionality in next NLog versions?

Thanks alot.

Best regards.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to check when log service is unavailable

Jason LaFlair
Administrator
Have you looked into the FallbackGroup wrapper target

http://nlog-project.org/wiki/FallbackGroup_target

You could setup your webservice as the first target, with a file target as your second.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to check when log service is unavailable

jortega
Hi Jason,

I guess my Nlog.config will be:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="file" xsi:type="FallbackGroup" returnToFirstOnSuccess="false">
      <target name="logfile"
            xsi:type="File"
            fileName="c:\temp\NLog.txt"
            autoFlush="true"
            archiveAboveSize="52428800"
            maxArchiveFiles="200"
            archiveFileName="c:\temp\Archive{###}-NLog.txt"
            archiveNumbering="Sequence"
            archiveEvery="Day">
        <layout xsi:type="CSVLayout">
          <column name="time" layout="${longdate}" />
          <column name="level" layout="${level}"/>
          <column name="message" layout="${message}" />
          <column name="logger" layout="${logger}"/>
          <column name="clientAddress" layout="${event-context:item=ClientAddress}"/>
          <column name="eventNumber" layout="${event-context:item=EventNumber}"/>
          <column name="exception" layout="${exception:format=ToString,StackTrace}" />
         
          <quoteChar>"</quoteChar>
          <withHeader>True</withHeader>
          <quoting>Auto</quoting>
          <delimiter>Semicolon</delimiter>
        </layout>
      </target>
    </target>
    <default-wrapper xsi:type="BufferingWrapper" bufferSize="100" encoding="utf-8"/>   
  </targets>

  <rules>
    <logger name="*" writeTo="logfile" />
  </rules>
 
</nlog>

but:

1-. where the exception is raised inside NLog source code from?
2-  where do I catch this exception in my application?

Thanks a lot.

Best regards.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to check when log service is unavailable

Jason LaFlair
Administrator
Ok, just to clarify - you want to log to your web service, but if that fails to make the call you want to log to the local system (to a file)?

With that assumption I'd think you'd want a config something like this:

<targets>
    <target name="file" xsi:type="FallbackGroup" name="fallbackTarget" returnToFirstOnSuccess="true">
        <target name="logfile" xsi:type="WebService" />
        <target name="logfile" xsi:type="File"  />
    </target>
</targets>
<rules>
    <logger name="*" writeTo="fallbackTarget" />
</rules>

Basically log to the fallback group and let it do it's job.  If it fails to write to the webservice it will then log to the filesystem.  With returnToFirstOnSuccess set to True it will always try to hit the webservice first.

Hope this helps, if not :) please let me know.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to check when log service is unavailable

jortega
Hi,

my configuration is:

I have a silverlight application deployed in machine A.
I have a WCF service to trace deployed also in machine A. This service uses NLog to perform the traces.
From my application, I call to my WCF service to trace.

my use case is:

I enter in the application from machine B: this means that the silverlight plug-in is downloaded in the machine B so the logic will be executed in the client.
When I want to trace, I call from machine B to my WCF service and my service call to Nlog methods but when the internal logic of Nlog raises an error, this error isn't raised to my wcf service.
For this reason I did the changes put in the first post in your code in order to do that Nlog raises up the exception to my service and then my service raises up the exception to my application.

Do you understand it?

Thanks a lot for your help Jason.

Best regards.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to check when log service is unavailable

Jason LaFlair
Administrator
After seeing this thread and thinking about it a bit more I'm thinking there was another issue someone was having with the LogReceiverService truly swallowing exceptions.

I'll have to do some digging and code diving when time frees up a bit more.

If anyone else remembers this, please speak up!!

Jason.
Loading...