如何配置Serilog实现每日滚动日志且每次启动生成新日志?
解决Serilog同时实现启动生成新文件、按日分类、自动删旧日志的问题
你的问题根源在于同时混用了自定义启动时间戳和Serilog内置的RollingInterval.Day滚动机制,导致文件名格式混乱,且自动清理逻辑无法识别跨启动的日志文件。下面是两种针对性的解决方案:
方案一:手动清理旧文件 + 自定义启动文件名(简单可靠)
这是最直接的方式,完全符合你“每次启动生成新文件”的需求,同时手动控制旧日志的删除逻辑,避开Serilog滚动机制的限制。
步骤说明:
- 启动时先清理旧日志:在初始化Serilog之前,遍历日志目录,删除90天前的所有
Info_*.txt文件。 - 生成启动专属文件名:用启动时间(包含日期+时分秒)作为文件名的一部分,不使用Serilog的
rollingInterval参数,避免自动添加后缀。
代码示例:
// 第一步:清理90天前的旧日志文件 var logDirectory = new DirectoryInfo("logs"); if (logDirectory.Exists) { var cutoffDate = DateTime.Now.AddDays(-90); foreach (var logFile in logDirectory.GetFiles("Info_*.txt")) { // 按文件创建时间判断是否过期 if (logFile.CreationTime < cutoffDate) { try { logFile.Delete(); } catch (IOException) { // 如果文件被其他进程占用,跳过本次删除,下次启动再尝试 Console.WriteLine($"无法删除过期日志文件:{logFile.FullName},文件可能正被占用"); } } } } // 第二步:生成启动时间戳(确保文件名唯一) var startupTimestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss", DateTimeFormatInfo.InvariantInfo); // 第三步:配置Serilog写入新文件 Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File( path: $"logs\\Info_{startupTimestamp}.txt", restrictedToMinimumLevel: LogEventLevel.Information, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]<{ThreadName}({ThreadId})> {Message:lj}{NewLine}{Exception}" ) .CreateLogger();
方案二:利用Serilog的retainedFileTimeLimit(需新版本支持)
如果你想用Serilog内置的清理机制,需要确保所有日志文件共享统一的前缀,让Serilog能识别为同一组日志。这种方式适合Serilog.Sinks.File 4.0.0及以上版本。
关键说明:
由于Serilog内置清理逻辑仅针对同一滚动组(相同前缀)的文件,直接用启动时间戳会导致每个文件前缀不同,无法跨组清理。如果要使用内置逻辑,需要自定义PathRoller类修改搜索模式为Info_*.txt,但这会增加代码复杂度,性价比不如方案一。因此更推荐方案一,若一定要尝试内置逻辑,可参考以下思路:
// 自定义PathRoller,修改搜索模式为所有Info_开头的文件 public class CustomPathRoller : PathRoller { public CustomPathRoller(string path) : base(path) { // 重写搜索模式,匹配所有Info_*.txt文件 DirectorySearchPattern = "Info_*.txt"; } } // 配置时使用自定义PathRoller var sink = new FileSink( path: $"logs\\Info_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt", formatter: new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]<{ThreadName}({ThreadId})> {Message:lj}{NewLine}{Exception}"), pathRoller: new CustomPathRoller("logs\\Info_.txt"), retainedFileTimeLimit: TimeSpan.FromDays(90) ); Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Sink(sink) .CreateLogger();
为什么你之前的配置失效?
- 自动添加日期后缀:当你设置
rollingInterval: RollingInterval.Day时,Serilog的PathRoller会自动在文件名末尾追加_yyyyMMdd后缀,导致你自定义的启动时间戳后又多了一个日期,不符合预期。 - 旧日志无法删除:Serilog的清理逻辑是基于文件前缀的,每个启动生成的文件前缀是
Info_<启动时间戳>,所以清理时只会搜索当前前缀的文件,其他启动生成的文件不在搜索范围内,自然无法被删除。
内容的提问来源于stack exchange,提问作者Synthetiker
相关产品推荐
相关产品推荐

