Logging exception properties

为君一笑 提交于 2019-12-07 09:46:21

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!