I am building a Windows 10 app (UWP) and implementing logging using Serilog.
Shown below is an appsettings.json file with which I configure Serilog to write to a Rolling File sink (amongst other sinks).
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "#{LogFilePath}log-{Date}.txt",
"fileSizeLimitBytes": "3000",
"retainedFileCountLimit": "2"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "Sample"
}
}
}
I then call the following code:
var configuration = new ConfigurationBuilder()
.AddJsonFile(sampleFile.Path)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
However, I need to be able to change the pathFormat attribute at runtime, so that the log is written to the application’s “LocalState” folder.
Q. Does Serilog support reading from configuration and then overriding particularly arguments at runtime?
My current workaround is to use a token in the JSON called “#{LogFilePath}” and replace this in the file at runtime.
I’ve found the following, but can’t use environment variables in my case: Specify directory for Serilog rolling file path
According to Serilog, you would need to use file logging – as it seems, RollingFile might be going away soon.
Important note: the rolling functionality in this sink has been improved and merged into the Serilog.Sinks.File package. RollingFile will be maintained for the foreseeable future, however File is recommended for new applications.
Here is a straightforward way of using a File Sink:
appsettings.json
{
"Serilog": {
"MinimumLevel": "Verbose",
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "Logs\\log.txt",
"fileSizeLimitBytes": 3000,
"buffered": false,
"rollOnFileSizeLimit": true,
"retainedFileCountLimit": 3,
"rollingInterval": "Hour"
}
}
]
}
}
Program.cs
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
var loggerConfig = new LoggerConfiguration().ReadFrom.Configuration(configuration);
var logger = loggerConfig.CreateLogger();
Last year there seemed to be some enthusiasm to specify some default configuration then have it overridden by the config files, in the Serilog team & the community. They created an experimental repository, and a Nuget Package - not sure where that stands today.
But I think there is a work around – below is one of the ways how you could implement this in a little bit cleaner way, than your "token" approach.
appsettings.json
{
"FileLogger": {
//"path": "Logs\\log.txt",
}
}
This way, if you specify the value in the config file, it would take precedence. Else, your custom format would be used. Having defaults specified in the application and then using configurations to override them (instead the other way around) is a better design in my opinion.
Program.cs
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();
var customLogFileFormat = configuration["FileLogger:path"] ?? $"Logs\\log_{DateTime.Now.ToString("MMddyyyy_hhmmsstt")}log.txt";
var loggerConfig = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File(
path: customLogFileFormat,
fileSizeLimitBytes: 3000,
buffered: true,
rollOnFileSizeLimit: true,
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 5);
If you are interested about more details about my test app, following sequence of PoweShell commands might help:
mkdir SerilogApp
cd SerilogApp
dotnet new console -f netcoreapp2.2 -n SerilogApp -o SerilogApp
dotnet new sln -n SerilogApp.sln
dotnet sln add .\SerilogApp\SerilogApp.csproj
dotnet add .\SerilogApp\SerilogApp.csproj package Microsoft.Extensions.Configuration -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Microsoft.Extensions.Configuration.FileExtensions -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Microsoft.Extensions.Configuration.Json -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Serilog -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Serilog.Settings.Configuration -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Serilog.Sinks.Console -f netcoreapp2.2
dotnet add .\SerilogApp\SerilogApp.csproj package Serilog.Sinks.File -f netcoreapp2.2 -v 4.0.0
cd .\SerilogApp
echo $null >> appsettings.json