Improved logging.

This commit is contained in:
2023-09-26 21:46:54 +03:00
parent d00ebfd7ed
commit f58a57c6cd
25 changed files with 429 additions and 633 deletions

View File

@@ -17,9 +17,8 @@ public class Exit : ICommandAction
{
if (args is null || args.Length == 0)
{
Config.Logger.Log("Exiting...", "Exit", isInternal: false);
Config.Logger.Log("Exiting...", source: typeof(ICommandAction), type: LogType.WARNING);
await Config.AppSettings.SaveToFile();
await Config.Logger.SaveToFile();
Environment.Exit(0);
}
else
@@ -34,7 +33,7 @@ public class Exit : ICommandAction
case "-f":
case "force":
Config.Logger.Log("Exiting (FORCE)...", "Exit", LogLevel.WARNING, false);
Config.Logger.Log("Exiting (FORCE)...", source: typeof(ICommandAction), type: LogType.WARNING);
Environment.Exit(0);
break;

View File

@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DiscordBot.Utilities;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Loaders;
using PluginManager.Online;
using PluginManager.Others;
using Spectre.Console;
namespace DiscordBot.Bot.Actions.Extra;
internal static class PluginMethods
{
private static readonly PluginsManager PluginsManager = new();
internal static async Task List()
{
var data = await ConsoleUtilities.ExecuteWithProgressBar(PluginsManager.GetAvailablePlugins(), "Loading plugins...");
TableData tableData = new(new List<string> { "Name", "Description", "Type", "Version" });
foreach (var plugin in data) tableData.AddRow(plugin);
tableData.HasRoundBorders = false;
tableData.PrintAsTable();
}
internal static async Task RefreshPlugins(bool quiet)
{
await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty);
await Program.internalActionManager.Refresh();
}
internal static async Task DownloadPlugin(PluginsManager manager, string pluginName)
{
var pluginData = await manager.GetPluginLinkByName(pluginName);
if (pluginData.Length == 0)
{
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
return;
}
var pluginType = pluginData[0];
var pluginLink = pluginData[1];
var pluginRequirements = pluginData[2];
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var downloadTask = ctx.AddTask("Downloading plugin...");
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
downloadTask.Increment(100);
ctx.Refresh();
});
if (pluginRequirements == string.Empty)
{
Console.WriteLine("Finished installing " + pluginName + " successfully");
await RefreshPlugins(false);
return;
}
List<string> requirementsUrLs = new();
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var gatherInformationTask = ctx.AddTask("Gathering info...");
gatherInformationTask.IsIndeterminate = true;
requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements);
await Task.Delay(2000);
gatherInformationTask.Increment(100);
});
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
List<Tuple<ProgressTask, IProgress<float>, Task>> downloadTasks = new();
foreach (var info in requirementsUrLs)
{
if (info.Length < 2) continue;
string[] data = info.Split(',');
string url = data[0];
string fileName = data[1];
var task = ctx.AddTask($"Downloading {fileName}...");
IProgress<float> progress = new Progress<float>(p =>
{
task.Value = p;
});
var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress);
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, Task>(task, progress, downloadTask));
}
foreach (var task in downloadTasks)
{
await task.Item3;
}
});
await RefreshPlugins(false);
}
internal static async Task<bool> LoadPlugins(string[] args)
{
var loader = new PluginLoader(Config.DiscordBot.client);
if (args.Length == 2 && args[1] == "-q")
{
loader.LoadPlugins();
return true;
}
var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Config.Logger.Log("Successfully loaded command : " + name, source: typeof(ICommandAction),
type: LogType.INFO);
}
else
{
Config.Logger.Log("Failed to load command : " + name + " because " + exception?.Message,
source: typeof(ICommandAction), type: LogType.ERROR);
}
Console.ForegroundColor = cc;
};
loader.onEVELoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Config.Logger.Log("Successfully loaded event : " + name, source: typeof(ICommandAction),
type: LogType.INFO);
}
else
{
Config.Logger.Log("Failed to load event : " + name + " because " + exception?.Message,
source: typeof(ICommandAction), type: LogType.ERROR);
}
Console.ForegroundColor = cc;
};
loader.onSLSHLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Config.Logger.Log("Successfully loaded slash command : " + name, source: typeof(ICommandAction),
type: LogType.INFO);
}
else
{
Config.Logger.Log("Failed to load slash command : " + name + " because " + exception?.Message,
source: typeof(ICommandAction), type: LogType.ERROR);
}
Console.ForegroundColor = cc;
};
loader.LoadPlugins();
Console.ForegroundColor = cc;
return true;
}
}

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using DiscordBot.Utilities;
using System.Windows.Input;
using DiscordBot.Bot.Actions.Extra;
using PluginManager;
using PluginManager.Interfaces;
using PluginManager.Loaders;
@@ -40,105 +39,26 @@ public class Plugin : ICommandAction
switch (args[0])
{
case "refresh":
await RefreshPlugins(true);
await PluginMethods.RefreshPlugins(true);
break;
case "list":
var data = await ConsoleUtilities.ExecuteWithProgressBar(manager.GetAvailablePlugins(), "Loading plugins...");
TableData tableData = new(new List<string> { "Name", "Description", "Type", "Version" });
foreach (var plugin in data) tableData.AddRow(plugin);
tableData.HasRoundBorders = false;
tableData.PrintAsTable();
await PluginMethods.List();
break;
case "load":
if (pluginsLoaded)
break;
if (Config.DiscordBot is null)
{
AnsiConsole.MarkupLine("[red]Discord bot not initialized[/]");
Config.Logger.Log("Plugins already loaded", source: typeof(ICommandAction), type: LogType.WARNING);
break;
}
var loader = new PluginLoader(Config.DiscordBot.client);
if (args.Length == 2 && args[1] == "-q")
if (Config.DiscordBot is null)
{
Console.WriteLine("Loading plugins in quiet mode...");
loader.LoadPlugins();
pluginsLoaded = true;
Config.Logger.Log("DiscordBot is null", source: typeof(ICommandAction), type: LogType.WARNING);
break;
}
var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[CMD] Successfully loaded command : " + name);
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
if (exception is null)
Console.WriteLine("An error occured while loading: " + name);
else
Console.WriteLine("[CMD] Failed to load command : " + name + " because " +
exception!.Message
);
}
Console.ForegroundColor = cc;
};
loader.onEVELoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[EVENT] Successfully loaded event : " + name);
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
}
Console.ForegroundColor = cc;
};
loader.onSLSHLoad += (name, typeName, success, exception) =>
{
if (name == null || name.Length < 2)
name = typeName;
if (success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[SLASH] Successfully loaded command : " + name);
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[SLASH] Failed to load command : " + name + " because " +
exception!.Message
);
}
Console.ForegroundColor = cc;
};
loader.LoadPlugins();
Console.ForegroundColor = cc;
pluginsLoaded = true;
pluginsLoaded = await PluginMethods.LoadPlugins(args);
break;
case "install":
@@ -155,112 +75,8 @@ public class Plugin : ICommandAction
}
}
await DownloadPlugin(manager, pluginName);
await PluginMethods.DownloadPlugin(manager, pluginName);
break;
}
}
private async Task RefreshPlugins(bool quiet)
{
await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty);
await Program.internalActionManager.Refresh();
}
public async Task DownloadPlugin(PluginsManager manager, string pluginName)
{
var pluginData = await manager.GetPluginLinkByName(pluginName);
if (pluginData.Length == 0)
{
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
return;
}
var pluginType = pluginData[0];
var pluginLink = pluginData[1];
var pluginRequirements = pluginData[2];
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var downloadTask = ctx.AddTask("Downloading plugin...");
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
downloadTask.Increment(100);
ctx.Refresh();
});
if (pluginRequirements == string.Empty)
{
Console.WriteLine("Finished installing " + pluginName + " successfully");
await RefreshPlugins(false);
return;
}
List<string> requirementsUrLs = new();
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
var gatherInformationTask = ctx.AddTask("Gathering info...");
gatherInformationTask.IsIndeterminate = true;
requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements);
await Task.Delay(2000);
gatherInformationTask.Increment(100);
});
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn()
})
.StartAsync(async ctx =>
{
List<Tuple<ProgressTask, IProgress<float>, Task>> downloadTasks = new();
foreach (var info in requirementsUrLs)
{
if (info.Length < 2) continue;
string[] data = info.Split(',');
string url = data[0];
string fileName = data[1];
var task = ctx.AddTask($"Downloading {fileName}...");
IProgress<float> progress = new Progress<float>(p =>
{
task.Value = p;
});
var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress);
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, Task>(task, progress, downloadTask));
}
foreach (var task in downloadTasks)
{
await task.Item3;
}
});
await RefreshPlugins(false);
}
}

