我具有动态更改日志文件路径的功能。但是当我更改在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
的可配置路径。当我们更改路径时,它会在新路径上创建一个日志文件,但同时也会继续写入旧路径文件。
因此我们希望它停止写入旧路径。
答案 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();