问题
Is it possible to log properties of exception with NLog?
For example SocketException has properties such as ErrorCode, HResult, NativeErrorCode, etc that are specific to only this type of exceptions. It is possible to log them without explicitly logging (i.e without using Log(e.ErrorCode)
) them and using just ErrorException from the code? The default Exception layout renderer just calls ToString on the exception.
回答1:
I don't know if it's a very good idea, but you can write your own LayoutRenderer. To keep it simple I just wrote one that inherits from ExceptionLayoutRenderer and overrode the Append method.
[LayoutRenderer("ExtendedException")]
public class ExtendedExceptionLayoutRenderer : ExceptionLayoutRenderer
{
protected override void Append(System.Text.StringBuilder builder, LogEventInfo logEvent)
{
base.Append(builder, logEvent);
var exception = logEvent.Exception;
if (exception is SocketException)
{
var sockException = (SocketException) exception;
builder.Append(sockException.ErrorCode).Append(" ").Append(sockException.SocketErrorCode);
}
}
}
The handling of the SocketException is not very sophisticated. I'm sure there is a better way, but it shows how you can do it.
To activate that you have to adjust your config like this:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<extensions>
<add assemblyFile="YourAssembly.dll"/>
</extensions>
<targets>
<target name="console" xsi:type="Console" layout="${extendedexception} ${message}"/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="console" />
</rules>
</nlog>
Edit
Ok, I wasn't aware that you want that feature for every exception that has it's own properties. If there are only a few others you're interested in, you can just add more if(exception is YourExceptionType) and adjust what properties you're interested in. A more generic approach is to use reflection to log all properties that are defined on the exception.
[LayoutRenderer("ExtendedException")]
public class ExtendedExceptionLayoutRenderer : ExceptionLayoutRenderer
{
protected override void Append(System.Text.StringBuilder builder, LogEventInfo logEvent)
{
var exception = logEvent.Exception;
var type = exception.GetType();
var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
var logEntries = new SortedDictionary<string, string>();
foreach (var property in properties)
{
var name = property.Name;
var value = property.GetValue(exception, null).ToString();
logEntries.Add(name, value);
}
foreach (var entry in logEntries)
{
builder.AppendFormat("{0}: {1} ", entry.Key, entry.Value);
}
base.Append(builder, logEvent);
}
}
This adds every property that is declared on the exception type in alphabetical order to the log output.
回答2:
I'm not familiar with NLog, but is it possible to catch the exception in a try / catch block and then throw a new exception of your own type, overriding ToString to output the data you care about in your new exception type?
This would break tracing somewhat, so you'd probably have to include the trace information from the original exception in your ToString output, but might be an easy enough work around.
My other thought was to extend and override ToString of SocketException, but I don't believe that is possible in C#.
回答3:
Serialize the exception and log the resulting stream?
来源:https://stackoverflow.com/questions/4248434/logging-exception-properties