View File

@@ -23,6 +23,6 @@ public static class Installer
AnsiConsole.MarkupLine("[bold]Config saved ![/]");
Config.Logger.Log("Config Saved", "Installer", isInternal: true);
Config.Logger.Log("Config Saved", source: typeof(Installer));
}
}

View File

@@ -7,6 +7,7 @@ using DiscordBot.Utilities;
using PluginManager.Bot;
using PluginManager.Others;
using PluginManager.Others.Actions;
using Spectre.Console;
using static PluginManager.Config;
namespace DiscordBot;
@@ -80,7 +81,7 @@ public class Program
}
catch ( Exception ex )
{
Logger.Log(ex.ToString(), "Bot", LogLevel.ERROR);
Logger.Log(ex.ToString(), source: typeof(Program), type: LogType.CRITICAL);
}
}
@@ -107,7 +108,7 @@ public class Program
Logger.Log("An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" +
"There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !",
"Bot", LogLevel.ERROR);
source: typeof(Program), type: LogType.ERROR);
}
}
}
@@ -116,19 +117,18 @@ public class Program
{
await Initialize();
Logger.LogEvent += (message, type, isInternal) =>
Logger.OnLog += (sender, logMessage) =>
{
if (type == LogLevel.INFO)
Console.ForegroundColor = ConsoleColor.Green;
else if (type == LogLevel.WARNING)
Console.ForegroundColor = ConsoleColor.DarkYellow;
else if (type == LogLevel.ERROR)
Console.ForegroundColor = ConsoleColor.Red;
else if (type == LogLevel.CRITICAL)
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"[{type.ToString()}] {message}");
Console.ResetColor();
string messageColor = logMessage.Type switch
{
LogType.INFO => "[green]",
LogType.WARNING => "[yellow]",
LogType.ERROR => "[red]",
LogType.CRITICAL => "[red]",
_ => "[white]"
};
AnsiConsole.MarkupLine($"{messageColor}{logMessage.ThrowTime} {logMessage.Message} [/]");
};
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();

