using System; using System.IO; namespace SabreTools.Helper { /// /// Log either to file or to the console /// /// /// Things to do: /// - Allow for "triggerable" logging done on an interval (async) /// - Log filtering? (#if debug?) /// public class Logger { // Private instance variables private bool _tofile; private string _filename; private DateTime _start; private StreamWriter _log; // Private required variables private string _basepath = "Logs" + Path.DirectorySeparatorChar; // Public wrappers public bool ToFile { get { return _tofile; } set { if (!value) { Close(); } _tofile = value; if (_tofile) { Start(); } } } /// /// Initialize a Logger object with the given information /// /// True if file should be written to instead of console /// Filename representing log location public Logger(bool tofile, string filename) { _tofile = tofile; _filename = Path.GetFileNameWithoutExtension(filename) + " (" + DateTime.Now.ToString("yyyy-MM-dd HHmmss") + ")" + Path.GetExtension(filename); if (!Directory.Exists(_basepath)) { Directory.CreateDirectory(_basepath); } } /// /// Start logging by opening output file (if necessary) /// /// True if the logging was started correctly, false otherwise public bool Start() { _start = DateTime.Now; if (!_tofile) { return true; } try { _log = new StreamWriter(File.Open(_basepath + _filename, FileMode.OpenOrCreate | FileMode.Append)); _log.WriteLine("Logging started " + DateTime.Now); _log.Flush(); } catch { return false; } return true; } /// /// End logging by closing output file (if necessary) /// /// True if all ending output is to be suppressed, false otherwise (default) /// True if the logging was ended correctly, false otherwise public bool Close(bool suppress = false) { if (!suppress) { TimeSpan span = DateTime.Now.Subtract(_start); string total = span.ToString(@"hh\:mm\:ss\.fffff"); if (!_tofile) { Console.WriteLine("Total runtime: " + total); return true; } try { _log.WriteLine("Logging ended " + DateTime.Now); _log.WriteLine("Total runtime: " + total); Console.WriteLine("Total runtime: " + total); _log.Close(); } catch { return false; } } else { try { _log.Close(); } catch { return false; } } return true; } /// /// Write the given string to the log output /// /// String to be written log /// Severity of the information being logged /// True if the output could be written, false otherwise public bool Log(string output, LogLevel loglevel = LogLevel.VERBOSE) { // USER and ERROR writes to console if (loglevel == LogLevel.USER || loglevel == LogLevel.ERROR) { Console.WriteLine((loglevel == LogLevel.ERROR ? loglevel.ToString() + " " : "") + output); } // If we're writing to file, use the existing stream if (_tofile) { try { _log.WriteLine(loglevel.ToString() + " - " + DateTime.Now + " - " + output); _log.Flush(); } catch { Console.WriteLine("Could not write to log file!"); return false; } } return true; } /// /// Write the given exact string to the log output /// /// String to be written log /// Line number to write out to /// Column number to write out to /// True if the output could be written, false otherwise public bool Log(string output, int line, int column) { // Set the cursor position (if not being redirected) if (!Console.IsOutputRedirected) { Console.CursorTop = line; Console.CursorLeft = column; } // Write out to the console Console.Write(output); // If we're writing to file, use the existing stream if (_tofile) { try { _log.Write(DateTime.Now + " - " + output); _log.Flush(); } catch { Console.WriteLine("Could not write to log file!"); return false; } } return true; } /// /// Write the given string as a user message to the log output /// /// String to be written log /// True if the output could be written, false otherwise public bool User(string output) { return Log(output, LogLevel.USER); } /// /// Write the given string as a warning to the log output /// /// String to be written log /// True if the output could be written, false otherwise public bool Warning(string output) { return Log(output, LogLevel.WARNING); } /// /// Writes the given string as an error in the log /// /// String to be written log /// True if the output could be written, false otherwise public bool Error(string output) { return Log(output, LogLevel.ERROR); } /// /// Clear lines beneath the given line in the console /// /// Line number to clear beneath /// True public bool ClearBeneath(int line) { if (!Console.IsOutputRedirected) { for (int i = line; i < Console.WindowHeight; i++) { // http://stackoverflow.com/questions/8946808/can-console-clear-be-used-to-only-clear-a-line-instead-of-whole-console Console.SetCursorPosition(0, Console.CursorTop); Console.Write(new string(' ', Console.WindowWidth)); Console.SetCursorPosition(0, i); } } return true; } } }