Skip to content

Commit

Permalink
ExceptionLayoutRenderer - Support Serialize Format
Browse files Browse the repository at this point in the history
  • Loading branch information
snakefoot committed Oct 14, 2017
1 parent 74e6e26 commit 86a5777
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 108 deletions.
6 changes: 5 additions & 1 deletion src/NLog/Config/ExceptionRenderingFormat.cs
Expand Up @@ -71,6 +71,10 @@ public enum ExceptionRenderingFormat
/// <summary>
/// Appends the contents of an Exception's Data property to the specified target.
/// </summary>
Data = 6
Data = 6,
/// <summary>
/// Destructure the exception (usually into JSON)
/// </summary>
Serialize = 7,
}
}
114 changes: 62 additions & 52 deletions src/NLog/LayoutRenderers/ExceptionLayoutRenderer.cs
Expand Up @@ -31,17 +31,16 @@
// THE POSSIBILITY OF SUCH DAMAGE.
//

using NLog.Conditions;

namespace NLog.LayoutRenderers
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Common;
using Config;
using Internal;
using NLog.Common;
using NLog.Conditions;
using NLog.Config;
using NLog.Internal;

/// <summary>
/// Exception information provided through
Expand All @@ -64,6 +63,7 @@ public class ExceptionLayoutRenderer : LayoutRenderer
{"METHOD",ExceptionRenderingFormat.Method},
{"STACKTRACE", ExceptionRenderingFormat.StackTrace},
{"DATA",ExceptionRenderingFormat.Data},
{"@",ExceptionRenderingFormat.Serialize},
};

/// <summary>
Expand All @@ -85,7 +85,8 @@ public ExceptionLayoutRenderer()
{ExceptionRenderingFormat.ToString, AppendToString},
{ExceptionRenderingFormat.Method, AppendMethod},
{ExceptionRenderingFormat.StackTrace, AppendStackTrace},
{ExceptionRenderingFormat.Data, AppendData}
{ExceptionRenderingFormat.Data, AppendData},
{ExceptionRenderingFormat.Serialize, AppendSerializeObject},
};
}

Expand Down Expand Up @@ -192,42 +193,24 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent)
Exception primaryException = logEvent.Exception;
if (primaryException != null)
{
var sb2 = new StringBuilder(128);
string separator = string.Empty;

foreach (ExceptionRenderingFormat renderingFormat in Formats)
{
var sbCurrentRender = new StringBuilder();
var currentRenderFunction = _renderingfunctions[renderingFormat];
currentRenderFunction(sbCurrentRender, primaryException);
if (sbCurrentRender.Length > 0)
{
sb2.Append(separator);
sb2.Append(sbCurrentRender);
}
separator = Separator;
}
AppendException(primaryException, Formats, builder);

Exception currentException = primaryException.InnerException;
int currentLevel = 0;
while (currentException != null && currentLevel < MaxInnerExceptionLevel)
if (currentLevel < MaxInnerExceptionLevel)
{
AppendInnerException(sb2, currentException);

currentException = currentException.InnerException;
currentLevel++;
}
currentLevel = AppendInnerExceptionTree(primaryException, currentLevel, builder);

#if !NET3_5 && !SILVERLIGHT4
AggregateException asyncException = primaryException as AggregateException;
if (asyncException != null)
{
AppendAggregateException(primaryException, currentLevel, sb2, asyncException);
}
AggregateException asyncException = primaryException as AggregateException;
if (asyncException != null)
{
AppendAggregateException(primaryException, currentLevel, builder, asyncException);
}
#endif
builder.Append(sb2.ToString());
}
}
}

#if !NET3_5 && !SILVERLIGHT4
private void AppendAggregateException(Exception primaryException, int currentLevel, StringBuilder builder, AggregateException asyncException)
{
Expand All @@ -246,36 +229,53 @@ private void AppendAggregateException(Exception primaryException, int currentLev
continue;
}

AppendInnerException(builder, currentException);
AppendInnerException(currentException, builder);
currentLevel++;

currentException = currentException.InnerException;
while (currentException != null && currentLevel < MaxInnerExceptionLevel)
{
AppendInnerException(builder, currentException);

currentException = currentException.InnerException;
currentLevel++;
}
currentLevel = AppendInnerExceptionTree(currentException, currentLevel, builder);
}
}
}
#endif
private void AppendInnerException(StringBuilder sb2, Exception currentException)

