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 logs directory (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

  1. Logger builder: New-KrLogger starts a builder; set minimum to Debug.
  2. Sinks: add a rolling hourly file sink (logs/sample<timestamp>.log) and the console sink.
  3. Register: Register-KrLogger registers the logger so it can be referenced. Optionally add -SetAsDefault to make Kestrun use it as the server logger (or pass -Logger/-LoggerName to New-KrServer).
  4. Server & listener: standard setup (server + loopback listener on port 5000).
  5. Runtime: add PowerShell runtime so script block routes execute.
  6. Apply config: call Enable-KrConfiguration to commit the listener/runtime.
  7. Initial event: write an informational log confirming server creation.
  8. Routes:
    • /hello-powershell writes a debug log then returns text.
    • /hello-csharp uses the same logger (closure variable myLogger) inside a C# code route.
  9. Start: Start-KrServer begins 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 Day for 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


Previous / Next

Go back to Shared Variables or continue to Multiple Loggers & Levels. Guide: Logging (Concepts)