我有一个动态改变日志文件路径的功能,但当我改变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.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();