Simple Logging
Introduce structured logging early: create a named logger with console + rolling file sinks, register it as the default, then write events from both PowerShell and embedded C# routes.
Prerequisites: see Introduction. Ensure you have a
logsdirectory (created on demand by the File sink).
Need more depth or advanced options? See the Logging guide for concepts, C#/PowerShell APIs, hot reload, enrichment, and sinks.
Full source
File: pwsh/tutorial/examples/5.1-Simple-Logging.ps1
<#
Sample Kestrun Server demonstrating basic logging.
Creates a logger with file + console sinks, registers it by name, then maps simple routes.
Use -SetAsDefault on Register-KrLogger or pass -Logger/-LoggerName to New-KrServer to enable framework logs.
FileName: 5.1-Simple-Logging.ps1
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
$myLogger = New-KrLogger |
Set-KrLoggerLevel -Value Debug |
Add-KrSinkFile -Path '.\logs\sample.log' -RollingInterval Hour |
Add-KrSinkConsole |
Register-KrLogger -Name 'myLogger' -PassThru
# Create a new Kestrun server
New-KrServer -Name "Simple Server"
# Add a listener using provided parameters
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
# Add the PowerShell runtime
Write-KrLog -Level Information -Logger $myLogger -Message "Kestrun server created and listener added."
# Enable Kestrun configuration
Enable-KrConfiguration
# Map the route with PowerShell
Add-KrMapRoute -Verbs Get -Path "/hello-powershell" -ScriptBlock {
$response = "Hello, World!"
Write-KrLog -Logger $myLogger -Level Debug -Message "Handling /hello-powershell response {response}" -Values $response
Write-KrTextResponse -InputObject $response -StatusCode 200
}
# Map the route with CSharp
Add-KrMapRoute -Verbs Get -Path "/hello-csharp" -Code @"
var response = "Hello, World!";
// Log the response using the provided logger instance 'myLogger' (shared from PowerShell)
myLogger.Debug("Handling /hello-csharp response {response}", response);
Context.Response.WriteTextResponse( response, 200);
"@ -Language CSharp
# Start the server asynchronously
Start-KrServer
# Clean up and close the logger when the server stops
Close-KrLogger -Logger $myLogger
Step-by-step
- Logger builder:
New-KrLoggerstarts a builder; set minimum toDebug. - Sinks: add a rolling hourly file sink (
logs/sample<timestamp>.log) and the console sink. - Register:
Register-KrLoggerregisters the logger so it can be referenced. Optionally add-SetAsDefaultto make Kestrun use it as the server logger (or pass-Logger/-LoggerNametoNew-KrServer). - Server & listener: standard setup (server + loopback listener on port 5000).
- Runtime: add PowerShell runtime so script block routes execute.
- Apply config: call
Enable-KrConfigurationto commit the listener/runtime. - Initial event: write an informational log confirming server creation.
- Routes:
/hello-powershellwrites a debug log then returns text./hello-csharpuses the same logger (closure variablemyLogger) inside a C# code route.
- Start:
Start-KrServerbegins processing requests asynchronously.
Kestrun server logs vs your logs
Kestrun’s internal server logs use a default sink called “SilentLogger,” so you won’t see framework logs unless you configure a server logger. Your own logs written with Write-KrLog (or using the myLogger instance) are independent of this.
To enable Kestrun’s server logs, choose one of the following options:
1) Set your logger as the default
$myLogger = New-KrLogger |
Set-KrLoggerLevel -Value Debug |
Add-KrSinkFile -Path '.\logs\sample.log' -RollingInterval Hour |
Add-KrSinkConsole |
Register-KrLogger -Name 'myLogger' -PassThru -SetAsDefault
This instructs Kestrun to use myLogger instead of the default SilentLogger.
1) Pass the logger to the server
$myLogger = New-KrLogger |
Set-KrLoggerLevel -Value Debug |
Add-KrSinkFile -Path '.\logs\sample.log' -RollingInterval Hour |
Add-KrSinkConsole |
Register-KrLogger -Name 'myLogger' -PassThru
New-KrServer -Name "Simple Server" -Logger $myLogger
# Or using the logger name
# New-KrServer -Name "Simple Server" -LoggerName 'myLogger'
Either approach enables framework logs in addition to your Write-KrLog events.
Try it
Save the sample locally so the log file is easy to find. Copy the contents of pwsh/tutorial/examples/5.1-Simple-Logging.ps1 into a new file in an empty working folder (for example, simple-logging.ps1), then run:
# From your working folder
pwsh .\simple-logging.ps1
curl http://127.0.0.1:5000/hello-powershell
curl http://127.0.0.1:5000/hello-csharp
Get-Content .\logs\sample*.log -Tail 20
Expected: console shows events; logs/sample<timestamp>.log contains recent entries.
Cleanup (closing the logger)
File sinks keep a handle open while the logger is alive. When you stop the server or script, close the logger to flush buffers and release file handles; otherwise you may not be able to rename/delete the log file until the process exits.
You can also close all active loggers by calling Close-KrLogger with no parameters.
# Close a specific logger instance
Close-KrLogger -Logger $myLogger
# Or close the default logger (if configured as default)
# Close-KrLogger -DefaultLogger
# Or close by name
# Close-KrLogger -LoggerName 'myLogger'
# Or close all active loggers
# Close-KrLogger
Customizing
- Change rolling period:
-RollingInterval Dayfor daily splits. - Filter noisier categories later (future chapter) with per-logger overrides.
- Add properties: insert
Add-KrEnrichProperty -Name 'App' -Value 'Sample'before registering. - Add another sink: e.g.,
Add-KrSinkSeq -ServerUrl 'http://localhost:5341'(if you have Seq running).
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No file created | Directory missing or no events yet | Trigger a request; ensure path is writable |
| Missing debug lines | Minimum level too high | Use Set-KrLoggerLevel -Value Debug |
| Logger variable not found in C# route | Name mismatch | Ensure variable name matches (myLogger) |
| Duplicate console lines | Multiple loggers set as default | Only set one default or adjust configuration |
| Cannot delete/rename log file | Logger still open / file handle | Run Close-KrLogger; let the process exit |
References
- New-KrLogger
- Set-KrLoggerLevel
- Add-KrSinkFile
- Add-KrSinkConsole
- Register-KrLogger
- Write-KrLog
- Close-KrLogger
- New-KrServer
- Add-KrMapRoute
- Start-KrServer
Previous / Next
Go back to Shared Variables or continue to Multiple Loggers & Levels. Guide: Logging (Concepts)