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 or .
///
/// 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 new StreamWriter(this.file.Open(FileMode.Append, FileAccess.Write, FileShare.ReadWrite));
} catch (Exception e) {
throw new IOException($"Failed to append to file sink {this.file}", e);
}
}
}
}