This package makes it possible to manipulate how objects are logged to Serilog using attributes.
Install from NuGet:
Install-Package Destructurama.AttributedModify logger configuration:
var log = new LoggerConfiguration()
.Destructure.UsingAttributes()
...Apply the LogWithName attribute:
public class PersonalData
{
[LogWithName("FullName")]
public string Name { get; set; }
}Apply the NotLogged attribute:
public class LoginCommand
{
public string Username { get; set; }
[NotLogged]
public string Password { get; set; }
}When the object is passed using {@...} syntax the attributes will be consulted.
var command = new LoginCommand { Username = "logged", Password = "not logged" };
log.Information("Logging in {@Command}", command);To prevent destructuring of a type or property at all, apply the [LogAsScalar] attribute.
Apply the LogMasked attribute with various settings:
- Text: If set, the property value will be set to this text.
- ShowFirst: Shows the first x characters in the property value.
- ShowLast: Shows the last x characters in the property value.
- PreserveLength: If set, it will swap out each character with the default value. Note that this property will be ignored if Text has been set to custom value.
Note that masking also works for properties of type IEnumerable<string> or derived from it, for example, string[] or List<string>.
public class CustomizedMaskedLogs
{
/// <summary>
/// 123456789 results in "***"
/// </summary>
[LogMasked]
public string DefaultMasked { get; set; }
/// <summary>
/// [123456789,123456789,123456789] results in [***,***,***]
/// </summary>
[LogMasked]
public string[] DefaultMaskedArray { get; set; }
/// <summary>
/// 123456789 results in "*********"
/// </summary>
[LogMasked(PreserveLength = true)]
public string DefaultMaskedPreserved { get; set; }
/// <summary>
/// 123456789 results in "#"
/// </summary>
[LogMasked(Text = "_REMOVED_")]
public string CustomMasked { get; set; }
/// <summary>
/// 123456789 results in "#########"
/// </summary>
[LogMasked(Text = "#", PreserveLength = true)]
public string CustomMaskedPreservedLength { get; set; }
/// <summary>
/// 123456789 results in "123******"
/// </summary>
[LogMasked(ShowFirst = 3)]
public string ShowFirstThreeThenDefaultMasked { get; set; }
/// <summary>
/// 123456789 results in "123******"
/// </summary>
[LogMasked(ShowFirst = 3, PreserveLength = true)]
public string ShowFirstThreeThenDefaultMaskedPreservedLength { get; set; }
/// <summary>
/// 123456789 results in "***789"
/// </summary>
[LogMasked(ShowLast = 3)]
public string ShowLastThreeThenDefaultMasked { get; set; }
/// <summary>
/// 123456789 results in "******789"
/// </summary>
[LogMasked(ShowLast = 3, PreserveLength = true)]
public string ShowLastThreeThenDefaultMaskedPreservedLength { get; set; }
/// <summary>
/// 123456789 results in "123REMOVED"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowFirst = 3)]
public string ShowFirstThreeThenCustomMask { get; set; }
/// <summary>
/// 123456789 results in "123_REMOVED_"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowFirst = 3, PreserveLength = true)]
public string ShowFirstThreeThenCustomMaskPreservedLengthIgnored { get; set; }
/// <summary>
/// 123456789 results in "_REMOVED_789"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowLast = 3)]
public string ShowLastThreeThenCustomMask { get; set; }
/// <summary>
/// 123456789 results in "_REMOVED_789"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowLast = 3, PreserveLength = true)]
public string ShowLastThreeThenCustomMaskPreservedLengthIgnored { get; set; }
/// <summary>
/// 123456789 results in "123***789"
/// </summary>
[LogMasked(ShowFirst = 3, ShowLast = 3)]
public string ShowFirstAndLastThreeAndDefaultMaskInTheMiddle { get; set; }
/// <summary>
/// 123456789 results in "123***789"
/// </summary>
[LogMasked(ShowFirst = 3, ShowLast = 3, PreserveLength = true)]
public string ShowFirstAndLastThreeAndDefaultMaskInTheMiddlePreservedLength { get; set; }
/// <summary>
/// 123456789 results in "123_REMOVED_789"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowFirst = 3, ShowLast = 3)]
public string ShowFirstAndLastThreeAndCustomMaskInTheMiddle { get; set; }
/// <summary>
/// 123456789 results in "123_REMOVED_789". PreserveLength is ignored"
/// </summary>
[LogMasked(Text = "_REMOVED_", ShowFirst = 3, ShowLast = 3, PreserveLength = true)]
public string ShowFirstAndLastThreeAndCustomMaskInTheMiddlePreservedLengthIgnored { get; set; }
}Apply the LogReplaced attribute on a string to apply a RegEx replacement during Logging.
This is applicable in scenarios which a string contains both Sensitive and Non-Sensitive information. An example of this could be a string such as "Sensitive|NonSensitive". Then apply the attribute like the following snippet:
[LogReplaced(@"([a-zA-Z0-9]+)\|([a-zA-Z0-9]+)", "***|$2")]
public property Information { get; set; }
// Will log: "***|NonSensitive"LogReplaced attribute is available with the following constructor:
LogReplaced(string pattern, string replacement)Constructor arguments:
- pattern: The pattern that should be applied on value.
- replacement: The string that will be applied by RegEx.
Available properties:
- Options: The RegexOptions that will be applied. Defaults to RegexOptions.None
- Timeout: A time-out interval to evaluate regular expression. Defaults to Regex.InfiniteMatchTimeout
public class WithRegex
{
const string RegexWithVerticalBars = @"([a-zA-Z0-9]+)\|([a-zA-Z0-9]+)\|([a-zA-Z0-9]+)";
/// <summary>
/// 123|456|789 results in "***|456|789"
/// </summary>
[LogReplaced(RegexWithVerticalBars, "***|$2|$3")]
public string RegexReplaceFirst { get; set; }
/// <summary>
/// 123|456|789 results in "123|***|789"
/// </summary>
[LogReplaced(RegexWithVerticalBars, "$1|***|$3")]
public string RegexReplaceSecond { get; set; }
}