View File

@@ -78,16 +78,13 @@ public class Boot
CommonTasks();
await client.LoginAsync(TokenType.Bot, botToken);
await client.StartAsync();
commandServiceHandler = new CommandHandler(client, service, botPrefix);
await commandServiceHandler.InstallCommandsAsync();
await Task.Delay(2000);
Config._DiscordBotClient = this;
while (!isReady) ;
@@ -108,8 +105,7 @@ public class Boot
if (arg.Message.Contains("401"))
{
Config.AppSettings.Remove("token");
Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", this,
LogLevel.ERROR);
Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", source:typeof(Boot), type: LogType.CRITICAL);
await Config.AppSettings.SaveToFile();
await Task.Delay(4000);
Environment.Exit(0);
@@ -118,7 +114,7 @@ public class Boot
private async Task Client_LoggedOut()
{
Config.Logger.Log("Successfully Logged Out", this);
Config.Logger.Log("Successfully Logged Out", source: typeof(Boot));
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
}
@@ -130,7 +126,7 @@ public class Boot
private Task LoggedIn()
{
Config.Logger.Log("Successfully Logged In", this);
Config.Logger.Log("Successfully Logged In", source: typeof(Boot));
return Task.CompletedTask;
}
@@ -140,13 +136,12 @@ public class Boot
{
case LogSeverity.Error:
case LogSeverity.Critical:
Config.Logger.Log(message.Message, this, LogLevel.ERROR);
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.ERROR);
break;
case LogSeverity.Info:
case LogSeverity.Debug:
Config.Logger.Log(message.Message, this);
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.INFO);
break;

View File

@@ -57,7 +57,7 @@ internal class CommandHandler
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, "CommandHandler", LogLevel.ERROR);
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
}
return Task.CompletedTask;
@@ -145,7 +145,7 @@ internal class CommandHandler
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
}
}
}

View File

