Enrichment & Correlation IDs
Attach useful properties (enrichment) to your log events and add a per-request correlation ID so you can trace a single request across multiple log lines and even across languages (PowerShell and C# routes).
See the Logging guide for in-depth enrichment options and Serilog helpers.
Full source
File: pwsh/tutorial/examples/5.3-Enrichment-Correlation-IDs.ps1
<#
Sample demonstrating enrichment and correlation IDs.
- Adds a global property 'App' to the logger
- For each request, generates a CorrelationId and attaches it to log events
FileName: 5.3-Enrichment-Correlation-IDs.ps1
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
$appLogger = New-KrLogger |
Set-KrLoggerLevel -Value Debug |
Add-KrEnrichProperty -Name 'App' -Value 'LoggingSamples' |
Add-KrEnrichFromLogContext |
Add-KrSinkConsole -OutputTemplate "[{App} {Timestamp:HH:mm:ss} {Level:u3} {CorrelationId}] {Message:lj}{NewLine}{Exception}" |
Add-KrSinkFile -Path '.\logs\enrichment.log' -RollingInterval Hour -OutputTemplate "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] ({App}) {CorrelationId} {Message:lj}{NewLine}{Exception}" |
Register-KrLogger -Name 'app' -PassThru
New-KrServer -Name "Enrichment & Correlation IDs"
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
Enable-KrConfiguration
# PowerShell route that adds a correlation id to each log event as a property
Add-KrMapRoute -Verbs Get -Path "/ps-correlation" -ScriptBlock {
$corr = [guid]::NewGuid().ToString('N')
$scope = Push-KrLogContextProperty -Name CorrelationId -Value $corr
try {
Write-KrLog -Logger $appLogger -Level Information -Message "Handling /ps-correlation"
Write-KrLog -Logger $appLogger -Level Debug -Message "Processing details"
Write-KrTextResponse -InputObject "ps-correlation: $corr" -StatusCode 200
} finally {
$scope.Dispose()
}
}
# C# route demonstrating per-request context using ForContext
Add-KrMapRoute -Verbs Get -Path "/csharp-correlation" -Code @"
var correlationId = Guid.NewGuid().ToString("N");
var log = appLogger.ForContext("CorrelationId", correlationId);
log.Information("Handling /csharp-correlation");
log.Debug("Processing details");
Context.Response.WriteTextResponse($"csharp-correlation: {correlationId}", 200);
"@ -Language CSharp
# Start the server
Start-KrServer
# Clean up and close the logger when the server stops
Close-KrLogger -Logger $appLogger
Step-by-step
- Build a logger with minimum
Debug, add a global propertyApp, enable FromLogContext, and sinks (console + file). - Standard server, listener, PowerShell runtime; then apply config with
Enable-KrConfiguration. - PowerShell route
/ps-correlation:- Generate a correlation ID per request (
[guid]::NewGuid().ToString('N')). - Push to LogContext using
Push-KrLogContextProperty -Name CorrelationId -Value $corrfor the scope of the request.
- Generate a correlation ID per request (
- C# route
/csharp-correlation:- Use
appLogger.ForContext("CorrelationId", id)to enrich subsequent events.
- Use
- Start with
Start-KrServer.
Try it
Save the sample locally so the log file is easy to find. Copy the contents of pwsh/tutorial/examples/5.3-Enrichment-Correlation-IDs.ps1 into a new file in an empty working folder (for example, enrichment.ps1), then run:
# From your working folder
pwsh .\enrichment.ps1
curl http://127.0.0.1:5000/ps-correlation
curl http://127.0.0.1:5000/csharp-correlation
Get-Content .\logs\enrichment.log -Tail 40
Expected: Each request shows a unique CorrelationId on all events for that request.
Note:
Custom properties like CorrelationId and App must be referenced in the sink OutputTemplate to be displayed. The example sets console to [{App} {Timestamp:HH:mm:ss} {Level:u3} {CorrelationId}] {Message} and file to {Timestamp} [{Level}] ({App}) {CorrelationId} {Message}.
Customizing
- Add more properties globally with
Add-KrEnrichProperty(e.g.,Environment,Version). - Use Serilog enrichers (machine name, thread id, etc.).
- Consider setting a request header (e.g.,
X-Correlation-Id) and reusing it if present. - To enable Kestrun framework logs, set your logger as default or pass it via
New-KrServer.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No CorrelationId appears in events | Property name mismatch | Ensure key is exactly CorrelationId |
| Different IDs in one request’s lines | New GUID generated per log call | Generate once per request and reuse |
| No logs written | Minimum level too high / bad path | Lower minimum; verify file path and permissions |
| Cannot delete/rename log file | Logger still open / file handle | Run Close-KrLogger; let the process exit |
References
- New-KrLogger
- Set-KrLoggerLevel
- Add-KrEnrichFromLogContext
- Push-KrLogContextProperty
- Add-KrEnrichProperty
- Add-KrSinkFile
- Add-KrSinkConsole
- Register-KrLogger
- Write-KrLog
- Close-KrLogger
- New-KrServer
- Add-KrMapRoute
- Start-KrServer
Previous / Next
Go back to Multiple Loggers & Levels or continue to Sinks (Console/File/JSON). Guide: Logging (Concepts)