Skip to content

Commit

Permalink
Merge pull request #148 from K07H/master
Browse files Browse the repository at this point in the history
Updated Logger class.
  • Loading branch information
PrimeSonic committed Jun 27, 2020
2 parents 04f5c4b + f55fa70 commit 3ef564d
Showing 1 changed file with 121 additions and 77 deletions.
198 changes: 121 additions & 77 deletions QModManager/Utility/Logger.cs
Original file line number Diff line number Diff line change
@@ -1,127 +1,171 @@
namespace QModManager.Utility
{
using System;
using System.Diagnostics;
using System.IO;

internal static class Logger
/// <summary>A simple logging class. Can be used for basic logging or to know which logging level is enabled.</summary>
public static class Logger
{
internal enum Level
/// <summary>Possible logging levels.</summary>
public enum Level
{
/// <summary>Debugging log level</summary>
Debug,
/// <summary>Informational log level</summary>
Info,
/// <summary>Warning log level</summary>
Warn,
/// <summary>Error log level</summary>
Error,
/// <summary>Fatal log level</summary>
Fatal
}

private static void Log(string logLevel, params string[] text)
private const string AssemblyName = "QModManager";

#region Private functions (used by the Logger)

private static string GetCallingAssemblyName() => ReflectionHelper.CallingAssemblyByStackTrace()?.GetName().Name;

private static void Debug(string msg, bool showOnScreen = false, string callingAssembly = null, bool force = false)
{
if (text == null || text.Length < 1)
if (!force && !Config.EnableDebugLogs)
return;

string from;
Type classType = GetCallingClass();
Console.WriteLine($"[{callingAssembly ?? GetCallingAssemblyName()}:DEBUG] {msg}");

if (classType == null)
from = null;
else if (classType.Namespace.Contains("SMLHelper"))
from = "SMLHelper";
else
from = classType.Name;
if (showOnScreen)
ErrorMessage.AddDebug(msg);
}

string toWrite = "[QModManager] ";
if (!string.IsNullOrEmpty(from) && !from.Contains("<>"))
toWrite += $"[{from}] ";
else if (!string.IsNullOrEmpty(from) && from.Contains("<>"))
toWrite += $"[Anonymous] ";
if (!string.IsNullOrEmpty(logLevel))
toWrite += $"[{logLevel}] ";
private static void Info(string msg, bool showOnScreen = false, string callingAssembly = null)
{
Console.WriteLine($"[{callingAssembly ?? GetCallingAssemblyName()}:INFO] {msg}");

int length = toWrite.Length;
if (showOnScreen)
ErrorMessage.AddMessage(msg);
}

Console.WriteLine($"{toWrite}{text[0]}");
private static void Warn(string msg, bool showOnScreen = false, string callingAssembly = null)
{
Console.WriteLine($"[{callingAssembly ?? GetCallingAssemblyName()}:WARN] {msg}");

for (int i = 1; i < text.Length; i++)
Console.WriteLine($"{text[i]}");
if (showOnScreen)
ErrorMessage.AddWarning(msg);
}

internal static void Log(params string[] text)
private static void Error(string msg = null, Exception ex = null, bool showOnScreen = false, string callingAssembly = null)
{
Log("", text);
if (ex != null)
msg = (string.IsNullOrEmpty(msg) ? ex.ToString() : msg + Environment.NewLine + ex.ToString());

Console.WriteLine($"[{callingAssembly ?? GetCallingAssemblyName()}:ERROR] {msg}");

if (showOnScreen && !string.IsNullOrEmpty(msg))
ErrorMessage.AddError(msg);
}

internal static void Log(Level logLevel, params string[] text)
private static void Exception(Exception e, bool selfAssembly = false) => Error(null, e, false, selfAssembly ? AssemblyName : GetCallingAssemblyName());

private static void Fatal(string msg = null, Exception ex = null, bool showOnScreen = false, string callingAssembly = null)
{
if (ex != null)
msg = (string.IsNullOrEmpty(msg) ? ex.ToString() : msg + Environment.NewLine + ex.ToString());
Console.WriteLine($"[{callingAssembly ?? GetCallingAssemblyName()}:FATAL] {msg}");

if (showOnScreen && !string.IsNullOrEmpty(msg))
ErrorMessage.AddError(msg);
}

#endregion

#region Internal functions (used by QModManager)

internal static void Debug(string msg) => Debug(msg, false, AssemblyName, false);

internal static void DebugForce(string msg) => Debug(msg, false, AssemblyName, true);

internal static void Info(string msg) => Info(msg, false, AssemblyName);

internal static void Warn(string msg) => Warn(msg, false, AssemblyName);

internal static void Error(string msg) => Error(msg, null, false, AssemblyName);

internal static void Exception(Exception e) => Exception(e, true);

internal static void Fatal(string msg) => Fatal(msg, null, false, AssemblyName);

internal static void Log(Level logLevel, string msg)
{
if (msg == null) // Return if there is no messages
return;

switch (logLevel)
{
case Level.Debug:
Debug(text);
break;
case Level.Info:
Info(text);
Debug(msg);
break;
case Level.Warn:
Warn(text);
Warn(msg);
break;
case Level.Error:
Error(text);
Error(msg);
break;
case Level.Fatal:
Fatal(text);
Fatal(msg);
break;
default: // Defaults to informational logging
Info(msg);
break;
}
}

internal static void Debug(params string[] text)
{
if (Config.EnableDebugLogs)
Log("Debug", text);
}

internal static void DebugForce(params string[] text)
{
Log("Debug", text);
}

internal static void Info(params string[] text)
{
Log("Info", text);
}
#endregion

internal static void Warn(params string[] text)
{
Log("Warn", text);
}
#region Public functions (used by mods)

internal static void Error(params string[] text)
{
Log("Error", text);
}

internal static void Exception(Exception e)
{
Log("Exception", e.ToString());
}

internal static void Fatal(params string[] text)
{
Log("Fatal", text);
}
/// <summary>Used to know if debug logging is enabled or not.</summary>
public static bool DebugLogsEnabled => Config.EnableDebugLogs;

private static Type GetCallingClass()
/// <summary>
/// This function will log given message and/or exception. It can optionally show the message on screen.
/// You need to provide a message and/or an exception (this function will do nothing if both are set to null).
/// Warning: You can call this function from any mod but don't call it from QModManager (<see cref="GetCallingAssemblyName"/> would fail).
/// </summary>
/// <param name="logLevel">The level of the log.</param>
/// <param name="msg">Optional: The message that needs to be logged.</param>
/// <param name="ex">Optional: The exception that needs to be logged.</param>
/// <param name="showOnScreen">Optional: Whether to show the message on screen or not.</param>
public static void Log(Level logLevel, string msg = null, Exception ex = null, bool showOnScreen = false)
{
var stackTrace = new StackTrace();
StackFrame[] frames = stackTrace.GetFrames();

foreach (StackFrame stackFrame in frames)
if (ex != null)
{
Type declaringClass = stackFrame.GetMethod().DeclaringType;
if (declaringClass != typeof(Logger))
return declaringClass;
// If exception was provided, concatenate its message to the log message
if (logLevel != Level.Error && logLevel != Level.Fatal)
msg = (msg == null) ? ex.Message : msg + Environment.NewLine + ex.Message;
}
else if (msg == null) // Return if both given message and exception were null
return;

return null;
switch (logLevel)
{
case Level.Debug:
Debug(msg, showOnScreen, null, false);
break;
case Level.Warn:
Warn(msg, showOnScreen, null);
break;
case Level.Error:
Error(msg, ex, showOnScreen, null);
break;
case Level.Fatal:
Fatal(msg, ex, showOnScreen, null);
break;
default: // Defaults to informational logging
Info(msg, showOnScreen, null);
break;
}
}

#endregion
}
}

0 comments on commit 3ef564d

Please sign in to comment.