@@ -9,8 +9,8 @@ namespace PluginManager;
public class Config
{
private static bool _isLoaded;
public static DBLogger? Logger;
private static bool _isLoaded;
public static Logger Logger;
public static SettingsDictionary<string, string> AppSettings;
internal static Boot? _DiscordBotClient;
@@ -30,15 +30,14 @@ public class Config
AppSettings = new SettingsDictionary<string, string>("./Data/Resources/config.json");
AppSettings["LogFolder"] = "./Data/Logs/Logs";
AppSettings["ErrorFolder"] = "./Data/Logs/Errors";
Logger = new DBLogger(true);
Logger = new Logger(false, true);
ArchiveManager.Initialize();
_isLoaded = true;
Logger.Log("Config initialized", LogLevel.INFO);
await Logger.Log(message: "Config initialized", source: typeof(Config));
}
}

View File

@@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace PluginManager.Interfaces.Exceptions;
public interface IException
{
public List<string> Messages { get; set; }
public bool isFatal { get; }
public string GenerateFullMessage();
public void HandleException();
public IException AppendError(string message);
public IException AppendError(List<string> messages);
public IException IsFatal(bool isFatal = true);
}

View File

@@ -0,0 +1,15 @@
using System;
using PluginManager.Others;
namespace PluginManager.Interfaces.Logger;
internal interface ILog
{
string Message { get; set; }
string OutputFile { get; set; }
Type? Source { get; set; }
LogType Type { get; set; }
DateTime ThrowTime { get; set; }
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Threading.Tasks;
using PluginManager.Others;
using PluginManager.Others.Logger;
namespace PluginManager.Interfaces.Logger;
internal interface ILogger
{
bool IsEnabled { get; init; }
bool OutputToFile { get; init; }
event EventHandler<Log> OnLog;
Task Log(
string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO,
DateTime throwTime = default);
}

View File

@@ -53,10 +53,9 @@ internal class Loader
{
Assembly.LoadFrom(file);
}
catch (Exception ex)
catch
{
Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", this,
LogLevel.ERROR);
Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", source: typeof(Loader), type: LogType.ERROR);
continue;
}
@@ -130,7 +129,7 @@ internal class Loader
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
Config.Logger.Log(ex.Message, source: typeof(Loader), type: LogType.ERROR);
return null;
}

View File

@@ -88,11 +88,10 @@ public class PluginLoader
Events = new List<DBEvent>();
SlashCommands = new List<DBSlashCommand>();
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, this,
LogLevel.INFO);
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, source: typeof(PluginLoader), type: LogType.INFO);
var loader = new Loader("./Data/Plugins", "dll");
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", this, LogLevel.INFO);
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", source: typeof(PluginLoader), type: LogType.INFO);
loader.PluginLoaded += Loader_PluginLoaded;
var res = loader.Load();
Events = res.Item1;
@@ -117,7 +116,7 @@ public class PluginLoader
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
}
break;
@@ -151,13 +150,13 @@ public class PluginLoader
var instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(client);
Events.Add(instance);
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", LogLevel.INFO);
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", source: typeof(PluginLoader));
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
var instance = (DBCommand)Activator.CreateInstance(type);
Commands.Add(instance);
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", LogLevel.INFO);
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
}
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
{
@@ -170,13 +169,13 @@ public class PluginLoader
await client.CreateGlobalApplicationCommandAsync(builder.Build());
SlashCommands.Add(instance);
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", LogLevel.INFO);
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
}
}
catch (Exception ex)
{
//Console.WriteLine(ex.Message);
Config.Logger.Error(ex);
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
}
}

View File

@@ -89,8 +89,7 @@ public class PluginsManager
}
catch (Exception exception)
{
Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this,
LogLevel.ERROR);
Config.Logger.Log(message: "Failed to execute command: listplugs\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR );
}
return null;
@@ -142,8 +141,7 @@ public class PluginsManager
}
catch (Exception exception)
{
Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this,
LogLevel.ERROR);
Config.Logger.Log("Failed to execute command: plugin list\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR);
}
return null;

View File

@@ -48,7 +48,7 @@ public class InternalActionManager
{
if (!Actions.ContainsKey(actionName))
{
Config.Logger.Log($"Action {actionName} not found", "InternalActionManager", LogLevel.WARNING, true);
Config.Logger.Log($"Action {actionName} not found", type: LogType.ERROR, source: typeof(InternalActionManager));
return "Action not found";
}
@@ -59,7 +59,7 @@ public class InternalActionManager
}
catch (Exception e)
{
Config.Logger.Log(e.Message, "InternalActionManager", LogLevel.ERROR);
Config.Logger.Log(e.Message , type: LogType.ERROR, source: typeof(InternalActionManager));
return e.Message;
}
}