private int AppendInnerExceptionTree(Exception currentException, int currentLevel, StringBuilder sb)
{
currentException = currentException.InnerException;
while (currentException != null && currentLevel < MaxInnerExceptionLevel)
{
AppendInnerException(currentException, sb);
currentLevel++;

currentException = currentException.InnerException;
}
return currentLevel;
}

private void AppendInnerException(Exception currentException, StringBuilder builder)
{
// separate inner exceptions
sb2.Append(InnerExceptionSeparator);
builder.Append(InnerExceptionSeparator);
AppendException(currentException, InnerFormats ?? Formats, builder);
}

string separator = string.Empty;
foreach (ExceptionRenderingFormat renderingFormat in InnerFormats ?? Formats)
private void AppendException(Exception currentException, List<ExceptionRenderingFormat> renderFormats, StringBuilder builder)
{
int orgLength = builder.Length;
foreach (ExceptionRenderingFormat renderingFormat in renderFormats)
{
sb2.Append(separator);
if (orgLength != builder.Length)
{
orgLength = builder.Length;
builder.Append(Separator);
}

int beforeRenderLength = builder.Length;
var currentRenderFunction = _renderingfunctions[renderingFormat];

currentRenderFunction(sb2, currentException);

separator = Separator;
currentRenderFunction(builder, currentException);
if (builder.Length == beforeRenderLength && builder.Length != orgLength)
{
builder.Length = orgLength;
}
}
}

Expand Down Expand Up @@ -378,6 +378,16 @@ protected virtual void AppendData(StringBuilder sb, Exception ex)
}
}

/// <summary>
/// Appends all the serialized properties of an Exception into the specified <see cref="StringBuilder" />.
/// </summary>
/// <param name="sb">The <see cref="StringBuilder"/> to append the rendered data to.</param>
/// <param name="ex">The Exception whose properties should be appended.</param>
protected virtual void AppendSerializeObject(StringBuilder sb, Exception ex)
{
ConfigurationItemFactory.Default.ValueSerializer.SerializeObject(ex, null, null, sb);
}

/// <summary>
/// Split the string and then compile into list of Rendering formats.
/// </summary>
Expand Down
26 changes: 8 additions & 18 deletions src/NLog/Targets/DefaultJsonSerializer.cs
Expand Up @@ -349,7 +349,7 @@ private bool SerializeTypeCodeValue(object value, StringBuilder destination, Jso
TypeCode objTypeCode = Convert.GetTypeCode(value);
if (objTypeCode == TypeCode.Object)
{
if (value is Guid || value is TimeSpan)
if (value is Guid || value is TimeSpan || value is MemberInfo || value is Assembly)
{
//object without property, to string
QuoteValue(destination, Convert.ToString(value, CultureInfo.InvariantCulture));
Expand Down Expand Up @@ -726,33 +726,23 @@ private static bool EscapeChar(char ch, bool escapeUnicode)

try
{
properties = GetPropertyInfosNoCache(type);
if (properties == null)
{
properties = ArrayHelper.Empty<PropertyInfo>();
}
properties = type.GetProperties(PublicProperties);
}
catch (Exception ex)
{
properties = ArrayHelper.Empty<PropertyInfo>();
Common.InternalLogger.Warn(ex, "Failed to get JSON properties for type: {0}", type);
}
finally
{
if (properties == null)
properties = ArrayHelper.Empty<PropertyInfo>();
}

props = new KeyValuePair<PropertyInfo[], ReflectionHelpers.LateBoundMethod[]>(properties, ArrayHelper.Empty<ReflectionHelpers.LateBoundMethod>());
_propsCache.TryAddValue(type, props);
return props;
}

private static PropertyInfo[] GetPropertyInfosNoCache(Type type)
{
#if NETSTANDARD
var props = System.Linq.Enumerable.ToArray(type.GetRuntimeProperties());
#else
var props = type.GetProperties();
#endif
return props;
}


private const BindingFlags PublicProperties = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
}
}

0 comments on commit 86a5777

Please sign in to comment.