using System.Text; namespace Agent.App.Logging; internal sealed class RollingFileWriter : IDisposable { private readonly object _sync = new(); private readonly string _path; private readonly long _maxBytes; private readonly int _retainedFiles; private StreamWriter _writer; public RollingFileWriter(string path, long maxBytes, int retainedFiles) { _path = path; _maxBytes = maxBytes; _retainedFiles = retainedFiles; Directory.CreateDirectory(Path.GetDirectoryName(path)!); _writer = Open(); } public void WriteLine(string line) { lock (_sync) { if (_writer.BaseStream.Length >= _maxBytes) Rotate(); _writer.WriteLine(line); _writer.Flush(); } } private StreamWriter Open() => new(new FileStream(_path, FileMode.Append, FileAccess.Write, FileShare.Read), new UTF8Encoding(false)); private void Rotate() { _writer.Dispose(); for (int index = _retainedFiles - 1; index >= 1; index--) { string source = $"{_path}.{index}"; if (File.Exists(source)) File.Move(source, $"{_path}.{index + 1}", true); } if (File.Exists(_path)) File.Move(_path, $"{_path}.1", true); _writer = Open(); } public void Dispose() { lock (_sync) _writer.Dispose(); } }