I'm currently working on a ASP.NET Core 2.1 application and I use Serilog for logging. I want to reload the application settings file for my Serilog implementation during runtime.
My goal is to change the log level at runtime eg I write into minimumLevel Debug instead of Information and I save the file. I want to trigger a live reload of the settings. My appsettings.json
looks like this:
{
"serilog": {
"using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console" ],
"minimumLevel": "Information",
"writeTo": [
{
"name": "File",
"args": {
"fileSizeLimitBytes": 256000000,
"retainedFileCountLimit": 62,
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
},
{
"name": "Console",
}
]
}
}
In my Program.cs I load the settings with the flag reloadOnChange: true
.
public class Program
{
public static readonly ServiceSettings Settings = new ServiceSettings();
public static void Main(string[] args)
{
//...
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(Path.GetFullPath(CoreServiceBase.Instance.ConfigFilePath), optional: false, reloadOnChange: true)
.AddCommandLine(args)
.Build();
config.Bind(Settings);
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog((hostingContext, loggerConfiguration) =>
loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
.UseConfiguration(config);
}
}
My Startup looks like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Custom application logging
ApplicationLogging.LoggerFactory = loggerFactory;
// ...
}
}
Do you know how to reload the Serilog configuration during runtime, if I somehow the appsettings.json gets changed. => Live reload for the appsettings.json.
Thank you!!
You can use Serilog.Settings.Reloader
I don't have ASP example, but on console program you can do this:
// Service collection
IServiceCollection serviceCollection = new ServiceCollection()
.AddLogging(loggingBuilder =>
loggingBuilder
.AddSerilog(SwitchableLogger.Instance, true)
.AddSerilogConfigurationLoader(configuration, SwitchableLogger.Instance)
);
// Services
using (var services = serviceCollection.BuildServiceProvider())
{
// Create logger
Microsoft.Extensions.Logging.ILogger logger = services.GetService<Microsoft.Extensions.Logging.ILogger<Program>>();
// Write
logger.LogInformation("Hello World");
// Modify config
config.Set("Serilog:WriteTo:0:Args:OutputTemplate", "[{SourceContext}] {Message:lj}{NewLine}{Exception}");
configuration.Reload();
// Write with the previous logger instance, but with different settings
logger.LogInformation("Hello world again");
}
The current Serilog implementation (2.9.0) is such that it is unable to fully reload settings. To work around this issue without introducing additional dependencies, avoid creating static loggers and follow the example provided here: https://github.com/akovac35/Logging/blob/v1.0.4/src/com.github.akovac35.Logging.Serilog/SerilogHelper.cs
public static void CreateLogger()
{
CreateLogger(configure =>
{
configure.AddJsonFile("serilog.json", optional: false, reloadOnChange: true);
});
}
public static void CreateLogger(Action<IConfigurationBuilder> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
UpdateLogger(configure);
}
public static void UpdateLogger(Action<IConfigurationBuilder> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
// The following pattern fires the reload token only once per settings change
var configurationBuilder = new ConfigurationBuilder();
try
{
configure(configurationBuilder);
IConfiguration configuration = configurationBuilder.Build();
// Release previous callback - will be released only if this line is reached, allowing for another reload
_changeCallback?.Dispose();
_changeCallback = null;
// .NET will not trigger a reload for invalid config file format, so reaching this line signals Json is OK
_changeCallback = configuration.GetReloadToken().RegisterChangeCallback(state =>
{
UpdateLogger(configure);
}, null);
// Reading configuration will fail for invalid properties, that is why reload registration must happen
// before this line or subsequent file updates may not be detected
global::Serilog.ILogger newLogger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext()
.CreateLogger();
Log.Logger = newLogger;
GetLogger().Here(l => l.LogInformation("Updated logger: {@configuration}", configuration));
}
catch (Exception ex)
{
GetLogger().Here(l => l.LogError(ex, ex.Message));
}
}
Or you can simply use the Logging.Serilog library which provides utility functions for just that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.