You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Serilog实现每日滚动日志且每次启动生成新日志?

解决Serilog同时实现启动生成新文件、按日分类、自动删旧日志的问题

你的问题根源在于同时混用了自定义启动时间戳和Serilog内置的RollingInterval.Day滚动机制,导致文件名格式混乱,且自动清理逻辑无法识别跨启动的日志文件。下面是两种针对性的解决方案:

方案一:手动清理旧文件 + 自定义启动文件名(简单可靠)

这是最直接的方式,完全符合你“每次启动生成新文件”的需求,同时手动控制旧日志的删除逻辑,避开Serilog滚动机制的限制。

步骤说明:

  1. 启动时先清理旧日志:在初始化Serilog之前,遍历日志目录,删除90天前的所有Info_*.txt文件。
  2. 生成启动专属文件名:用启动时间(包含日期+时分秒)作为文件名的一部分,不使用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();

为什么你之前的配置失效?

  1. 自动添加日期后缀:当你设置rollingInterval: RollingInterval.Day时,Serilog的PathRoller会自动在文件名末尾追加_yyyyMMdd后缀,导致你自定义的启动时间戳后又多了一个日期,不符合预期。
  2. 旧日志无法删除:Serilog的清理逻辑是基于文件前缀的,每个启动生成的文件前缀是Info_<启动时间戳>,所以清理时只会搜索当前前缀的文件,其他启动生成的文件不在搜索范围内,自然无法被删除。

内容的提问来源于stack exchange,提问作者Synthetiker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:01:03