Serilog
Tayra integrates with Serilog to automatically redact [PersonalData]-annotated properties when objects are logged via Serilog's {@Object} destructuring syntax. This prevents PII from leaking into log files, consoles, or centralized logging platforms.
Prerequisites
Tayra.Serilog requires Serilog 4.x or later.
Install
dotnet add package Tayra.SerilogInstall-Package Tayra.SerilogSetup
Standalone (no DI)
var metadataCache = new PersonalDataMetadataCache();
Log.Logger = new LoggerConfiguration()
.Destructure.WithTayra(metadataCache)
.WriteTo.Console()
.CreateLogger();With Dependency Injection
services.AddTayra(opts => opts.LicenseKey = licenseKey); // defaults to InMemoryKeyStore; use PostgreSQL, Vault, etc. in production
services.AddTayraSerilog(opts =>
{
opts.UsePartialRedaction = true;
});How It Works
When Serilog encounters {@Object} in a log message template, it calls Tayra's TayraDestructuringPolicy. The policy inspects the object's type metadata and redacts any properties annotated with Tayra PII attributes:
public class User
{
[DataSubjectId]
public string UserId { get; set; }
[PersonalData]
public string Name { get; set; }
[PersonalData]
public string Email { get; set; }
public string Role { get; set; } // Not PII
}
var user = new User
{
UserId = "u1", Name = "Alice",
Email = "alice@test.com", Role = "Admin"
};
Log.Information("User: {@User}", user);Without Tayra:
User: {"UserId": "u1", "Name": "Alice", "Email": "alice@test.com", "Role": "Admin"}With Tayra:
User: {"UserId": "u1", "Name": "[REDACTED]", "Email": "[REDACTED]", "Role": "Admin"}Objects without any PII attributes are passed through to Serilog's default destructuring unchanged — zero overhead for non-PII types.
Options
services.AddTayraSerilog(opts =>
{
opts.RedactedPlaceholder = "[REDACTED]"; // default
opts.UsePartialRedaction = true;
opts.IncludeFieldKindHint = true;
opts.RedactDataSubjectId = false; // default
});| Property | Type | Default | Description |
|---|---|---|---|
RedactedPlaceholder | string | "[REDACTED]" | The placeholder string for redacted values |
UsePartialRedaction | bool | false | Use the field's masking strategy to produce partially-masked values (e.g. "Al***") |
IncludeFieldKindHint | bool | false | Append the field name to the placeholder (e.g. "[REDACTED:Email]") |
RedactDataSubjectId | bool | false | Also redact properties marked with [DataSubjectId] |
Supported Field Kinds
The policy handles all Tayra field kinds:
| Attribute | Behavior |
|---|---|
[PersonalData] | Replaced with placeholder (or partial redaction / custom MaskValue) |
[PersonalData] on List<string> | Each element redacted, collection length preserved |
[DeepPersonalData] | Recursively destructured with PII scrubbing |
[DeepPersonalData] on collections | Each element recursively destructured |
[SerializedPersonalData] | Replaced with placeholder |
[DataSubjectId] | Passed through by default; redacted when RedactDataSubjectId = true |
Partial Redaction
When UsePartialRedaction is enabled, fields with a redaction strategy produce masked values instead of the full placeholder:
public class Customer
{
[PersonalData(Masking = MaskingStrategies.MaskAfter, MaskingParameter = 2)]
public string Name { get; set; }
[PersonalData(Masking = MaskingStrategies.MaskEmailDomain)]
public string Email { get; set; }
}
// Logs: {"Name": "Al***", "Email": "alice@****.***"}Custom MaskValue
Fields with an explicit MaskValue always use that mask value, regardless of other options:
[PersonalData(MaskValue = "***NAME***")]
public string Name { get; set; }
// Logs: {"Name": "***NAME***"}Safety
- Depth limit: Recursive
[DeepPersonalData]traversal is capped at 10 levels to prevent stack overflows - Property getter errors: If a property getter throws, the field is logged as
nullrather than crashing the pipeline - Null values: Null PII properties are logged as
null, not the placeholder string
See Also
- Getting Started -- End-to-end encryption tutorial
- ASP.NET Core Integration -- Response body PII redaction middleware
- Partial Redaction -- Configuring partial redaction modes
- Attributes -- Full attribute reference
