2020-09-22 21:52:24 +00:00
|
|
|
|
using System;
|
2020-09-22 21:46:39 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reactive.Subjects;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Wabbajack.Common.StatusFeed;
|
|
|
|
|
using Wabbajack.Common.StatusFeed.Errors;
|
|
|
|
|
using File = Alphaleonis.Win32.Filesystem.File;
|
|
|
|
|
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
|
|
|
|
|
using Path = Alphaleonis.Win32.Filesystem.Path;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Common
|
|
|
|
|
{
|
2020-09-22 21:52:24 +00:00
|
|
|
|
public static class LoggingSettings
|
|
|
|
|
{
|
|
|
|
|
// False by default, so that library users do not have to swap it
|
|
|
|
|
public static bool LogToFile = false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-22 21:46:39 +00:00
|
|
|
|
public static partial class Utils
|
|
|
|
|
{
|
|
|
|
|
public static AbsolutePath LogFile { get; private set; }
|
|
|
|
|
public static AbsolutePath LogFolder { get; private set; }
|
|
|
|
|
|
|
|
|
|
private static object _logLock = new object();
|
|
|
|
|
|
|
|
|
|
private static DateTime _startTime;
|
|
|
|
|
|
|
|
|
|
private static readonly Subject<IStatusMessage> LoggerSubj = new Subject<IStatusMessage>();
|
|
|
|
|
public static IObservable<IStatusMessage> LogMessages => LoggerSubj;
|
|
|
|
|
|
2021-05-20 08:08:24 +00:00
|
|
|
|
public static async Task InitializeLogging()
|
2020-09-22 21:46:39 +00:00
|
|
|
|
{
|
|
|
|
|
_startTime = DateTime.Now;
|
|
|
|
|
|
2020-09-22 21:52:24 +00:00
|
|
|
|
if (LoggingSettings.LogToFile)
|
2020-09-22 21:46:39 +00:00
|
|
|
|
{
|
2020-09-22 21:52:24 +00:00
|
|
|
|
LogFolder = Consts.LogsFolder;
|
|
|
|
|
LogFile = Consts.LogFile;
|
|
|
|
|
Consts.LocalAppDataPath.CreateDirectory();
|
|
|
|
|
Consts.LogsFolder.CreateDirectory();
|
2020-09-22 21:46:39 +00:00
|
|
|
|
|
2020-09-22 21:52:24 +00:00
|
|
|
|
if (LogFile.Exists)
|
2020-09-22 21:46:39 +00:00
|
|
|
|
{
|
2020-09-22 21:52:24 +00:00
|
|
|
|
var newPath = Consts.LogsFolder.Combine(Consts.EntryPoint.FileNameWithoutExtension + LogFile.LastModified.ToString(" yyyy-MM-dd HH_mm_ss") + ".log");
|
|
|
|
|
await LogFile.MoveToAsync(newPath, true);
|
|
|
|
|
}
|
2020-09-22 21:46:39 +00:00
|
|
|
|
|
2020-09-22 21:52:24 +00:00
|
|
|
|
var logFiles = LogFolder.EnumerateFiles(false).ToList();
|
|
|
|
|
if (logFiles.Count >= Consts.MaxOldLogs)
|
|
|
|
|
{
|
|
|
|
|
Log($"Maximum amount of old logs reached ({logFiles.Count} >= {Consts.MaxOldLogs})");
|
|
|
|
|
var filesToDelete = logFiles
|
|
|
|
|
.Where(f => f.IsFile)
|
|
|
|
|
.OrderBy(f => f.LastModified)
|
|
|
|
|
.Take(logFiles.Count - Consts.MaxOldLogs)
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
Log($"Found {filesToDelete.Count} old log files to delete");
|
|
|
|
|
|
|
|
|
|
var success = 0;
|
|
|
|
|
var failed = 0;
|
|
|
|
|
filesToDelete.Do(f =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
f.Delete();
|
|
|
|
|
success++;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
failed++;
|
|
|
|
|
Log($"Could not delete log at {f}!\n{e}");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Log($"Deleted {success} log files, failed to delete {failed} logs");
|
|
|
|
|
}
|
2020-09-22 21:46:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-22 21:52:24 +00:00
|
|
|
|
|
|
|
|
|
|
2020-09-22 21:46:39 +00:00
|
|
|
|
public static void Log(string msg)
|
|
|
|
|
{
|
|
|
|
|
Log(new GenericInfo(msg));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static T Log<T>(T msg) where T : IStatusMessage
|
|
|
|
|
{
|
|
|
|
|
LogStraightToFile(string.IsNullOrWhiteSpace(msg.ExtendedDescription) ? msg.ShortDescription : msg.ExtendedDescription);
|
|
|
|
|
LoggerSubj.OnNext(msg);
|
|
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Error(string errMessage)
|
|
|
|
|
{
|
|
|
|
|
Log(errMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Error(Exception ex, string? extraMessage = null)
|
|
|
|
|
{
|
|
|
|
|
Log(new GenericException(ex, extraMessage));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ErrorThrow(Exception ex, string? extraMessage = null)
|
|
|
|
|
{
|
|
|
|
|
Error(ex, extraMessage);
|
|
|
|
|
throw ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Error(IException err)
|
|
|
|
|
{
|
|
|
|
|
LogStraightToFile($"{err.ShortDescription}\n{err.Exception.StackTrace}");
|
|
|
|
|
LoggerSubj.OnNext(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ErrorThrow(IException err)
|
|
|
|
|
{
|
|
|
|
|
Error(err);
|
|
|
|
|
throw err.Exception;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void LogStraightToFile(string msg)
|
|
|
|
|
{
|
2020-09-22 21:52:24 +00:00
|
|
|
|
if (!LoggingSettings.LogToFile || LogFile == default) return;
|
2020-09-22 21:46:39 +00:00
|
|
|
|
lock (_logLock)
|
|
|
|
|
{
|
2021-04-23 05:28:20 +00:00
|
|
|
|
File.AppendAllText(LogFile.ToString(), $"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}\r\n", new UTF8Encoding(false, true));
|
2020-09-22 21:46:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Status(string msg, Percent progress, bool alsoLog = false)
|
|
|
|
|
{
|
|
|
|
|
WorkQueue.AsyncLocalCurrentQueue.Value?.Report(msg, progress);
|
|
|
|
|
if (alsoLog)
|
|
|
|
|
{
|
|
|
|
|
Utils.Log(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Status(string msg, bool alsoLog = false)
|
|
|
|
|
{
|
|
|
|
|
Status(msg, Percent.Zero, alsoLog: alsoLog);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void CatchAndLog(Action a)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
a();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Utils.Error(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task CatchAndLog(Func<Task> f)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await f();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Utils.Error(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-04 03:48:30 +00:00
|
|
|
|
|
|
|
|
|
public static void ErrorMetric(Exception exception)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
2020-09-22 21:46:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|