Last active
March 17, 2021 16:48
-
-
Save jezzsantos/4b1f27e9a7c99784a6aa4fcab3ba1b55 to your computer and use it in GitHub Desktop.
A serilog.net Enricher (with unit tests) that removes any properties of any structured value that are named by a black-list (partially or wholly case-sensitive).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Serilog.Events; | |
namespace Gene.Diagnostics | |
{ | |
/// <summary> | |
/// Defines a black-list filter of <see cref="LogEventPropertyValue" /> | |
/// </summary> | |
internal class BlacklistedPropertyFilter : ILogEventPropertyValueFilter | |
{ | |
private Func<string, bool> isBlacklistedName; | |
public BlacklistedPropertyFilter(Func<string, bool> isBlacklistedName) | |
{ | |
this.isBlacklistedName = isBlacklistedName; | |
} | |
public LogEventPropertyValue Apply(ScalarValue value) | |
{ | |
//Do nothing with ScalarValue, as property has no name to filter | |
return null; | |
} | |
public LogEventPropertyValue Apply(SequenceValue value) | |
{ | |
var childElements = value.Elements.ToList(); | |
var clonedChildElements = new List<LogEventPropertyValue>(childElements); | |
var requireUpdate = false; | |
childElements.ForEach(childElement => | |
{ | |
var updatedChild = Apply(childElement); | |
if (updatedChild != null) | |
{ | |
clonedChildElements[clonedChildElements.FindIndex(x => x == childElement)] = updatedChild; | |
requireUpdate = true; | |
} | |
}); | |
if (requireUpdate) | |
{ | |
return new SequenceValue(clonedChildElements); | |
} | |
return null; | |
} | |
public LogEventPropertyValue Apply(DictionaryValue value) | |
{ | |
var childElements = value.Elements.ToList(); | |
var clonedChildElements = value.Elements.ToDictionary(x => x.Key, x => x.Value); | |
var requireUpdate = false; | |
childElements.ForEach(childElement => | |
{ | |
var name = childElement.Key.Value.ToString(); | |
if (this.isBlacklistedName(name)) | |
{ | |
clonedChildElements.Remove(childElement.Key); | |
requireUpdate = true; | |
} | |
else | |
{ | |
var updatedChild = Apply(childElement.Value); | |
if (updatedChild != null) | |
{ | |
clonedChildElements[childElement.Key] = updatedChild; | |
requireUpdate = true; | |
} | |
} | |
}); | |
if (requireUpdate) | |
{ | |
return new DictionaryValue(clonedChildElements); | |
} | |
return null; | |
} | |
public LogEventPropertyValue Apply(StructureValue value) | |
{ | |
var childProperties = value.Properties.ToList(); | |
var clonedChildProperties = new List<LogEventProperty>(childProperties); | |
var requireUpdate = false; | |
childProperties.ForEach(childProperty => | |
{ | |
var name = childProperty.Name; | |
if (this.isBlacklistedName(name)) | |
{ | |
clonedChildProperties.Remove(childProperty); | |
requireUpdate = true; | |
} | |
else | |
{ | |
var updatedChild = Apply(childProperty.Value); | |
if (updatedChild != null) | |
{ | |
clonedChildProperties[clonedChildProperties.FindIndex(x => x == childProperty)] | |
= new LogEventProperty(childProperty.Name, updatedChild); | |
requireUpdate = true; | |
} | |
} | |
}); | |
if (requireUpdate) | |
{ | |
return new StructureValue(clonedChildProperties); | |
} | |
return null; | |
} | |
public LogEventPropertyValue Apply(LogEventPropertyValue value) | |
{ | |
var scalarValue = value as ScalarValue; | |
if (scalarValue != null) | |
{ | |
return new FilterableScalar(scalarValue).Filter(this); | |
} | |
var sequenceValue = value as SequenceValue; | |
if (sequenceValue != null) | |
{ | |
return new FilterableSequence(sequenceValue).Filter(this); | |
} | |
var dictionaryValue = value as DictionaryValue; | |
if (dictionaryValue != null) | |
{ | |
return new FilterableDictionary(dictionaryValue).Filter(this); | |
} | |
var structureValue = value as StructureValue; | |
if (structureValue != null) | |
{ | |
return new FilterableStructure(structureValue).Filter(this); | |
} | |
return null; | |
} | |
} | |
internal interface ILogEventPropertyValueFilter | |
{ | |
LogEventPropertyValue Apply(ScalarValue value); | |
LogEventPropertyValue Apply(SequenceValue value); | |
LogEventPropertyValue Apply(DictionaryValue value); | |
LogEventPropertyValue Apply(StructureValue value); | |
} | |
internal interface IFilterableLogEventPropertyValue | |
{ | |
LogEventPropertyValue Filter(ILogEventPropertyValueFilter filter); | |
} | |
internal class FilterableScalar : IFilterableLogEventPropertyValue | |
{ | |
private ScalarValue value; | |
public FilterableScalar(ScalarValue value) | |
{ | |
this.value = value; | |
} | |
public LogEventPropertyValue Filter(ILogEventPropertyValueFilter filter) | |
{ | |
return filter.Apply(this.value); | |
} | |
} | |
internal class FilterableSequence : IFilterableLogEventPropertyValue | |
{ | |
private SequenceValue value; | |
public FilterableSequence(SequenceValue value) | |
{ | |
this.value = value; | |
} | |
public LogEventPropertyValue Filter(ILogEventPropertyValueFilter filter) | |
{ | |
return filter.Apply(this.value); | |
} | |
} | |
internal class FilterableDictionary : IFilterableLogEventPropertyValue | |
{ | |
private DictionaryValue value; | |
public FilterableDictionary(DictionaryValue value) | |
{ | |
this.value = value; | |
} | |
public LogEventPropertyValue Filter(ILogEventPropertyValueFilter filter) | |
{ | |
return filter.Apply(this.value); | |
} | |
} | |
internal class FilterableStructure : IFilterableLogEventPropertyValue | |
{ | |
private StructureValue value; | |
public FilterableStructure(StructureValue value) | |
{ | |
this.value = value; | |
} | |
public LogEventPropertyValue Filter(ILogEventPropertyValueFilter filter) | |
{ | |
return filter.Apply(this.value); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using Serilog.Core; | |
using Serilog.Events; | |
namespace Gene.Diagnostics | |
{ | |
/// <summary> | |
/// Defines a <see cref="ILogEventEnricher" /> that removes properties that match (wholey or partially case-sensitive) those in a black-list | |
/// </summary> | |
public class BlackListedPropertyRemover : ILogEventEnricher | |
{ | |
internal static readonly List<string> DefaultBlacklistedPropertyNames = new List<string> | |
{ | |
"Password", | |
"Secret", | |
"Token", | |
"Pin" | |
}; | |
private IEnumerable<string> blacklistedNames; | |
public BlackListedPropertyRemover() | |
: this(DefaultBlacklistedPropertyNames) | |
{ | |
} | |
public BlackListedPropertyRemover(IEnumerable<string> blacklistedNames) | |
{ | |
this.blacklistedNames = blacklistedNames; | |
} | |
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) | |
{ | |
var filter = new BlacklistedPropertyFilter(n => IsBlacklistedName(n)); | |
logEvent.Properties | |
.ToList() | |
.ForEach(propertyValue => | |
{ | |
var name = propertyValue.Key; | |
if (IsBlacklistedName(name)) | |
{ | |
logEvent.RemovePropertyIfPresent(name); | |
} | |
else | |
{ | |
var updatedPropertyValue = filter.Apply(propertyValue.Value); | |
if (updatedPropertyValue != null) | |
{ | |
logEvent.AddOrUpdateProperty(new LogEventProperty(name, updatedPropertyValue)); | |
} | |
} | |
}); | |
} | |
private bool IsBlacklistedName(string name) | |
{ | |
return this.blacklistedNames.Any(bl => bl.EqualsOrdinal(name) || name.Contains(bl)); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Gene.Diagnostics; | |
using Microsoft.VisualStudio.TestTools.UnitTesting; | |
using Moq; | |
using Serilog.Core; | |
using Serilog.Events; | |
using Serilog.Parsing; | |
namespace Gene.UnitTests.Diagnostics | |
{ | |
public class BlackListedPropertyRemoverSpec | |
{ | |
private static readonly IAssertion Assert = new Assertion(); | |
[TestClass] | |
public class GivenABlacklistedName | |
{ | |
private BlackListedPropertyRemover enricher; | |
private Mock<ILogEventPropertyFactory> propertyFactory; | |
[TestInitialize] | |
public void Initialize() | |
{ | |
this.propertyFactory = new Mock<ILogEventPropertyFactory>(); | |
this.enricher = new BlackListedPropertyRemover(new List<string> { "ablacklistedname" }); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithScalars_ThenNotRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname1", new ScalarValue("avalue")), | |
new LogEventProperty("aname2", new ScalarValue(42)) | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(2, logEvent.Properties.Count); | |
Assert.Equal("\"avalue\"", logEvent.Properties["aname1"].ToString()); | |
Assert.Equal("42", logEvent.Properties["aname2"].ToString()); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithStructureContainingNoSensitiveProperties_ThenNotRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname1", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname2", new ScalarValue("avalue2")), | |
new LogEventProperty("aname3", new ScalarValue("avalue3")), | |
})), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(1, logEvent.Properties.Count); | |
Assert.Equal("{ aname2: \"avalue2\", aname3: \"avalue3\" }", logEvent.Properties["aname1"].ToString()); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingAPartiallySensitiveStructuredProperty_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistednameandprefix", new StructureValue(new List<LogEventProperty>())), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(0, logEvent.Properties.Count); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingAWrongCasedSensitiveStructuredProperty_ThenNotRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aBlacklistedName", new StructureValue(new List<LogEventProperty>())), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(1, logEvent.Properties.Count); | |
Assert.Equal("{ }", logEvent.Properties["aBlacklistedName"].ToString()); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingASingleSensitiveStructuredProperty_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new StructureValue(new List<LogEventProperty>())), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(0, logEvent.Properties.Count); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingASingleSensitiveScalarProperty_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(0, logEvent.Properties.Count); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingASingleSensitiveSequenceProperty_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue1"), | |
new ScalarValue("avalue2"), | |
})), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(0, logEvent.Properties.Count); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingASingleSensitiveDictionaryProperty_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname2"), new ScalarValue("avalue") } | |
})), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(0, logEvent.Properties.Count); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingSensitiveProperties_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname1", new ScalarValue("avalue1")), | |
new LogEventProperty("aname2", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname3", new ScalarValue("avalue3")), | |
})), | |
new LogEventProperty("aname4", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname5"), new ScalarValue("avalue5") } | |
})), | |
new LogEventProperty("aname6", new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue6") | |
})), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("ablacklistedname", new StructureValue(new List<LogEventProperty>())), | |
new LogEventProperty("ablacklistedname", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue>())), | |
new LogEventProperty("ablacklistedname", new SequenceValue(new List<LogEventPropertyValue>())), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(4, logEvent.Properties.Count); | |
Assert.Equal("\"avalue1\"", logEvent.Properties["aname1"].ToString()); | |
Assert.Equal("{ aname3: \"avalue3\" }", logEvent.Properties["aname2"].ToString()); | |
Assert.Equal("[(\"aname5\": \"avalue5\")]", logEvent.Properties["aname4"].ToString()); | |
Assert.Equal("[\"avalue6\"]", logEvent.Properties["aname6"].ToString()); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingNestedSensitiveProperties_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname1", new ScalarValue("avalue1")), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname2", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname3", new ScalarValue("avalue3")), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname4", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname5", new ScalarValue("avalue5")), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
})), | |
new LogEventProperty("aname6", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname7"), new ScalarValue("avalue7") }, | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
})), | |
new LogEventProperty("aname8", new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue8"), | |
})), | |
})), | |
new LogEventProperty("aname9", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname10"), new ScalarValue("avalue10") }, | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ | |
new ScalarValue("aname11"), new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname12", new ScalarValue("avalue12")), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
}) | |
}, | |
{ | |
new ScalarValue("aname13"), new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname14"), new ScalarValue("avalue15") }, | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
}) | |
}, | |
{ | |
new ScalarValue("aname16"), new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue16"), | |
}) | |
}, | |
})), | |
new LogEventProperty("aname17", new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue18"), | |
new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname19", new ScalarValue("avalue19")), | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
}), | |
new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("aname20"), new ScalarValue("avalue20") }, | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
}), | |
new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("avalue21"), | |
}), | |
})), | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(4, logEvent.Properties.Count); | |
Assert.Equal("\"avalue1\"", logEvent.Properties["aname1"].ToString()); | |
Assert.Equal("{ aname3: \"avalue3\", aname4: { aname5: \"avalue5\" }, aname6: [(\"aname7\": \"avalue7\")], aname8: [\"avalue8\"] }", | |
logEvent.Properties["aname2"].ToString()); | |
Assert.Equal( | |
"[(\"aname10\": \"avalue10\"), (\"aname11\": { aname12: \"avalue12\" }), (\"aname13\": [(\"aname14\": \"avalue15\")]), (\"aname16\": [\"avalue16\"])]", | |
logEvent.Properties["aname9"].ToString()); | |
Assert.Equal("[\"avalue18\", { aname19: \"avalue19\" }, [(\"aname20\": \"avalue20\")], [\"avalue21\"]]", | |
logEvent.Properties["aname17"].ToString()); | |
} | |
[TestMethod, TestCategory("Unit")] | |
public void WhenEnrichWithComplexStructureContainingRecursiveSensitiveProperties_ThenRemoved() | |
{ | |
var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, | |
new MessageTemplate("atemplate", new List<MessageTemplateToken>()), | |
new List<LogEventProperty> | |
{ | |
new LogEventProperty("aname1", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname2", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname3", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname4", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname5", new StructureValue(new List<LogEventProperty> | |
{ | |
new LogEventProperty("ablacklistedname", new ScalarValue("avalue")), | |
new LogEventProperty("aname6", new ScalarValue("avalue6")), | |
})), | |
})), | |
})), | |
})), | |
})), | |
new LogEventProperty("aname7", new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ | |
new ScalarValue("aname8"), new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ | |
new ScalarValue("aname9"), new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ | |
new ScalarValue("aname10"), new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ | |
new ScalarValue("aname11"), new DictionaryValue(new Dictionary<ScalarValue, LogEventPropertyValue> | |
{ | |
{ new ScalarValue("ablacklistedname"), new ScalarValue("avalue") }, | |
{ new ScalarValue("aname12"), new ScalarValue("avalue12") }, | |
}) | |
}, | |
}) | |
}, | |
}) | |
}, | |
}) | |
}, | |
})), | |
new LogEventProperty("aname13", new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("aname14"), | |
new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("aname15"), | |
new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("aname16"), | |
new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("aname17"), | |
new SequenceValue(new List<LogEventPropertyValue> | |
{ | |
new ScalarValue("aname18"), | |
}) | |
}) | |
}) | |
}) | |
})) | |
}); | |
this.enricher.Enrich(logEvent, this.propertyFactory.Object); | |
Assert.Equal(3, logEvent.Properties.Count); | |
Assert.Equal("{ aname2: { aname3: { aname4: { aname5: { aname6: \"avalue6\" } } } } }", logEvent.Properties["aname1"].ToString()); | |
Assert.Equal("[(\"aname8\": [(\"aname9\": [(\"aname10\": [(\"aname11\": [(\"aname12\": \"avalue12\")])])])])]", logEvent.Properties["aname7"].ToString()); | |
Assert.Equal("[\"aname14\", [\"aname15\", [\"aname16\", [\"aname17\", [\"aname18\"]]]]]", logEvent.Properties["aname13"].ToString()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment