重新加载 Serilog JSON .NET Core 2.1 中更改的配置

Reload Serilog JSON Configuration on changes in .NET Core 2.1

我目前正在开发 ASP.NET Core 2.1 应用程序,我使用 Serilog 进行日志记录。我想在运行时为我的 Serilog 实现重新加载应用程序设置文件。

我的目标是在运行时更改日志级别,例如我写入 minimumLevel Debug 而不是 Information 并保存文件。我想触发设置的实时重新加载。我的 appsettings.json 看起来像这样:

{
  "serilog": {
    "using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console" ],
    "minimumLevel": "Information",
    "writeTo": [
      {
        "name": "File",
        "args": {
          "fileSizeLimitBytes": 256000000,
          "retainedFileCountLimit": 62,
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
      },
      {
        "name": "Console",
      }
    ]
  }
}

在我的 Program.cs 中,我使用标志 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);
    }
}

我的启动看起来像这样:

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;

        // ...
    }
}

你知道如何在运行时重新加载 Serilog 配置吗,如果我以某种方式更改了 appsettings.json。 => appsettings.json.

的实时重新加载

谢谢!!

您可以使用 LoggingLevelSwitch 更改日志级别。你可以阅读它 here

您可以使用IOptionsSnapshot<>界面重新加载配置。您可以阅读更多相关信息 here

您可以使用Serilog.Settings.Reloader

我没有 ASP 示例,但在控制台程序上你可以这样做:

        // 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");
        }

澄清一下,单例“SwitchableLogger.Instance”仅用于演示,也可以创建一个新实例“new SwitchableLogger()”。

当前的 Serilog 实现 (2.9.0) 无法完全重新加载设置。要在不引入额外依赖项的情况下解决此问题,请避免创建静态记录器并遵循此处提供的示例: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));
    }
}

或者您可以简单地使用 Logging.Serilog 库,它为此提供实用函数。