Serilog.FluentDestructuring
1.0.1
dotnet add package Serilog.FluentDestructuring --version 1.0.1
NuGet\Install-Package Serilog.FluentDestructuring -Version 1.0.1
<PackageReference Include="Serilog.FluentDestructuring" Version="1.0.1" />
<PackageVersion Include="Serilog.FluentDestructuring" Version="1.0.1" />
<PackageReference Include="Serilog.FluentDestructuring" />
paket add Serilog.FluentDestructuring --version 1.0.1
#r "nuget: Serilog.FluentDestructuring, 1.0.1"
#:package Serilog.FluentDestructuring@1.0.1
#addin nuget:?package=Serilog.FluentDestructuring&version=1.0.1
#tool nuget:?package=Serilog.FluentDestructuring&version=1.0.1
Serilog.FluentDestructuring
This package makes it possible to manipulate how complex objects are logged to Serilog using Fluent API.
Motivation
The Destructurama.Attributed package provides convenient ways to configure Serilog complex object logging by using attributes. With these, you can easily ignore some properties, apply masking and so on. But this attribute-based approach does introduce a dependency on Serilog in projects where such a dependency may be undesirable (a similar issue exists with Entity Framework Core and its attribute-based model configuring approach). This package emerged out of the need to eliminate this dependency and provide another way for the developers to configure complex objects logging using a Fluent API.
Installation
Package Manager
NuGet\Install-Package Serilog.FluentDestructuring -Version *version_number*
.NET CLI
dotnet add package Serilog.FluentDestructuring --version *version_number*
Usage
Define your custom policy and override configure method to specify what destructuring rules to use.
public class ApplicationFluentDestructuringPolicy : FluentDestructuringPolicy
{
protected override void Configure(FluentDestructuringBuilder builder)
{
// Your configurations.
}
}
Modify logger configuration.
var cfg = new LoggerConfiguration()
.Destructure.WithFluentDestructuringPolicy<ApplicationFluentDestructuringPolicy>()
...
Destructuring rules applying.
Add configuration for specific entity type right here.
public class ApplicationFluentDestructuringPolicy : FluentDestructuringPolicy
{
protected override void Configure(FluentDestructuringBuilder builder)
{
builder.Entity<UserRegisterRequest>(e =>
{
e.Property(p => p.Email)
.Mask();
e.Property(p => p.Password)
.Ignore();
});
}
}
Apply predefined configuration for a specific entity.
public class UserRegisterRequestDestructuringConfiguration : IEntityDestructuringConfiguration<UserRegisterRequest>
{
public void Configure(EntityDestructuringBuilder<UserRegisterRequest> builder)
{
builder.Property(p => p.Email)
.Mask();
builder.Property(p => p.Password)
.Ignore();
}
}
public class ApplicationFluentDestructuringPolicy : FluentDestructuringPolicy
{
protected override void Configure(FluentDestructuringBuilder builder)
{
builder.ApplyConfiguration(new UserRegisterRequestDestructuringConfiguration());
}
}
Apply all entity destructuring configurations found in a specified assembly.
public class ApplicationFluentDestructuringPolicy : FluentDestructuringPolicy
{
protected override void Configure(FluentDestructuringBuilder builder)
{
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
}
1. Changing a property name.
Apply by calling WithAlias
method.
builder.Entity<UserRegisterRequest>(e =>
{
e.Property(p => p.Email)
.WithAlias("user_email");
});
You can also use custom property name along with a main destructuring rule.
builder.Entity<UserRegisterRequest>(e =>
{
e.Property(p => p.Email)
.Mask()
.WithAlias("user_email");
});
2. Ignoring a property.
Apply by calling Ignore
method.
builder.Entity<UserRegisterRequest>(e =>
{
e.Property(p => p.Password)
.Ignore();
});
3. Logging types and properties as scalars.
Apply by calling AsScalar
method.
// Whole entity.
builder.Entity<UserRegisterRequest>(e => e.AsScalar());
builder.Entity<UserRegisterRequest>(e =>
{
// Individual property.
e.Property(p => p.Passport)
.AsScalar();
});
4. Masking a property.
Apply by calling Mask
method.
Note that masking works for properties of type string
, IEnumerable<string>
or derived from it, for example, string[]
or List<string>
.
4.1. Default behaviour.
- MaskCharacter: The character used for masking. The default is an asterisk
*
. - MaskLength: The length of the mask to be applied. This is the number of
MaskCharacter
that will be used to obfuscate the value. The default is10
. - PreserveValueLength: Value indicating whether the length of the original value should be preserved when applying the mask. If
true
, the masked value will have the same length as the original value, and theMaskLength
property will be ignored. The default isfalse
.
builder.Entity<UserRegisterRequest>(e =>
{
// Default masking processor with default options.
e.Property(p => p.Email)
.Mask();
// Customize default masking processor behaviour by specify options.
e.Property(e => e.Password)
.Mask(new DefaultMaskingProcessorOptions { PreserveValueLength = true, MaskCharacter = '#' })
});
4.2. Custom behaviour.
You can use custom masking processor by implementing the IMaskingProcessor
interface and passing an instance to one of the overloads of Mask
method.
public class PasswordMaskingProcessor : IMaskingProcessor
{
public bool TryMask(string value, out string? maskedValue)
{
// Your implementation.
}
}
builder.Entity<UserRegisterRequest>(e =>
{
e.Property(e => e.Password)
.Mask(new PasswordMaskingProcessor());
});
5. Conditional property destructuring.
You can define the condition under which the destructuring rule will be applied.
builder.Entity<UserRegisterRequest>(e =>
{
// One of predefined conditions.
e.Property(p => p.Email)
.Ignore()
.ApplyWhenNull();
e.Property(e => e.Passport)
.AsScalar()
.WithAlias("user_passport")
.ApplyWhenNotNull();
// Define your custom condition.
e.Property(p => p.Password)
.Mask()
.ApplyWhen(e => !string.IsNullOrWhiteSpace(e.Email) && e.Email.EndsWith("@gmail.com"));
});
6. Inner entities.
Only single-level properties are supported.
builder.Entity<UserRegisterRequest>(e =>
{
// Will throw an exception.
e.Property(e => e.Passport.Series)
.Mask();
});
Configure inner entities by calling InnerEntity
method.
builder.Entity<UserRegisterRequest>(e =>
{
e.InnerEntity(o => o.Passport, x =>
{
x.Property(a => a.Series)
.Mask();
x.Property(a => a.Number)
.Ignore()
.ApplyWhenNull();
})
.WithAlias("user_passport")
.ApplyWhen(e => !string.IsNullOrWhiteSpace(e.Email));
});
Or apply predefined configuration.
public class UserPassportRequestDestructuringConfiguration : IEntityDestructuringConfiguration<UserPassportRequest>
{
public void Configure(EntityDestructuringBuilder<UserPassportRequest> builder)
{
builder.Property(a => a.Series)
.Mask();
builder.Property(a => a.Number)
.Ignore()
.ApplyWhenNull();
}
}
builder.Entity<UserRegisterRequest>(e =>
{
e.InnerEntity(o => o.Passport, new UserPassportRequestDestructuringConfiguration())
.WithAlias("user_passport")
.ApplyWhen(e => !string.IsNullOrWhiteSpace(e.Email));
});
7. Global options.
- IgnoreNullProperties - Indicating whether properties with null values should be ignored during destructuring. The default is
false
. - ExcludeTypeTag - Indicating whether the
$type
tag should be excluded from the destructured output. The default isfalse
.
var cfg = new LoggerConfiguration()
.Destructure.WithFluentDestructuringPolicy<ApplicationFluentDestructuringPolicy>(e =>
{
e.IgnoreNullProperties = true;
e.ExcludeTypeTag = true;
})
...
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Serilog (>= 4.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.