A feature of my nice WPF application is to log exceptions that bring it down when running standalone. Of course this never happens but still, if such an event occurs I want to understand the cause. Why exceptions in plural? Because an exception might have an InnerException and this InnerException might have another InnerException and so forth.
I use NLog as logging framework. Nice and slick. Here is my really simple configuration:
<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="File" fileName="log.txt" layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}" />
<target name="ds" xsi:type="Debugger"/>
</targets>
<rules>
<logger name="*" writeTo="file" minLevel="Warn"/>
<logger name="*" writeTo="ds" />
</rules>
</nlog>
Basically I log exceptions to log.txt file (as well as pretty much everything to debugger’s output). The layout to write the exception is this: layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}". It is a pretty much standard NLog’s format for exceptions. However, the problem with it is that it won’t log InnerExceptions at all.
Hence I need to use the following code:
private bool showingFatal; private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { if (showingFatal) { e.Handled = true; return; } showingFatal = true; logger.Error(LogCategory.Engine, "Fatal exception start ********************** "); try { int level = 0; Exception ex = e.Exception; while (ex != null) { logger.Error(LogCategory.Engine, string.Format("Fatal exception level {0}: ", level++), ex); ex = ex.InnerException; } } finally { logger.Error(LogCategory.Engine, "Fatal exception end ********************** "); } Shutdown(); }
I use the flag showingFatal to prevent duplicate entry into the method (not sure why it happens but it happens) and a loop to log all, really all, exceptions and callstacks there are.
This way I have a good information about the exception that caused the crash. If it happens someday…
I've been getting the duplicate log entries in too. It seems to happen if your running in a multi-threaded environment.
Why not to use ${exception:maxInnerExceptionLevel=N} parameter?