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

问题描述 投票:2回答:1

我有一个动态改变日志文件路径的功能,但当我改变Consul中可配置的路径时,它在两个地方都写了部分日志,即在旧路径和新路径。但是当我改变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}")

logFolderFullPath 是可配置的路径 appsetting.json. 当我们改变路径时,它在新的路径上创建了一个日志文件,但同时也一直在写旧路径的文件。

所以我们希望它能停止向旧路径写入文件。

serilog
1个回答
1
投票

你可以尝试使用 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();

在你的情况下,你想根据配置的变化动态地改变这个属性名。一个简单的方法是通过创建一个自定义的 致富者 可以根据您的配置设置改变像上面这样的属性的值。

您的自定义 致富者 会是这样的。

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

NB: 上面的例子可以更有效地使用 选项模式而不是每次写入日志消息时检查配置。

有了一个可以动态设置的浓缩器,它可以动态设置 LogFilePath 属性的基础上为您配置,您只需根据该属性配置日志管道的映射。

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

// ...

Log.CloseAndFlush();
© www.soinside.com 2019 - 2024. All rights reserved.