在Serilog中动态更改日志文件路径吗?

时间:2020-05-19 11:18:42

标签: serilog

我具有动态更改日志文件路径的功能。但是当我更改在Consul中可配置的路径时,它将在两个位置(即旧路径和新路径)写入部分日志。更改日志文件路径应该可以正常工作,而无需重新启动任何服务。我们该如何存档?

我们正在如下记录日志文件:

.WriteTo.File(logFolderFullPath + "\\" + applicationName + "_.txt",
                         LogEventLevel.Error, shared: true,
                         fileSizeLimitBytes: fileSizeLimitBytes, rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Day,
                          outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] [{MachineName}] [{SourceContext}] {RequestId} {CorrelationId} {Message}{NewLine}{Exception}{properties}")

logFolderFullPathappsetting.json的可配置路径。当我们更改路径时,它会在新路径上创建一个日志文件,但同时也会继续写入旧路径文件。

因此我们希望它停止写入旧路径。

1 个答案:

答案 0 :(得分:2)

您可以尝试使用Serilog.Settings.Reloader,该配置可以在配置发生更改时在运行时交换记录器实例。


在运行时更改记录器属性的另一种常见方法是使用Serilog.Sinks.Map,这是一个根据日志事件的属性调度事件的接收器。

下面的示例使用名为FileName的日志事件属性来确定将要写入的日志文件的名称,因此,只要此属性更改,日志文件就会相应地更改:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Map("FileName", "IDontKnow", (fileName, wt) => wt.File($"{fileName}.txt"))
    .CreateLogger();

Log.ForContext("FileName", "Alice").Information("Hey!"); // writes to Alice.txt
Log.ForContext("FileName", "Bob").Information("Hello!"); // writes to Bob.txt
Log.Information("Hi Again!"); // writes to IDontKnow.txt (default if property is missing)

Log.CloseAndFlush();

根据您的情况,您想根据配置的更改动态更改此属性名称。一种简单的方法是创建一个自定义enricher,该自定义enricher可以根据您的配置设置更改上述属性的值。

您的自定义Options pattern看起来像这样:

internal class LogFilePathEnricher : ILogEventEnricher
{
    private string _cachedLogFilePath;
    private LogEventProperty _cachedLogFilePathProperty;

    public const string LogFilePathPropertyName = "LogFilePath";

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var logFilePath = // Read path from your appsettings.json
        // Check for null, etc...

        LogEventProperty logFilePathProperty;

        if (logFilePath.Equals(_cachedLogFilePath))
        {
            // Path hasn't changed, so let's use the cached property
            logFilePathProperty = _cachedLogFilePathProperty;
        }
        else
        {
            // We've got a new path for the log. Let's create a new property
            // and cache it for future log events to use
            _cachedLogFilePath = logFilePath;

            _cachedLogFilePathProperty = logFilePathProperty =
                propertyFactory.CreateProperty(LogFilePathPropertyName, logFilePath);
        }

        logEvent.AddPropertyIfAbsent(logFilePathProperty);
    }
}

注意:如果使用{{3}},而不是每次写入日志消息时都要检查配置,则上面的示例浓缩器可能会更有效。

有了能够根据配置为您动态设置LogFilePath属性的扩充器,您只需要配置日志记录管道即可基于该属性进行映射。

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .Enrich.With<LogFileNameEnricher>()
    .WriteTo.Map(LogFileNameEnricher.LogFilePathPropertyName,
        (logFilePath, wt) => wt.File($"{logFilePath}"), sinkMapCountLimit: 1)
    .CreateLogger();

// ...

Log.CloseAndFlush();