View File

@@ -2,7 +2,6 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading.Tasks;
namespace PluginManager.Others;
@@ -94,7 +93,7 @@ public static class ArchiveManager
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, "Archive Manager", LogLevel.ERROR); // Write the error to a file
Config.Logger.Log(message: ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); // Write the error to a file
await Task.Delay(100);
return await ReadFromPakAsync(FileName, archFile);
}
@@ -132,8 +131,7 @@ public static class ArchiveManager
}
catch (Exception ex)
{
Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}",
"Archive Manager", LogLevel.ERROR);
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
}
currentZIPFile++;
@@ -165,8 +163,7 @@ public static class ArchiveManager
}
catch (Exception ex)
{
Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}",
"Archive Manager", LogLevel.ERROR);
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
}
await Task.Delay(10);

View File

@@ -14,7 +14,7 @@ public enum OperatingSystem
/// <summary>
/// The output log type
/// </summary>
public enum LogLevel
public enum LogType
{
INFO,
WARNING,

View File

@@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using PluginManager.Interfaces.Exceptions;
namespace PluginManager.Others.Exceptions;
public class ConfigFailedToLoad : IException
{
public List<string>? Messages { get; set; }
public bool isFatal { get; private set; }
public string? File { get; }
public ConfigFailedToLoad(string message, bool isFatal, string file)
{
this.isFatal = isFatal;
Messages = new List<string>() {message};
this.File = file;
}
public ConfigFailedToLoad(string message, bool isFatal)
{
this.isFatal = isFatal;
Messages = new List<string>() {message};
this.File = null;
}
public ConfigFailedToLoad(string message)
{
this.isFatal = false;
Messages = new List<string>() {message};
this.File = null;
}
public string GenerateFullMessage()
{
string messages = "";
foreach (var message in Messages)
{
messages += message + "\n";
}
return $"\nMessage: {messages}\nIsFatal: {isFatal}\nFile: {File ?? "null"}";
}
public void HandleException()
{
if (isFatal)
{
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
Environment.Exit((int)ExceptionExitCode.CONFIG_FAILED_TO_LOAD);
}
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
}
public IException AppendError(string message)
{
Messages.Add(message);
return this;
}
public IException AppendError(List<string> messages)
{
Messages.AddRange(messages);
return this;
}
public IException IsFatal(bool isFatal = true)
{
this.isFatal = isFatal;
return this;
}
public static ConfigFailedToLoad CreateError(string message, bool isFatal, string? file = null)
{
if (file is not null)
return new ConfigFailedToLoad(message, isFatal, file);
return new ConfigFailedToLoad(message, isFatal);
}
public static ConfigFailedToLoad CreateError(string message)
{
return new ConfigFailedToLoad(message);
}
}

View File

@@ -1,75 +0,0 @@
using System;
using System.Collections.Generic;
using PluginManager.Interfaces.Exceptions;
namespace PluginManager.Others.Exceptions;
public class ConfigNoKeyWasPresent: IException
{
public List<string> Messages { get; set; }
public bool isFatal { get; private set; }
public ConfigNoKeyWasPresent(string message, bool isFatal)
{
this.Messages = new List<string>() { message };
this.isFatal = isFatal;
}
public ConfigNoKeyWasPresent(string message)
{
this.Messages = new List<string>() { message };
this.isFatal = false;
}
public string GenerateFullMessage()
{
string messages = "";
foreach (var message in Messages)
{
messages += message + "\n";
}
return $"\nMessage: {messages}\nIsFatal: {isFatal}";
}
public void HandleException()
{
if (isFatal)
{
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
Environment.Exit((int)ExceptionExitCode.CONFIG_KEY_NOT_FOUND);
}
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
}
public IException AppendError(string message)
{
Messages.Add(message);
return this;
}
public IException AppendError(List<string> messages)
{
Messages.AddRange(messages);
return this;
}
public IException IsFatal(bool isFatal = true)
{
this.isFatal = isFatal;
return this;
}
public static ConfigNoKeyWasPresent CreateError(string message)
{
return new ConfigNoKeyWasPresent(message);
}
public static ConfigNoKeyWasPresent CreateError(string message, bool isFatal)
{
return new ConfigNoKeyWasPresent(message, isFatal);
}
}

View File

@@ -1,95 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace PluginManager.Others.Logger;
public class DBLogger
{
public delegate void LogHandler(string message, LogLevel logType, bool isInternal = false);
private readonly string _errFolder;
private readonly string _logFolder;
private readonly List<LogMessage> ErrorHistory = new();
private readonly List<LogMessage> LogHistory = new();
private readonly bool _continuousSave;
private readonly bool _LogErrorsOnly;
public DBLogger(bool continuousSave = true, bool logErrorsOnly = true)
{
_logFolder = Config.AppSettings["LogFolder"];
_errFolder = Config.AppSettings["ErrorFolder"];
_continuousSave = continuousSave;
_LogErrorsOnly = logErrorsOnly;
}
public IReadOnlyList<LogMessage> Logs => LogHistory;
public IReadOnlyList<LogMessage> Errors => ErrorHistory;
public event LogHandler? LogEvent;
public void Log(string message, LogLevel type = LogLevel.INFO)
{
Log(new LogMessage(message, type));
}
public void Log(string message, LogLevel type= LogLevel.INFO, bool isInternal = false)
{
Log(new LogMessage(message, type,"unknown", isInternal));
}
public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO, bool isInternal = false)
{
Log(new LogMessage(message, type,sender,isInternal));
}
public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO)
{
Log(new LogMessage(message, type, sender));
}
public void Error(Exception? e)
{
Log(e.Message, e.Source, LogLevel.ERROR);
}
private async void Log(LogMessage message)
{
LogEvent?.Invoke(message.Message, message.Type);
if (message.Type != LogLevel.ERROR && message.Type != LogLevel.CRITICAL)
LogHistory.Add(message);
else
ErrorHistory.Add(message);
if (_continuousSave)
await SaveToFile();
}
public void Log(string message, object sender, LogLevel type = LogLevel.INFO)
{
Log(message, sender.GetType().Name, type);
}
public async Task SaveToFile()
{
await SaveToTxt();
}
private async Task SaveToTxt()
{
if (!_LogErrorsOnly)
{
var logFile = new LogFile(_logFolder + $"/{DateTime.Today.ToShortDateString().Replace('/', '_')}_log.txt");
foreach (var logMessage in LogHistory)
logFile.Write(logMessage);
}
var errFile = new LogFile(_errFolder + $"/{DateTime.Today.ToShortDateString().Replace('/', '_')}_err.txt");
foreach (var logMessage in ErrorHistory)
errFile.Write(logMessage);
}
}

View File

@@ -0,0 +1,78 @@
using System;
using System.Linq;
using PluginManager.Interfaces.Logger;
namespace PluginManager.Others.Logger;
public class Log : ILog
{
public string Message { get; set; }
public string OutputFile { get; set; }
public Type? Source { get; set; }
public LogType Type { get; set; }
public DateTime ThrowTime { get; set; }
public Log(string message, string outputFile, Type? source, LogType type, DateTime throwTime)
{
Message = message;
OutputFile = outputFile;
Source = source;
Type = type;
ThrowTime = throwTime;
}
public Log(string message, string outputFile, Type? source, LogType type)
{
Message = message;
OutputFile = outputFile;
Source = source;
Type = type;
ThrowTime = DateTime.Now;
}
public Log(string message, string outputFile, Type? source)
{
Message = message;
OutputFile = outputFile;
Source = source;
Type = LogType.INFO;
ThrowTime = DateTime.Now;
}
public Log(string message, string outputFile)
{
Message = message;
OutputFile = outputFile;
Source = typeof(Log);
Type = LogType.INFO;
ThrowTime = DateTime.Now;
}
public Log(string message)
{
Message = message;
OutputFile = "";
Source = typeof(Log);
Type = LogType.INFO;
ThrowTime = DateTime.Now;
}
public static implicit operator Log(string message) => new (message);
public static implicit operator string(Log log) => $"[{log.ThrowTime}] {log.Message}";
public string AsLongString()
{
return $"[{ThrowTime}] [{Source}] [{Type}] {Message}";
}
public string AsShortString()
{
return this;
}
public string FormatedLongString()
{
return $"[{ThrowTime}]\t[{Source}]\t\t\t[{Type}]\t{Message}";
}
}

