diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml
index e110b23..8ff0130 100644
--- a/.github/workflows/benchmarks.yml
+++ b/.github/workflows/benchmarks.yml
@@ -38,7 +38,7 @@ jobs:
tool: 'benchmarkdotnet'
output-file-path: src/Benchmarks/BenchmarkDotNet.Artifacts/results/Combined.Benchmarks.json
github-token: ${{ secrets.GITHUB_TOKEN }}
- alert-threshold: '110%'
+ alert-threshold: '130%'
comment-on-alert: true
- name: Push benchmarks results
if: github.event_name != 'pull_request'
diff --git a/README.md b/README.md
index f894ca2..1a52736 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ public class PersonalData
public string? Name { get; set; }
}
```
-snippet source | anchor
+snippet source | anchor
## 2. Ignoring a property
diff --git a/src/Destructurama.Attributed.Tests/Approval/Destructurama.Attributed.approved.txt b/src/Destructurama.Attributed.Tests/Approval/Destructurama.Attributed.approved.txt
index e112361..894160f 100644
--- a/src/Destructurama.Attributed.Tests/Approval/Destructurama.Attributed.approved.txt
+++ b/src/Destructurama.Attributed.Tests/Approval/Destructurama.Attributed.approved.txt
@@ -4,6 +4,7 @@ namespace Destructurama.Attributed
{
public AttributedDestructuringPolicyOptions() { }
public bool IgnoreNullProperties { get; set; }
+ public bool RespectLogPropertyIgnoreAttribute { get; set; }
}
public interface IPropertyDestructuringAttribute
{
diff --git a/src/Destructurama.Attributed.Tests/AttributedDestructuringTests.cs b/src/Destructurama.Attributed.Tests/AttributedDestructuringTests.cs
index 64f5624..8abd804 100644
--- a/src/Destructurama.Attributed.Tests/AttributedDestructuringTests.cs
+++ b/src/Destructurama.Attributed.Tests/AttributedDestructuringTests.cs
@@ -1,4 +1,5 @@
using Destructurama.Attributed.Tests.Support;
+using Microsoft.Extensions.Logging;
using NUnit.Framework;
using Serilog.Events;
using Shouldly;
@@ -63,6 +64,7 @@ public void AttributesAreConsultedWhenDestructuring()
MutableScalar = new(),
NotAScalar = new(),
Ignored = "Hello, there",
+ Ignored2 = "Hello, there again",
ScalarAnyway = new(),
AuthData = new()
{
@@ -71,11 +73,14 @@ public void AttributesAreConsultedWhenDestructuring()
}
};
- var evt = DelegatingSink.Execute(customized);
+ var evt = DelegatingSink.Execute(customized, configure: opt => opt.RespectLogPropertyIgnoreAttribute = true);
var sv = (StructureValue)evt.Properties["Customized"];
var props = sv.Properties.ToDictionary(p => p.Name, p => p.Value);
+ props.ShouldNotContainKey("Ignored");
+ props.ShouldNotContainKey("Ignored2");
+
props["ImmutableScalar"].LiteralValue().ShouldBeOfType();
props["MutableScalar"].LiteralValue().ShouldBe(new MutableScalar().ToString());
props["NotAScalar"].ShouldBeOfType();
@@ -145,6 +150,9 @@ public class Customized
[NotLogged]
public string? Ignored { get; set; }
+ [LogPropertyIgnore]
+ public string? Ignored2 { get; set; }
+
[LogAsScalar]
public NotAScalar? ScalarAnyway { get; set; }
diff --git a/src/Destructurama.Attributed.Tests/Destructurama.Attributed.Tests.csproj b/src/Destructurama.Attributed.Tests/Destructurama.Attributed.Tests.csproj
index c5e68bc..8f7cb82 100644
--- a/src/Destructurama.Attributed.Tests/Destructurama.Attributed.Tests.csproj
+++ b/src/Destructurama.Attributed.Tests/Destructurama.Attributed.Tests.csproj
@@ -5,9 +5,11 @@
net8.0
false
$(NoWarn);1591
+ $(DefineConstants);CODE_GENERATION_ATTRIBUTES
+
diff --git a/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicy.cs b/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicy.cs
index 6dbebc6..6b3edf8 100644
--- a/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicy.cs
+++ b/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicy.cs
@@ -68,7 +68,18 @@ private static IEnumerable GetPropertiesRecursive(Type type)
private CacheEntry CreateCacheEntry(Type type)
{
- static T GetCustomAttribute(PropertyInfo propertyInfo) => propertyInfo.GetCustomAttributes().OfType().FirstOrDefault();
+ IPropertyDestructuringAttribute? GetPropertyDestructuringAttribute(PropertyInfo propertyInfo)
+ {
+ var attr = propertyInfo.GetCustomAttributes().OfType().FirstOrDefault();
+ if (attr != null)
+ return attr;
+
+ // Do not check attribute explicitly to not take dependency from Microsoft.Extensions.Telemetry.Abstractions package.
+ // https://github.com/serilog/serilog/issues/1984
+ return _options.RespectLogPropertyIgnoreAttribute && propertyInfo.GetCustomAttributes().Any(a => a.GetType().FullName == "Microsoft.Extensions.Logging.LogPropertyIgnoreAttribute")
+ ? NotLoggedAttribute.Instance
+ : null;
+ }
var classDestructurer = type.GetCustomAttributes().OfType().FirstOrDefault();
if (classDestructurer != null)
@@ -76,19 +87,19 @@ private CacheEntry CreateCacheEntry(Type type)
var properties = GetPropertiesRecursive(type).ToList();
if (!_options.IgnoreNullProperties && properties.All(pi =>
- GetCustomAttribute(pi) == null
- && GetCustomAttribute(pi) == null))
+ GetPropertyDestructuringAttribute(pi) == null
+ && pi.GetCustomAttributes().OfType().FirstOrDefault() == null))
{
return CacheEntry.Ignore;
}
var optionalIgnoreAttributes = properties
- .Select(pi => new { pi, Attribute = GetCustomAttribute(pi) })
+ .Select(pi => new { pi, Attribute = pi.GetCustomAttributes().OfType().FirstOrDefault() })
.Where(o => o.Attribute != null)
.ToDictionary(o => o.pi, o => o.Attribute);
var destructuringAttributes = properties
- .Select(pi => new { pi, Attribute = GetCustomAttribute(pi) })
+ .Select(pi => new { pi, Attribute = GetPropertyDestructuringAttribute(pi)! })
.Where(o => o.Attribute != null)
.ToDictionary(o => o.pi, o => o.Attribute);
diff --git a/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicyOptions.cs b/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicyOptions.cs
index 3f2c4b6..4d00e9a 100644
--- a/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicyOptions.cs
+++ b/src/Destructurama.Attributed/Attributed/AttributedDestructuringPolicyOptions.cs
@@ -13,4 +13,10 @@ public class AttributedDestructuringPolicyOptions
/// and affected by this property only in case at least one property (or the type itself) has Destructurama attribute applied.
///
public bool IgnoreNullProperties { get; set; }
+
+ ///
+ /// Respect Microsoft.Extensions.Logging.LogPropertyIgnoreAttribute to not include property when destructuring an object for logging.
+ /// This works the same as when applying to the property but may help if you have no access to it's source code.
+ ///
+ public bool RespectLogPropertyIgnoreAttribute { get; set; }
}
diff --git a/src/Destructurama.Attributed/Attributed/NotLoggedAttribute.cs b/src/Destructurama.Attributed/Attributed/NotLoggedAttribute.cs
index 8a3f830..40c4369 100644
--- a/src/Destructurama.Attributed/Attributed/NotLoggedAttribute.cs
+++ b/src/Destructurama.Attributed/Attributed/NotLoggedAttribute.cs
@@ -24,6 +24,8 @@ namespace Destructurama.Attributed;
[AttributeUsage(AttributeTargets.Property)]
public class NotLoggedAttribute : Attribute, IPropertyDestructuringAttribute
{
+ internal static readonly NotLoggedAttribute Instance = new();
+
///
public bool TryCreateLogEventProperty(string name, object? value, ILogEventPropertyValueFactory propertyValueFactory, [NotNullWhen(true)] out LogEventProperty? property)
{
diff --git a/src/Destructurama.Attributed/Attributed/NotLoggedIfDefaultAttribute.cs b/src/Destructurama.Attributed/Attributed/NotLoggedIfDefaultAttribute.cs
index 71751cb..af09497 100644
--- a/src/Destructurama.Attributed/Attributed/NotLoggedIfDefaultAttribute.cs
+++ b/src/Destructurama.Attributed/Attributed/NotLoggedIfDefaultAttribute.cs
@@ -48,7 +48,6 @@ bool IPropertyOptionalIgnoreAttribute.ShouldPropertyBeIgnored(string name, objec
{
if (value != null)
{
-
if (type.IsValueType)
{
if (!_cache.TryGetValue(type, out CachedValue cachedValue))