How to log exceptions with network targets in NLog
Asked Answered
H

6

8

I am using the NLog logging framework and am trying to get exception and stacktrace information showing up in any UDP logger appliaction, such as Sentinel and Log2Console, but can only get the log message part displayed. Outputting to a file works well as most examples do just that, so the problem revolves around using network targets with NLog.

Bonus if a custom format can be applied on inner exceptions and stacktrace, but this is not required. Exception.ToString() would go a long way.

Note on the example code: With Log2Console I found an article on how to send exception as a separate log entry. Although this worked, I was not happy with the solution.

Example exception logging code:

Logger Log = LogManager.GetCurrentClassLogger();

try
{
    throw new InvalidOperationException("My ex", new FileNotFoundException("My inner ex1", new AccessViolationException("Innermost ex")));
}
catch (Exception e)
{
    Log.ErrorException("TEST", e);
}

Example NLog.config:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<targets async="true">

    <!-- Send by UDP to Sentinel with NLogViewer protocol -->
    <target name="network" xsi:type="NLogViewer" address="udp://192.168.1.3:9999" layout="${message}${onexception:inner=${newline}${exception:format=tostring}}" />

    <!-- Send message by UDP to Log2Console with Chainsaw protocol -->
    <target name="network2" xsi:type="Chainsaw" address="udp://192.168.1.3:9998" appinfo="Grocelist"/>

    <!-- Send exception/stacktrace by UDP to Log2Console with generic network protocol -->
    <target name="network2ex" xsi:type="Network" address="udp4://192.168.1.3:9998" layout="${exception:format=ToString}" />

    <target name="logfile" xsi:type="File" layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=tostring}"
                createDirs="true"
                fileName="${basedir}/logs/${shortdate}.log"
                />
</targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
    <logger name="*" minlevel="Debug" writeTo="network" />
    <logger name="*" minlevel="Debug" writeTo="network2" />
    <logger name="*" minlevel="Warn" writeTo="network2ex" />
  </rules>
</nlog>

Some links:

Edit: After searching some more this seems to be a limitation on NLog's end. A recent patch is apparently out there: log4jxmlevent does not render Exception

Edit2: I rebuilt NLog with patch, but it did not seem to help in Sentinel or Log2Console apps. I might have to try log4net to make sure those apps really do support what I am trying to achieve.

Edit3: I currently use string.Format() to join and format message and exception text myself. This works well, but is not what I'm looking for here.

Horrendous answered 3/4, 2012 at 9:31 Comment(1)
The source code for NLogViewerTarget on Github shows that the Layout set {} is no-op so you cannot override the default which does not include exceptions.Rasping
G
4

You can also extend NLog to include exceptions for network logging.

Create an extended layout:

[Layout("Log4JXmlEventLayoutEx")]    
public class Log4JXmlEventLayoutEx : Log4JXmlEventLayout
{
    protected override string GetFormattedMessage(LogEventInfo logEvent)
    {
        string msg = logEvent.Message + " ${exception:format=Message,Type,ToString,StackTrace}";
        msg = SimpleLayout.Evaluate(msg, logEvent);    
        LogEventInfo updatedInfo;
        if (msg == logEvent.Message) { 
            updatedInfo = logEvent;
        } else {
            updatedInfo = new LogEventInfo(
                logEvent.Level, logEvent.LoggerName, 
                logEvent.FormatProvider, msg, 
                logEvent.Parameters, logEvent.Exception);
        }    
        return base.GetFormattedMessage(updatedInfo);
    }
}

Create a target that uses that layout

[Target("NLogViewerEx")]
public class NLogViewerTargetEx : NLogViewerTarget
{
    private readonly Log4JXmlEventLayoutEx layout = new Log4JXmlEventLayoutEx();    
    public override Layout Layout { get { return layout; } set {} }
}

Update NLog.config:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <extensions>
    <add assembly="Assembly.Name.That.Contains.Extended.Target"/>
  </extensions>
  <targets>
    <target name="logViewer" 
            xsi:type="NLogViewerEx" 
            address="udp://localhost:7071">
  </targets>
 ...
</nlog>
Gamb answered 20/3, 2013 at 9:34 Comment(1)
Hi Alex, is it possible to have two custom Layouts for two targets? Sentinel and `File ? I'm stuck and it is not working (https://mcmap.net/q/1326947/-nlog-custom-filetarget/6229375) - (link updated).Diestock
F
3

A few years later and this is pretty trivial, try adding

includeSourceInfo="true"

to your target file, so it looks like;

 <target name="viewer"
            xsi:type="NLogViewer"
            includeSourceInfo="true"
            address="udp://127.0.0.1:9999" />

Gives you Source File, Line, Class and Method info.

Felicidad answered 16/11, 2015 at 21:41 Comment(2)
Thanks, I'll try this the next time I come across NLog and UDP again.Horrendous
Sadly still no easy way of getting a stacktrace though! And running in Release mode strips a lot of the source info.. I'd avoid this approach a bit longer :-)Felicidad
S
2

I had this problem, and just updated my NLog nuget package to 2.0.1.2

Now I have exceptions coming through to Log2Console just fine.

Stingy answered 30/4, 2013 at 12:11 Comment(1)
Thanks for the heads up, I'll have to revisit this sometime and try it myself! Could you also post your configuration?Horrendous
S
1

Have you tried the latest developer snapshot of Chainsaw? It will display stack traces and supports log4net/UDP appenders, and according to NLog you can use it as well: http://nlog-project.org/wiki/Chainsaw_target

Try the latest developer snapshot, has a ton of features: http://people.apache.org/~sdeboy

Sherellsherer answered 3/4, 2012 at 22:51 Comment(2)
I feel bad, but I can't seem to figure out how to run the latest snapshot on Windows? The zip file only contains a .bat, and by reading it I can't figure out exactly what I need to do to get it working.Horrendous
You need to have a Java runtime installed. Once you do, you can save the zip to your file system and extract it, navigate to the apache-chainsaw-2.1.0-SNAPSHOT\bin folder and run the chainsaw.bat command. That should do it.Sherellsherer
S
1

Just download and build the latest (NLog-Build-2.0.0.2007-0-g72f6495) sources from GitHub: https://github.com/jkowalski/NLog/tree/ This issue is fixed there by NLog developer.

Shipboard answered 4/4, 2012 at 14:20 Comment(1)
You can also download compiled binaries from here nlog.codeplex.com/releases/view/81084Raoul
R
1

In your NLog.config modify the target like the following.

<target name="file" xsi:type="File" fileName="log.txt" layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}" /> 

The part that you are looking for is

${exception:format=message,stacktrace:separator=*}

For more information on this look here.

Royceroyd answered 18/4, 2013 at 19:13 Comment(2)
This is for file target only, right? The question was to get exception information for network targets.Horrendous
Ahh, I must have just missed that. Yes this is for outputting to a file. GL getting a network solution.Royceroyd

© 2022 - 2024 — McMap. All rights reserved.