Skip to content

Commit

Permalink
Added serilog destructring for newtonsoft, sjt and nettolpologysuite (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
david-driscoll authored Jun 29, 2022
1 parent b7b7ed7 commit 2b52094
Show file tree
Hide file tree
Showing 49 changed files with 1,045 additions and 61 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,5 @@ src/Cake.Scripts/tools/tools/
codealike.json

# Rider
.idea/
.idea/
*.received.*
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using Rocket.Surgery.Conventions;
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.LaunchPad.Foundation.Conventions;
using Rocket.Surgery.LaunchPad.Serilog;
using Serilog;

[assembly: Convention(typeof(NewtonsoftJsonConvention))]

Expand All @@ -16,8 +18,14 @@ namespace Rocket.Surgery.LaunchPad.Foundation.Conventions;
/// <summary>
/// Convention for working with Newtonsoft Json
/// </summary>
public class NewtonsoftJsonConvention : IServiceConvention
public class NewtonsoftJsonConvention : IServiceConvention, ISerilogConvention
{
/// <inheritdoc />
public void Register(IConventionContext context, IServiceProvider services, IConfiguration configuration, LoggerConfiguration loggerConfiguration)
{
loggerConfiguration.Destructure.NewtonsoftJsonTypes();
}

/// <inheritdoc />
public void Register(IConventionContext context, IConfiguration configuration, IServiceCollection services)
{
Expand Down
76 changes: 76 additions & 0 deletions src/Foundation.NewtonsoftJson/NewtonsoftJsonDestructuringPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Newtonsoft.Json.Linq;
using Serilog.Core;
using Serilog.Events;

namespace Rocket.Surgery.LaunchPad.Foundation;

internal class NewtonsoftJsonDestructuringPolicy : IDestructuringPolicy
{
private static LogEventPropertyValue Destructure(JValue jv, ILogEventPropertyValueFactory propertyValueFactory)
{
return propertyValueFactory.CreatePropertyValue(jv.Value, true);
}

private static LogEventPropertyValue Destructure(JArray ja, ILogEventPropertyValueFactory propertyValueFactory)
{
var elems = ja.Select(t => propertyValueFactory.CreatePropertyValue(t, true));
return new SequenceValue(elems);
}

private static LogEventPropertyValue Destructure(JObject jo, ILogEventPropertyValueFactory propertyValueFactory)
{
string typeTag = null;
var props = new List<LogEventProperty>(jo.Count);

foreach (var prop in jo.Properties())
{
if (prop.Name == "$type")
{
if (prop.Value is JValue typeVal && typeVal.Value is string)
{
typeTag = (string)typeVal.Value;
continue;
}
}
else if (!LogEventProperty.IsValidName(prop.Name))
{
return DestructureToDictionaryValue(jo, propertyValueFactory);
}

props.Add(new LogEventProperty(prop.Name, propertyValueFactory.CreatePropertyValue(prop.Value, true)));
}

return new StructureValue(props, typeTag);
}

private static LogEventPropertyValue DestructureToDictionaryValue(JObject jo, ILogEventPropertyValueFactory propertyValueFactory)
{
var elements = jo.Properties().Select(
prop =>
new KeyValuePair<ScalarValue, LogEventPropertyValue>(
new ScalarValue(prop.Name),
propertyValueFactory.CreatePropertyValue(prop.Value, true)
)
);
return new DictionaryValue(elements);
}

public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
{
switch (value)
{
case JObject jo:
result = Destructure(jo, propertyValueFactory);
return true;
case JArray ja:
result = Destructure(ja, propertyValueFactory);
return true;
case JValue jv:
result = Destructure(jv, propertyValueFactory);
return true;
}

result = null;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Serilog;
using Serilog.Configuration;

namespace Rocket.Surgery.LaunchPad.Foundation;

/// <summary>
/// Adds the Destructure.NewtonsoftJsonTypes() extension to <see cref="LoggerConfiguration" />.
/// </summary>
public static class NewtonsoftJsonLoggerConfigurationExtensions
{
/// <summary>
/// Enable destructuring of JSON.NET dynamic objects.
/// </summary>
/// <param name="configuration">The logger configuration to apply configuration to.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration NewtonsoftJsonTypes(this LoggerDestructuringConfiguration configuration)
{
return configuration.With<NewtonsoftJsonDestructuringPolicy>();
}
}
17 changes: 10 additions & 7 deletions src/Foundation/Conventions/SystemTextJsonConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Rocket.Surgery.Conventions;
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.LaunchPad.Foundation.Conventions;
using Rocket.Surgery.LaunchPad.Serilog;
using Serilog;

[assembly: Convention(typeof(SystemTextJsonConvention))]

Expand All @@ -17,14 +19,15 @@ namespace Rocket.Surgery.LaunchPad.Foundation.Conventions;
/// Implements the <see cref="IServiceConvention" />
/// </summary>
/// <seealso cref="IServiceConvention" />
public class SystemTextJsonConvention : IServiceConvention
public class SystemTextJsonConvention : IServiceConvention, ISerilogConvention
{
/// <summary>
/// Registers the specified context.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="configuration"></param>
/// <param name="services"></param>
/// <inheritdoc />
public void Register(IConventionContext context, IServiceProvider services, IConfiguration configuration, LoggerConfiguration loggerConfiguration)
{
loggerConfiguration.Destructure.SystemTextJsonTypes();
}

/// <inheritdoc />
public void Register(IConventionContext context, IConfiguration configuration, IServiceCollection services)
{
services.AddTransient<IConfigureOptions<JsonSerializerOptions>>(
Expand Down
40 changes: 40 additions & 0 deletions src/Foundation/SystemTextJsonDestructuringPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Text.Json;
using Serilog.Core;
using Serilog.Events;

namespace Rocket.Surgery.LaunchPad.Foundation;

internal class SystemTextJsonDestructuringPolicy : IDestructuringPolicy
{
private static LogEventPropertyValue Destructure(in JsonElement jel)
{
return jel.ValueKind switch
{
JsonValueKind.Array => new SequenceValue(jel.EnumerateArray().Select(ae => Destructure(in ae))),
JsonValueKind.False => new ScalarValue(false),
JsonValueKind.True => new ScalarValue(true),
JsonValueKind.Null => new ScalarValue(null),
JsonValueKind.Undefined => new ScalarValue(null),
JsonValueKind.Number => new ScalarValue(jel.GetDecimal()),
JsonValueKind.String => new ScalarValue(jel.GetString()),
JsonValueKind.Object => new StructureValue(jel.EnumerateObject().Select(jp => new LogEventProperty(jp.Name, Destructure(jp.Value)))),
_ => throw new ArgumentException("Unrecognized value kind " + jel.ValueKind + ".")
};
}

public bool TryDestructure(object value, ILogEventPropertyValueFactory _, out LogEventPropertyValue? result)
{
switch (value)
{
case JsonDocument jdoc:
result = Destructure(jdoc.RootElement);
return true;
case JsonElement jel:
result = Destructure(jel);
return true;
}

result = null;
return false;
}
}
20 changes: 20 additions & 0 deletions src/Foundation/SystemTextJsonLoggerConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Serilog;
using Serilog.Configuration;

namespace Rocket.Surgery.LaunchPad.Foundation;

/// <summary>
/// Adds the Destructure.NewtonsoftJsonTypes() extension to <see cref="LoggerConfiguration" />.
/// </summary>
public static class SystemTextJsonLoggerConfigurationExtensions
{
/// <summary>
/// Enable destructuring of JSON.NET dynamic objects.
/// </summary>
/// <param name="configuration">The logger configuration to apply configuration to.</param>
/// <returns>An object allowing configuration to continue.</returns>
public static LoggerConfiguration SystemTextJsonTypes(this LoggerDestructuringConfiguration configuration)
{
return configuration.With<SystemTextJsonDestructuringPolicy>();
}
}
10 changes: 9 additions & 1 deletion src/Spatial/Conventions/SpatialConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
using NetTopologySuite.Geometries;
using Rocket.Surgery.Conventions;
using Rocket.Surgery.Conventions.DependencyInjection;
using Rocket.Surgery.LaunchPad.Serilog;
using Rocket.Surgery.LaunchPad.Spatial.Conventions;
using Serilog;

[assembly: Convention(typeof(SpatialConvention))]

Expand All @@ -15,8 +17,14 @@ namespace Rocket.Surgery.LaunchPad.Spatial.Conventions;
/// <summary>
/// Adds support for spatial types into STJ
/// </summary>
public class SpatialConvention : IServiceConvention
public class SpatialConvention : IServiceConvention, ISerilogConvention
{
/// <inheritdoc />
public void Register(IConventionContext context, IServiceProvider services, IConfiguration configuration, LoggerConfiguration loggerConfiguration)
{
loggerConfiguration.Destructure.NetTopologySuiteTypes();
}

/// <inheritdoc />
public void Register(IConventionContext context, IConfiguration configuration, IServiceCollection services)
{
Expand Down
Loading

0 comments on commit 2b52094

Please sign in to comment.