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

如何使用Serilog File Sink维持单一稳定的日志文件名

实现仅保留单个日志文件的方案

可以实现仅保留log.log单个文件,无需生成带递增编号的滚动文件,但不能直接依赖Serilog默认的按大小滚动机制,需要通过自定义文件生命周期钩子替换默认的滚动逻辑。

问题原因

默认的rollOnFileSizeLimit机制是在文件达到大小限制时,将当前日志文件重命名为带编号的旧文件,再创建新的主日志文件,因此必然会产生带编号的文件。要实现单文件覆盖,需要在达到大小阈值时直接清空原文件,而非生成新文件。

具体实现

1. 自定义文件生命周期钩子

创建自定义钩子类,继承Serilog的FileLifecycleHooks,通过监控文件写入大小,达到限制时截断原文件:

public class OverwriteSingleFileHook : FileLifecycleHooks
{
    private readonly long _sizeLimitBytes;
    private long _currentFileSize;

    public OverwriteSingleFileHook(long sizeLimitBytes)
    {
        _sizeLimitBytes = sizeLimitBytes;
    }

    public override Stream OnFileOpened(string path, Stream underlyingStream, Encoding encoding)
    {
        var fileInfo = new FileInfo(path);
        _currentFileSize = fileInfo.Exists ? fileInfo.Length : 0;
        return new SizeMonitoringStream(underlyingStream, _sizeLimitBytes, ref _currentFileSize, path);
    }
}

public class SizeMonitoringStream : Stream
{
    private readonly Stream _innerStream;
    private readonly long _sizeLimit;
    private ref long _currentSize;
    private readonly string _filePath;

    public SizeMonitoringStream(Stream innerStream, long sizeLimit, ref long currentSize, string filePath)
    {
        _innerStream = innerStream;
        _sizeLimit = sizeLimit;
        _currentSize = currentSize;
        _filePath = filePath;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        // 检查写入后是否超过大小限制
        if (_currentSize + count > _sizeLimit)
        {
            // 截断文件并重置指针
            _innerStream.SetLength(0);
            _innerStream.Position = 0;
            _currentSize = 0;
        }

        _innerStream.Write(buffer, offset, count);
        _currentSize += count;
    }

    // 实现Stream的其他必要方法,委托给内部流
    public override bool CanRead => _innerStream.CanRead;
    public override bool CanSeek => _innerStream.CanSeek;
    public override bool CanWrite => _innerStream.CanWrite;
    public override long Length => _innerStream.Length;
    public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
    public override void Flush() => _innerStream.Flush();
    public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
    public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
    public override void SetLength(long value) => _innerStream.SetLength(value);
}

2. 配置Serilog使用自定义钩子

在日志配置中关闭默认的滚动开关,使用自定义钩子处理大小限制:

.WriteTo.File("log.log",
    hooks: new OverwriteSingleFileHook(10), // 设置文件大小限制为10字节
    retainedFileCountLimit: null) // 无需保留旧文件,直接覆盖原文件

效果说明

配置完成后,当log.log文件大小达到设定的10字节时,会直接清空文件内容并从头写入,始终只存在一个log.log文件,不会生成任何带编号的滚动文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:05:23