2016-03-28 17:54:24 -07:00
|
|
|
|
using System;
|
|
|
|
|
|
|
2017-03-01 21:58:09 -08:00
|
|
|
|
using SabreTools.Helper.Data;
|
|
|
|
|
|
|
2017-03-29 11:25:31 -07:00
|
|
|
|
#if MONO
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
#else
|
|
|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
|
|
|
|
|
|
|
|
|
|
|
using FileAccess = System.IO.FileAccess;
|
|
|
|
|
|
using FileMode = System.IO.FileMode;
|
|
|
|
|
|
using StreamWriter = System.IO.StreamWriter;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2016-03-29 13:48:10 -07:00
|
|
|
|
namespace SabreTools.Helper
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Log either to file or to the console
|
|
|
|
|
|
/// </summary>
|
2016-05-22 23:57:44 -07:00
|
|
|
|
/// <remarks>
|
2017-02-27 23:00:57 -08:00
|
|
|
|
/// TODO: Allow for "triggerable" logging done on an interval (async)
|
2016-05-22 23:57:44 -07:00
|
|
|
|
/// </remarks>
|
2016-03-28 18:40:35 -07:00
|
|
|
|
public class Logger
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
|
|
|
|
|
// Private instance variables
|
|
|
|
|
|
private bool _tofile;
|
2016-10-08 23:33:16 -07:00
|
|
|
|
private bool _warnings;
|
2016-10-11 22:10:28 -07:00
|
|
|
|
private bool _errors;
|
2016-03-28 17:54:24 -07:00
|
|
|
|
private string _filename;
|
2017-03-01 21:58:09 -08:00
|
|
|
|
private LogLevel _filter;
|
2016-04-27 22:17:19 -07:00
|
|
|
|
private DateTime _start;
|
2016-03-28 17:54:24 -07:00
|
|
|
|
private StreamWriter _log;
|
|
|
|
|
|
|
2016-05-10 16:01:32 -07:00
|
|
|
|
// Private required variables
|
2017-03-29 12:49:34 -07:00
|
|
|
|
private string _basepath = Path.Combine(Globals.ExeDir, "logs") + Path.DirectorySeparatorChar;
|
2016-05-10 16:01:32 -07:00
|
|
|
|
|
2016-10-24 12:58:57 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialize a console-only logger object
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Logger()
|
|
|
|
|
|
{
|
|
|
|
|
|
_tofile = false;
|
|
|
|
|
|
_warnings = false;
|
|
|
|
|
|
_errors = false;
|
|
|
|
|
|
_filename = null;
|
2017-03-01 21:58:09 -08:00
|
|
|
|
_filter = LogLevel.VERBOSE;
|
2016-10-24 12:58:57 -07:00
|
|
|
|
|
|
|
|
|
|
Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialize a Logger object with the given information
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="tofile">True if file should be written to instead of console</param>
|
2016-06-02 00:08:55 -07:00
|
|
|
|
/// <param name="filename">Filename representing log location</param>
|
2017-03-01 21:58:09 -08:00
|
|
|
|
/// <param name="filter">Highest filtering level to be kept, default VERBOSE</param>
|
|
|
|
|
|
public Logger(bool tofile, string filename, LogLevel filter = LogLevel.VERBOSE)
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
|
|
|
|
|
_tofile = tofile;
|
2016-10-08 23:33:16 -07:00
|
|
|
|
_warnings = false;
|
2016-10-24 12:58:57 -07:00
|
|
|
|
_errors = false;
|
2017-01-05 10:43:16 -08:00
|
|
|
|
_filename = Path.GetFileNameWithoutExtension(filename) + " (" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ")" + Path.GetExtension(filename);
|
2017-03-01 21:58:09 -08:00
|
|
|
|
_filter = filter;
|
2016-05-10 16:01:32 -07:00
|
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(_basepath))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(_basepath);
|
|
|
|
|
|
}
|
2016-09-22 16:43:38 -07:00
|
|
|
|
|
|
|
|
|
|
Start();
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Start logging by opening output file (if necessary)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>True if the logging was started correctly, false otherwise</returns>
|
2016-03-28 17:54:24 -07:00
|
|
|
|
public bool Start()
|
|
|
|
|
|
{
|
2016-04-28 17:39:10 -07:00
|
|
|
|
_start = DateTime.Now;
|
2016-03-28 17:54:24 -07:00
|
|
|
|
if (!_tofile)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2016-10-26 23:36:29 -07:00
|
|
|
|
_log = new StreamWriter(File.Open(_basepath + _filename, FileMode.OpenOrCreate | FileMode.Append, FileAccess.Write));
|
|
|
|
|
|
_log.AutoFlush = true;
|
|
|
|
|
|
|
2017-01-11 21:00:17 -08:00
|
|
|
|
_log.WriteLine("Logging started " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
2016-09-23 15:22:58 -07:00
|
|
|
|
_log.WriteLine(Environment.CommandLine);
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// End logging by closing output file (if necessary)
|
|
|
|
|
|
/// </summary>
|
2016-06-13 00:40:32 -07:00
|
|
|
|
/// <param name="suppress">True if all ending output is to be suppressed, false otherwise (default)</param>
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <returns>True if the logging was ended correctly, false otherwise</returns>
|
2016-06-13 00:40:32 -07:00
|
|
|
|
public bool Close(bool suppress = false)
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2016-06-13 00:40:32 -07:00
|
|
|
|
if (!suppress)
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2016-10-24 12:58:57 -07:00
|
|
|
|
if (_warnings)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("There were warnings in the last run! Check the log for more details");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_errors)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("There were errors in the last run! Check the log for more details");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-13 00:40:32 -07:00
|
|
|
|
TimeSpan span = DateTime.Now.Subtract(_start);
|
2017-02-28 23:32:28 -08:00
|
|
|
|
|
|
|
|
|
|
// Special case for multi-day runs
|
|
|
|
|
|
string total = "";
|
|
|
|
|
|
if (span >= TimeSpan.FromDays(1))
|
|
|
|
|
|
{
|
|
|
|
|
|
total = span.ToString(@"d\:hh\:mm\:ss");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
total = span.ToString(@"hh\:mm\:ss");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-13 00:40:32 -07:00
|
|
|
|
if (!_tofile)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("Total runtime: " + total);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2016-03-28 17:54:24 -07:00
|
|
|
|
|
2016-06-13 00:40:32 -07:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-01-11 21:00:17 -08:00
|
|
|
|
_log.WriteLine("Logging ended " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
2016-06-13 00:40:32 -07:00
|
|
|
|
_log.WriteLine("Total runtime: " + total);
|
|
|
|
|
|
Console.WriteLine("Total runtime: " + total);
|
|
|
|
|
|
_log.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
2016-06-13 00:40:32 -07:00
|
|
|
|
else
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2016-06-13 00:40:32 -07:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
_log.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write the given string to the log output
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
2016-03-30 13:53:14 -07:00
|
|
|
|
/// <param name="loglevel">Severity of the information being logged</param>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement, false otherwise</param>
|
2016-03-29 14:49:03 -07:00
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
private bool Log(string output, LogLevel loglevel, bool appendPrefix)
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2017-03-01 21:58:09 -08:00
|
|
|
|
// If the log level is less than the filter level, we skip it but claim we didn't
|
|
|
|
|
|
if (loglevel < _filter)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-10 15:41:33 -07:00
|
|
|
|
// USER and ERROR writes to console
|
|
|
|
|
|
if (loglevel == LogLevel.USER || loglevel == LogLevel.ERROR)
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
Console.WriteLine((loglevel == LogLevel.ERROR && appendPrefix ? loglevel.ToString() + " " : "") + output);
|
2016-05-10 15:41:33 -07:00
|
|
|
|
}
|
2016-03-30 12:18:56 -07:00
|
|
|
|
|
2016-03-28 17:54:24 -07:00
|
|
|
|
// If we're writing to file, use the existing stream
|
2016-03-30 12:18:56 -07:00
|
|
|
|
if (_tofile)
|
2016-03-28 17:54:24 -07:00
|
|
|
|
{
|
2016-03-30 12:18:56 -07:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
_log.WriteLine((appendPrefix ? loglevel.ToString() + " - " + DateTime.Now + " - " : "" ) + output);
|
2016-03-30 12:18:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("Could not write to log file!");
|
2016-06-22 20:57:53 -07:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write the given exact string to the log output
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
2016-06-26 22:08:35 -07:00
|
|
|
|
/// <param name="line">Line number to write out to</param>
|
|
|
|
|
|
/// <param name="column">Column number to write out to</param>
|
2016-06-22 20:57:53 -07:00
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
public bool WriteExact(string output, int line, int column)
|
2016-06-22 20:57:53 -07:00
|
|
|
|
{
|
2016-06-26 22:08:35 -07:00
|
|
|
|
// Set the cursor position (if not being redirected)
|
|
|
|
|
|
if (!Console.IsOutputRedirected)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.CursorTop = line;
|
|
|
|
|
|
Console.CursorLeft = column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Write out to the console
|
2016-06-29 13:44:41 -07:00
|
|
|
|
Console.Write(output);
|
2016-06-22 20:57:53 -07:00
|
|
|
|
|
|
|
|
|
|
// If we're writing to file, use the existing stream
|
|
|
|
|
|
if (_tofile)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
_log.Write(DateTime.Now + " - " + output);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("Could not write to log file!");
|
2016-03-30 12:18:56 -07:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2016-03-30 13:36:52 -07:00
|
|
|
|
|
2016-09-23 15:09:00 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write the given string as a verbose message to the log output
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
|
|
|
|
|
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
|
|
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>s
|
|
|
|
|
|
public bool Verbose(string output, bool appendPrefix = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Log(output, LogLevel.VERBOSE, appendPrefix);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-22 23:57:44 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write the given string as a user message to the log output
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
|
2016-05-22 23:57:44 -07:00
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
public bool User(string output, bool appendPrefix = true)
|
2016-05-10 15:41:33 -07:00
|
|
|
|
{
|
2016-09-23 15:09:00 -07:00
|
|
|
|
return Log(output, LogLevel.USER, appendPrefix);
|
2016-05-10 15:41:33 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-30 13:53:14 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Write the given string as a warning to the log output
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
|
2016-03-30 13:53:14 -07:00
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
public bool Warning(string output, bool appendPrefix = true)
|
2016-03-30 13:53:14 -07:00
|
|
|
|
{
|
2016-10-08 23:33:16 -07:00
|
|
|
|
_warnings = true;
|
2016-09-23 15:09:00 -07:00
|
|
|
|
return Log(output, LogLevel.WARNING, appendPrefix);
|
2016-03-30 13:53:14 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-30 13:36:52 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Writes the given string as an error in the log
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="output">String to be written log</param>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
/// <param name="appendPrefix">True if the level and datetime should be prepended to each statement (default), false otherwise</param>
|
2016-03-30 13:36:52 -07:00
|
|
|
|
/// <returns>True if the output could be written, false otherwise</returns>
|
2016-09-23 15:09:00 -07:00
|
|
|
|
public bool Error(string output, bool appendPrefix = true)
|
2016-03-30 13:36:52 -07:00
|
|
|
|
{
|
2016-10-11 22:10:28 -07:00
|
|
|
|
_errors = true;
|
2016-09-23 15:09:00 -07:00
|
|
|
|
return Log(output, LogLevel.ERROR, appendPrefix);
|
2016-03-30 13:36:52 -07:00
|
|
|
|
}
|
2016-06-26 23:25:48 -07:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Clear lines beneath the given line in the console
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="line">Line number to clear beneath</param>
|
|
|
|
|
|
/// <returns>True</returns>
|
|
|
|
|
|
public bool ClearBeneath(int line)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Console.IsOutputRedirected)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = line; i < Console.WindowHeight; i++)
|
|
|
|
|
|
{
|
2016-06-28 21:19:12 -07:00
|
|
|
|
// 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);
|
2016-06-26 23:25:48 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2016-03-28 17:54:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|