How to log exceptions with network targets in NLog

2019-04-06 11:41发布

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.

6条回答
家丑人穷心不美
2楼-- · 2019-04-06 12:07

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

查看更多
小情绪 Triste *
3楼-- · 2019-04-06 12:12

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.

查看更多
Melony?
4楼-- · 2019-04-06 12:19

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>
查看更多
虎瘦雄心在
5楼-- · 2019-04-06 12:25

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.

查看更多
地球回转人心会变
6楼-- · 2019-04-06 12:27

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.

查看更多
来,给爷笑一个
7楼-- · 2019-04-06 12:30

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.

查看更多
登录 后发表回答