diff --git a/Entities/LogEntry.cs b/Entities/LogEntry.cs index e041532..7bbb8b9 100644 --- a/Entities/LogEntry.cs +++ b/Entities/LogEntry.cs @@ -2,8 +2,11 @@ public class LogEntry { + internal string RawMessage { get; set; } + public DateTime TimeOfEvent { get; set; } public LogLevel LogLevel { get; set; } public string Message { get; set; } + public object[] Args { get; set; } public Exception? Exception { get; set; } } \ No newline at end of file diff --git a/Entities/StringPart.cs b/Entities/StringPart.cs new file mode 100644 index 0000000..bec6aec --- /dev/null +++ b/Entities/StringPart.cs @@ -0,0 +1,13 @@ +namespace Xorog.Logger.Entities; + +internal class StringPart : IDisposable +{ + internal string String { get; set; } + internal ConsoleColor? Color { get; set; } + + public void Dispose() + { + String = ""; + Color = null; + } +} diff --git a/Logger.cs b/Logger.cs index 4ed574a..d1a77ab 100644 --- a/Logger.cs +++ b/Logger.cs @@ -1,4 +1,6 @@ -namespace Xorog.Logger; +using Newtonsoft.Json; + +namespace Xorog.Logger; #pragma warning disable IDE1006 // Naming Styles @@ -92,10 +94,7 @@ public class Logger : ILogger continue; } - string LogLevelText = currentLog.LogLevel.ToString(); - - if (LogLevelText.Length < 6) - LogLevelText += new string(' ', 6 - LogLevelText.Length); + string LogLevelText = $"{currentLog.LogLevel,-6}"; ConsoleColor LogLevelColor; ConsoleColor BackgroundColor; @@ -118,19 +117,86 @@ public class Logger : ILogger _ => ConsoleColor.Black }; - string LogMessage = currentLog.Message; + string leftOver = currentLog.RawMessage; foreach (var blacklistobject in handler.Blacklist) - LogMessage = LogMessage.Replace(blacklistobject, new String('*', blacklistobject.Length), StringComparison.CurrentCultureIgnoreCase); + leftOver = leftOver.Replace(blacklistobject, new String('*', blacklistobject.Length), StringComparison.CurrentCultureIgnoreCase); + + int currentArg = 0; + bool inTemplate = false; + List builder = new(); + + while (leftOver.Length > 0) + { + if (inTemplate && currentLog.Args?.Length >= currentArg) + { + int endIndex = leftOver.IndexOf('}'); + + object objectToAdd = currentLog.Args[currentArg]; + currentArg++; + + if (objectToAdd.GetType() == typeof(int)) + builder.Add(new StringPart { String = objectToAdd.ToString(), Color = ConsoleColor.Cyan }); + else if (objectToAdd.GetType() == typeof(long)) + builder.Add(new StringPart { String = objectToAdd.ToString(), Color = ConsoleColor.Cyan }); + else if (objectToAdd.GetType() == typeof(uint)) + builder.Add(new StringPart { String = objectToAdd.ToString(), Color = ConsoleColor.Cyan }); + else if (objectToAdd.GetType() == typeof(ulong)) + builder.Add(new StringPart { String = objectToAdd.ToString(), Color = ConsoleColor.Cyan }); + else + builder.Add(new StringPart { String = objectToAdd.ToString(), Color = ConsoleColor.DarkGray }); + + inTemplate = false; + + leftOver = leftOver[(endIndex + 1)..]; + continue; + } + + inTemplate = false; + + int placeholderIndex = leftOver.IndexOf('{'); + + if (placeholderIndex != -1 && currentLog.Args?.Length >= currentArg) + inTemplate = true; + + if (placeholderIndex is -1 or 0 || placeholderIndex > leftOver.Length) + placeholderIndex = leftOver.Length; + + builder.Add(new StringPart { String = leftOver[..placeholderIndex] }); + leftOver = leftOver[placeholderIndex..]; + } if (handler.maxLogLevel >= currentLog.LogLevel) { Console.ResetColor(); Console.Write($"[{currentLog.TimeOfEvent:dd.MM.yyyy HH:mm:ss:fff}] "); - Console.ForegroundColor = LogLevelColor; Console.BackgroundColor = BackgroundColor; Console.Write($"[{LogLevelText}]"); - Console.ResetColor(); Console.WriteLine($" {LogMessage}"); + Console.ForegroundColor = LogLevelColor; Console.BackgroundColor = BackgroundColor; Console.Write($"[{LogLevelText}]"); Console.ResetColor(); Console.Write(" "); + + foreach (StringPart part in builder) + { + Console.ForegroundColor = part.Color ?? ConsoleColor.White; + Console.BackgroundColor = ConsoleColor.Black; + + Console.Write($"{part.String}"); + } + Console.ResetColor(); + Console.WriteLine(); if (currentLog.Exception is not null) - Console.WriteLine(currentLog.Exception); + try + { + Console.WriteLine(JsonConvert.SerializeObject(currentLog.Exception, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore })); + } + catch (Exception) + { + Console.WriteLine(currentLog.Exception); + } + } + + currentLog.Message = string.Join("", builder.Select(x => x.String)); + + for (int i1 = 0; i1 < builder.Count; i1++) + { + builder[i1].Dispose(); } _ = Task.Run(() => @@ -142,7 +208,7 @@ public class Logger : ILogger { if (!handler.FileBlackList.Contains(currentLog.LogLevel)) { - Byte[] FileWrite = Encoding.UTF8.GetBytes($"[{currentLog.TimeOfEvent:dd.MM.yyyy HH:mm:ss:fff}] [{LogLevelText}] {LogMessage}\n{(currentLog.Exception is not null ? $"{currentLog.Exception}\n" : "")}"); + Byte[] FileWrite = Encoding.UTF8.GetBytes($"[{currentLog.TimeOfEvent:dd.MM.yyyy HH:mm:ss:fff}] [{LogLevelText}] {currentLog.Message}\n{(currentLog.Exception is not null ? $"{currentLog.Exception}\n" : "")}"); if (handler.OpenedFile != null) { await handler.OpenedFile.WriteAsync(FileWrite.AsMemory(0, FileWrite.Length)); @@ -168,8 +234,6 @@ public class Logger : ILogger return handler; } - - /// /// Stops the logger /// @@ -188,181 +252,363 @@ public class Logger : ILogger OpenedFile?.Close(); } - - /// - /// Add blacklisted string to censor automatically + /// Add strings automatically censor on output to console and file. /// - /// - public void AddBlacklist(string blacklist) + /// The strings to censor + public void AddBlacklist(params string[] blacklist) { - Blacklist.Add(blacklist); + for (int i = 0; i < blacklist.Length; i++) + { + Blacklist.Add(blacklist[i]); + } } - + /// /// Add blacklisted log level to not save /// - /// - public void AddLogLevelBlacklist(LogLevel level) + /// The log levels not to save to the log file + public void AddLogLevelBlacklist(params LogLevel[] levels) { - FileBlackList.Add(level); + for (int i = 0; i < levels.Length; i++) + { + FileBlackList.Add(levels[i]); + } } - - /// /// Changes the log level /// - /// - public void ChangeLogLevel(LogLevel level) - { - maxLogLevel = level; - } - - + /// The new log level to apply + public void ChangeLogLevel(LogLevel level) => maxLogLevel = level; /// /// Log with none log level /// - /// - /// - public void LogNone(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogNone(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.NONE, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.NONE, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with none log level + /// + /// The message to display + /// The exception that was caused + public void LogNone(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.NONE, + RawMessage = message, + Exception = exception + }); + /// + /// Log with none log level + /// + /// The message to display + /// The objects involved in the event + public void LogNone(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.NONE, + RawMessage = message, + Args = args + }); /// /// Log with trace log level /// - /// - /// - public void LogTrace(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogTrace(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.TRACE, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.TRACE, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with trace log level + /// + /// The message to display + /// The exception that was caused + public void LogTrace(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.TRACE, + RawMessage = message, + Exception = exception + }); + /// + /// Log with trace log level + /// + /// The message to display + /// The objects involved in the event + public void LogTrace(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.TRACE, + RawMessage = message, + Args = args, + }); /// /// Log with debug2 log level /// - /// - /// - public void LogDebug2(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogDebug2(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.DEBUG2, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG2, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with debug2 log level + /// + /// The message to display + /// The exception that was caused + public void LogDebug2(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG2, + RawMessage = message, + Exception = exception + }); + /// + /// Log with debug2 log level + /// + /// The message to display + /// The objects involved in the event + public void LogDebug2(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG2, + RawMessage = message, + Args = args + }); /// /// Log with debug log level /// - /// - /// - public void LogDebug(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogDebug(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.DEBUG, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with debug log level + /// + /// The message to display + /// The exception that was caused + public void LogDebug(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG, + RawMessage = message, + Exception = exception + }); + /// + /// Log with debug log level + /// + /// The message to display + /// The objects involved in the event + public void LogDebug(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.DEBUG, + RawMessage = message, + Args = args + }); /// /// Log with info log level /// - /// - /// - public void LogInfo(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogInfo(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.INFO, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.INFO, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with info log level + /// + /// The message to display + /// The exception that was caused + public void LogInfo(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.INFO, + RawMessage = message, + Exception = exception + }); + /// + /// Log with info log level + /// + /// The message to display + /// The objects involved in the event + public void LogInfo(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.INFO, + RawMessage = message, + Args = args + }); /// /// Log with warn log level /// - /// - /// - public void LogWarn(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogWarn(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.WARN, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.WARN, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with warn log level + /// + /// The message to display + /// The exception that was caused + public void LogWarn(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.WARN, + RawMessage = message, + Exception = exception + }); + /// + /// Log with warn log level + /// + /// The message to display + /// The objects involved in the event + public void LogWarn(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.WARN, + RawMessage = message, + Args = args + }); /// /// Log with error log level /// - /// - /// - public void LogError(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogError(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.ERROR, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.ERROR, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with error log level + /// + /// The message to display + /// The exception that was caused + public void LogError(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.ERROR, + RawMessage = message, + Exception = exception + }); + /// + /// Log with error log level + /// + /// The message to display + /// The objects involved in the event + public void LogError(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.ERROR, + RawMessage = message, + Args = args + }); /// /// Log with fatal log level /// - /// - /// - public void LogFatal(string message, Exception? exception = null) + /// The message to display + /// The exception that was caused + /// The objects involved in the event + public void LogFatal(string message, Exception? exception = null, params object[] args) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry - { - TimeOfEvent = DateTime.Now, - LogLevel = LogLevel.FATAL, - Message = message, - Exception = exception - }); - } + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.FATAL, + RawMessage = message, + Args = args, + Exception = exception + }); + /// + /// Log with fatal log level + /// + /// The message to display + /// The exception that was caused + public void LogFatal(string message, Exception? exception = null) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.FATAL, + RawMessage = message, + Exception = exception + }); + + /// + /// Log with fatal log level + /// + /// The message to display + /// The objects involved in the event + public void LogFatal(string message, params object[] args) => LogsToPost.Add(new LogEntry + { + TimeOfEvent = DateTime.Now, + LogLevel = LogLevel.FATAL, + RawMessage = message, + Args = args + }); /// /// Log with standard Microsoft.Extensions.Logging format @@ -373,38 +619,27 @@ public class Logger : ILogger /// /// /// - public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) => LogsToPost.Add(new LogEntry { - LogsToPost.Add(new LogEntry + TimeOfEvent = DateTime.Now, + LogLevel = logLevel switch { - TimeOfEvent = DateTime.Now, - LogLevel = logLevel switch - { - Microsoft.Extensions.Logging.LogLevel.Debug => LogLevel.DEBUG2, - Microsoft.Extensions.Logging.LogLevel.Trace => LogLevel.TRACE2, - Microsoft.Extensions.Logging.LogLevel.Information => LogLevel.INFO, - Microsoft.Extensions.Logging.LogLevel.Warning => LogLevel.WARN, - Microsoft.Extensions.Logging.LogLevel.Error => LogLevel.ERROR, - Microsoft.Extensions.Logging.LogLevel.Critical => LogLevel.FATAL, - Microsoft.Extensions.Logging.LogLevel.None => LogLevel.NONE, - _ => throw new NotImplementedException() - }, - Message = $"[{eventId.Id,2}] {formatter(state, exception)}", - Exception = exception - }); - } - - - - public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) - { - return loggerStarted; - } - + Microsoft.Extensions.Logging.LogLevel.Debug => LogLevel.DEBUG2, + Microsoft.Extensions.Logging.LogLevel.Trace => LogLevel.TRACE2, + Microsoft.Extensions.Logging.LogLevel.Information => LogLevel.INFO, + Microsoft.Extensions.Logging.LogLevel.Warning => LogLevel.WARN, + Microsoft.Extensions.Logging.LogLevel.Error => LogLevel.ERROR, + Microsoft.Extensions.Logging.LogLevel.Critical => LogLevel.FATAL, + Microsoft.Extensions.Logging.LogLevel.None => LogLevel.NONE, + _ => LogLevel.NONE, + }, + RawMessage = $"[{eventId.Id}] {formatter(state, exception)}", + Exception = exception + }); + public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) + => loggerStarted; public IDisposable BeginScope(TState state) - { - return default!; - } + => default!; } diff --git a/Xorog.Logger.csproj b/Xorog.Logger.csproj index 1b0335d..d221006 100644 --- a/Xorog.Logger.csproj +++ b/Xorog.Logger.csproj @@ -34,6 +34,7 @@ +