/// <summary>Construct a <see cref="FileSink"/>.</summary> /// <param name="path">Path to the file.</param> /// <param name="textFormatter">Formatter used to convert log events to text.</param> /// <param name="fileSizeLimitBytes">The approximate maximum size, in bytes, to which a log file will be allowed to grow. /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit /// will be written in full even if it exceeds the limit.</param> /// <param name="encoding">Character encoding used to write the text file. The default is UTF-8 without BOM.</param> /// <param name="buffered">Indicates if flushing to the output file can be buffered or not. The default /// is false.</param> /// <returns>Configuration object allowing method chaining.</returns> /// <remarks>The file will be written using the UTF-8 character set.</remarks> /// <exception cref="IOException"></exception> public FileSink(string path, ITextFormatter textFormatter, long?fileSizeLimitBytes, Encoding encoding = null, bool buffered = false) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (textFormatter == null) { throw new ArgumentNullException(nameof(textFormatter)); } if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) { throw new ArgumentException("Negative value provided; file size limit must be non-negative"); } _textFormatter = textFormatter; _fileSizeLimitBytes = fileSizeLimitBytes; _buffered = buffered; var directory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read); if (_fileSizeLimitBytes != null) { outputStream = _countingStreamWrapper = new WriteCountingStream(_underlyingStream); } _output = new StreamWriter(outputStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); }
// This overload should be used internally; the overload above maintains compatibility with the earlier public API. internal FileSink( string path, ITextFormatter textFormatter, long?fileSizeLimitBytes, Encoding encoding, bool buffered, FileLifecycleHooks hooks) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) { throw new ArgumentException("Negative value provided; file size limit must be non-negative."); } _textFormatter = textFormatter ?? throw new ArgumentNullException(nameof(textFormatter)); _fileSizeLimitBytes = fileSizeLimitBytes; _buffered = buffered; var directory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read); if (_fileSizeLimitBytes != null) { outputStream = _countingStreamWrapper = new WriteCountingStream(_underlyingStream); } // Parameter reassignment. encoding = encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); if (hooks != null) { outputStream = hooks.OnFileOpened(outputStream, encoding) ?? throw new InvalidOperationException($"The file lifecycle hook `{nameof(FileLifecycleHooks.OnFileOpened)}(...)` returned `null`."); } _output = new StreamWriter(outputStream, encoding); }