如何使用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
相关产品推荐
相关产品推荐