View File

@@ -1,36 +0,0 @@
using System.IO;
namespace PluginManager.Others.Logger;
public class LogFile
{
public FileInfo File { get; set; }
public LogFile(string path)
{
File = new FileInfo(path);
}
public void Write(string message)
{
using var sw = File.AppendText();
sw.WriteLine(message);
}
public void Write(string message, LogLevel type)
{
using var sw = File.AppendText();
sw.WriteLine($"[{type}] {message}");
}
public void Write(string message, string sender, LogLevel type)
{
using var sw = File.AppendText();
sw.WriteLine($"[{type}] [{sender}] {message}");
}
public void Write(LogMessage logMessage)
{
using var sw = File.AppendText();
sw.WriteLine(logMessage.ToString());
}
}

View File

@@ -1,51 +0,0 @@
using System;
namespace PluginManager.Others.Logger;
public class LogMessage
{
public LogMessage(string message, LogLevel type)
{
Message = message;
Type = type;
Time = DateTime.Now.ToString("HH:mm:ss");
isInternal = false;
}
public LogMessage(string message, LogLevel type, string sender, bool isInternal) : this(message, type)
{
Sender = sender;
this.isInternal = isInternal;
}
public LogMessage(string message, LogLevel type, string sender) : this (message, type, sender, false)
{
}
public string Message { get; set; }
public LogLevel Type { get; set; }
public string Time { get; set; }
public string Sender { get; set; }
public bool isInternal { get; set; }
public override string ToString()
{
return $"[{Time}] {Message}";
}
public static explicit operator LogMessage(string message)
{
return new LogMessage(message, LogLevel.INFO);
}
public static explicit operator LogMessage((string message, LogLevel type) tuple)
{
return new LogMessage(tuple.message, tuple.type);
}
public static explicit operator LogMessage((string message, LogLevel type, string sender) tuple)
{
return new LogMessage(tuple.message, tuple.type, tuple.sender);
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using PluginManager.Interfaces.Logger;
namespace PluginManager.Others.Logger;
public sealed class Logger : ILogger
{
public bool IsEnabled { get; init; }
public bool OutputToFile { get; init; }
public LogType LowestLogLevel { get; set; }
private bool UseShortVersion { get; }
public Logger(bool useShortVersion, bool outputToFile, LogType lowestLogLevel = LogType.INFO)
{
UseShortVersion = useShortVersion;
OutputToFile = outputToFile;
IsEnabled = true;
LowestLogLevel = lowestLogLevel;
}
public event EventHandler<Log>? OnLog;
private async Task Log(Log logMessage)
{
if (!IsEnabled) return;
OnLog?.Invoke(this, logMessage);
if (logMessage.Type < LowestLogLevel) return;
if (OutputToFile)
await File.AppendAllTextAsync(
logMessage.OutputFile,
(UseShortVersion ? logMessage : logMessage.AsLongString()) + "\n");
}
public async Task Log(string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO, DateTime throwTime = default)
{
if (!IsEnabled) return;
if (type < LowestLogLevel) return;
if (string.IsNullOrEmpty(message)) return;
if (string.IsNullOrEmpty(outputFile)) outputFile = Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
if(throwTime == default) throwTime = DateTime.Now;
if (source == default) source = typeof(Log);
await Log(new Log(message, outputFile, source, type, throwTime));
}
}

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using PluginManager.Others.Exceptions;
namespace PluginManager.Others;
@@ -16,10 +15,8 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
_file = file;
if (!LoadFromFile())
{
ConfigFailedToLoad.CreateError("Failed to load config")
.AppendError("The file is empty or does not exist")
.IsFatal()
.HandleException();
_dictionary = new Dictionary<TKey, TValue>();
SaveToFile();
}
}
@@ -50,10 +47,6 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
}
catch
{
ConfigFailedToLoad
.CreateError("Failed to load config")
.IsFatal()
.HandleException();
return false;
}
@@ -126,11 +119,6 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s))
return this._dictionary[key];
ConfigNoKeyWasPresent.CreateError($"Key {(key is string ? key : typeof(TKey).Name)} was not present in {_file ?? "config"}")
.AppendError("Deleting the file may fix this issue")
.IsFatal()
.HandleException();
return default!;
}
set => this._dictionary![key] = value;