using System; using System.IO; namespace ExtremelySimpleLogger { /// /// A that writes log output to a file. /// public class FileSink : Sink { /// /// The that this sink is currently using as its destination. /// public FileInfo CurrentFile { get { lock (this.file) return this.file; } } private const int OneGb = 1024 * 1024 * 1024; private readonly FileInfo file; private readonly StreamWriter writer; private readonly bool reopenOnWrite; /// /// Creates a new file sink with the given settings. /// /// The full, or relative, path of the file to write to /// Whether new output should be appended to the old log file /// Whether this file sink should reopen the file every time it logs to it. If this is false, the file will be kept open by this sink. /// If is true, this property determines how big the log file has to be (in bytes) before it is deleted on startup. Defaults to 1gb. public FileSink(string file, bool append, bool reopenOnWrite = false, int fileSizeLimit = OneGb) : this(new FileInfo(file), append, reopenOnWrite, fileSizeLimit) {} /// /// Creates a new file sink with the given settings. /// /// The full, or relative, path of the file to write to /// Whether new output should be appended to the old log file /// Whether this file sink should reopen the file every time it logs to it. If this is false, the file will be kept open by this sink. /// If is true, this property determines how big the log file has to be (in bytes) before it is deleted on startup. public FileSink(FileInfo file, bool append, bool reopenOnWrite = false, int fileSizeLimit = OneGb) { this.reopenOnWrite = reopenOnWrite; this.file = file; try { var dir = file.Directory; if (dir != null && !dir.Exists) dir.Create(); } catch (Exception e) { throw new IOException($"Failed to create directory for file sink {file}", e); } try { if (file.Exists && (!append || file.Length >= fileSizeLimit)) file.Delete(); } catch (Exception e) { throw new IOException($"Failed to delete file sink file {file}", e); } if (!reopenOnWrite) { this.writer = this.Append(); this.writer.AutoFlush = true; } } /// /// Logs the given message, which has already been formatted using . /// /// The logger that the message was passed to /// The importance level of this message /// The message to log protected override void Log(Logger logger, LogLevel level, string s) { lock (this.file) { if (this.reopenOnWrite) { using (var w = this.Append()) w.WriteLine(s); } else { this.writer.WriteLine(s); } } } /// /// Disposes this sink, freeing all of the resources it uses. /// public override void Dispose() { base.Dispose(); lock (this.file) { if (!this.reopenOnWrite) this.writer.Dispose(); } } private StreamWriter Append() { try { return this.file.AppendText(); } catch (Exception e) { throw new IOException($"Failed to append to file sink {this.file}", e); } } } }