Hot Reload (Update Logger)
Change logging behavior without restarting the server. Two approaches:
- Dynamic minimum level: configure a logger with a dynamic level switch and adjust it at runtime.
- Re-register: create a new configuration and register it under the same name to change sinks/properties/level.
Tip: Using a dynamic level via Set-KrLoggerLevel -Dynamic <Level> creates an internal switch you can read/change by logger name with Get-KrLevelSwitch/Set-KrLevelSwitch.
Full source
File: pwsh/tutorial/examples/5.6-Hot-Reload.ps1
<#
Sample demonstrating hot reload:
- Dynamically change minimum level with a LoggingLevelSwitch
- Re-register a logger with the same name to change sinks/properties
FileName: 5.6-Hot-Reload.ps1
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
# Dynamic level switch logger
New-KrLogger |
Set-KrLoggerLevel -Dynamic Debug |
Add-KrSinkConsole |
Add-KrSinkFile -Path '.\logs\hot-reload.log' -RollingInterval Hour |
Register-KrLogger -Name 'app' -PassThru
# Default logger for server events
New-KrLogger |
Set-KrLoggerLevel -Value Debug |
Add-KrSinkConsole |
Register-KrLogger -Name 'Default'
New-KrServer -Name "Hot Reload" -LoggerName 'Default'
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
Enable-KrConfiguration
# Writes both Debug and Information; visibility depends on level switch
Add-KrMapRoute -Verbs Get -Path "/log" -ScriptBlock {
Write-KrLog -LoggerName 'app' -Level Debug -Message "Debug event"
Write-KrLog -LoggerName 'app' -Level Information -Message "Information event"
Write-KrLog -LoggerName 'app' -Level Warning -Message "Warning event"
Write-KrLog -LoggerName 'app' -Level Error -Message "Error event"
Write-KrLog -LoggerName 'app' -Level Fatal -Message "Fatal event"
Write-KrTextResponse -InputObject "ok - $(Get-KrLoggerLevelSwitch -LoggerName 'app')" -StatusCode 200
}
# Change minimum level via route: /level/{level} e.g., /level/Debug or /level/Warning
Add-KrMapRoute -Verbs Get -Path "/level/{level}" -ScriptBlock {
$lvl = Get-KrRequestRouteParam -Name 'level'
$parsed = [Serilog.Events.LogEventLevel]::Information
if ([Enum]::TryParse([Serilog.Events.LogEventLevel], $lvl, $true, [ref]$parsed)) {
Write-KrLog -Level Debug -LoggerName 'Default' -Message "Changing level to {lvl}" -Values $lvl
Set-KrLoggerLevelSwitch -LoggerName 'app' -MinimumLevel $parsed | Out-Null
Write-KrLog -LoggerName 'app' -Level Information -Message "Level switch set to {level}" -Values $lvl
Write-KrTextResponse -InputObject "level=$lvl" -StatusCode 200
} else {
Write-KrLog -LoggerName 'app' -Level Warning -Message "Invalid level value {level}" -Values $lvl
Write-KrTextResponse -InputObject "invalid level '$lvl'" -StatusCode 400
}
}
# Reconfigure 'app' logger at runtime: add a property and tighten minimum level
Add-KrMapRoute -Verbs Post -Path "/reconfigure" -ScriptBlock {
New-KrLogger |
Set-KrLoggerLevel -Value Warning |
Add-KrEnrichProperty -Name 'Reconfigured' -Value $true |
Add-KrSinkConsole |
Add-KrSinkFile -Path '.\logs\hot-reload.log' -RollingInterval Hour |
Register-KrLogger -Name 'app'
Write-KrTextResponse -InputObject "reconfigured" -StatusCode 200
}
# Start the server
Start-KrServer
# Clean up and close the logger when the server stops
Close-KrLogger
Step-by-step
- Configure a logger with a dynamic minimum level using
Set-KrLoggerLevel -Dynamic Debug, add sinks (console + file), and register it asapp. - Route
/logwrites events at multiple levels so you can see the current threshold in effect; the response echoes the level viaGet-KrLevelSwitch -LoggerName 'app'. - Route
/level/{level}changes the level at runtime (Debug, Information, Warning, Error, Fatal) usingSet-KrLevelSwitch -LoggerName 'app' -MinimumLevel .... - Route
/reconfigurere-registers a new configuration under the same nameapp(adds aReconfigured=trueproperty and sets minimum to Warning), replacing the prior logger safely.
Try it
Save the sample locally so it’s easy to run. Copy the contents of pwsh/tutorial/examples/5.6-Hot-Reload.ps1 into a new file in an empty working folder (for example, hot-reload.ps1), then run:
Curl examples:
curl http://127.0.0.1:5000/log
curl http://127.0.0.1:5000/level/Debug
curl http://127.0.0.1:5000/log
curl -X POST http://127.0.0.1:5000/reconfigure
curl http://127.0.0.1:5000/log
Invoke-WebRequest examples:
Invoke-RestMethod -Uri 'http://127.0.0.1:5000/log' -Method Get
Invoke-RestMethod -Uri 'http://127.0.0.1:5000/level/Debug' -Method Get
Invoke-RestMethod -Uri 'http://127.0.0.1:5000/log' -Method Get
Invoke-RestMethod -Uri 'http://127.0.0.1:5000/reconfigure' -Method Post
Invoke-RestMethod -Uri 'http://127.0.0.1:5000/log' -Method Get
Expected: Debug becomes visible after /level/Debug; after /reconfigure, only Warning+ are written and the Reconfigured=true property appears.
Notes
- Dynamic level:
Set-KrLoggerLevel -Dynamic <Level>attaches a per-logger switch that you can later inspect or change by name usingGet-KrLevelSwitch/Set-KrLevelSwitch. - Per-sink control: sinks can still have their own level switches if you need different thresholds per sink.
- Re-registering a logger with the same name disposes the previous instance (see LoggerManager).
- To update the Kestrun framework logger, re-register the default logger name or set
-SetAsDefault.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Level not changing | Wrong enum casing/route value | Use Debug/Information/Warning/Error/Fatal |
| Still seeing Debug logs | Logger not configured as dynamic | Use Set-KrLoggerLevel -Dynamic <Level> initially |
| No change after POST | Logger name mismatch | Re-register/change using the exact same name (app) |
References
- Get-KrLevelSwitch
- Set-KrLevelSwitch
- New-KrLogger
- Set-KrLoggerLevel
- Add-KrEnrichProperty
- Add-KrSinkFile
- Add-KrSinkConsole
- Register-KrLogger
- Write-KrLog
- New-KrServer
- Add-KrMapRoute
- Start-KrServer
- Close-KrLogger
Previous / Next
Go back to Sinks (HTTP/EventLog/Syslog) or continue to PowerShell vs C# Interop. Guide: Logging (Concepts)