From 4627e103fea07aea01ef831380b5762ad142bed2 Mon Sep 17 00:00:00 2001 From: EonaCat Date: Wed, 12 Jul 2023 18:19:28 +0200 Subject: [PATCH] Added test program --- EonaCat.Logger.sln | 26 ++ EonaCat.Logger/Enums.cs | 52 +++- EonaCat.Logger/EonaCat.Logger.csproj | 2 +- .../Internal/BatchingLogger.cs | 1 + .../Internal/BatchingLoggerProvider.cs | 7 +- .../Extensions/ExceptionExtensions.cs | 72 +++++ EonaCat.Logger/Managers/EFileLoggingMode.cs | 8 - EonaCat.Logger/Managers/ILogManager.cs | 8 +- EonaCat.Logger/Managers/LogHelper.cs | 268 ++++++------------ EonaCat.Logger/Managers/LogManager.cs | 165 +++++------ EonaCat.Logger/Managers/LoggerSettings.cs | 20 +- LoggerTest/LoggerTest.csproj | 14 + LoggerTest/Program.cs | 14 + 13 files changed, 351 insertions(+), 306 deletions(-) create mode 100644 EonaCat.Logger/Extensions/ExceptionExtensions.cs delete mode 100644 EonaCat.Logger/Managers/EFileLoggingMode.cs create mode 100644 LoggerTest/LoggerTest.csproj create mode 100644 LoggerTest/Program.cs diff --git a/EonaCat.Logger.sln b/EonaCat.Logger.sln index e4aa6d2..dc85b7e 100644 --- a/EonaCat.Logger.sln +++ b/EonaCat.Logger.sln @@ -5,16 +5,42 @@ VisualStudioVersion = 17.3.32811.315 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EonaCat.Logger", "EonaCat.Logger\EonaCat.Logger.csproj", "{DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggerTest", "LoggerTest\LoggerTest.csproj", "{3530C36E-E245-43E1-8C5C-9FBCA450728F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|x64.Build.0 = Debug|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Debug|x86.Build.0 = Debug|Any CPU {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|Any CPU.Build.0 = Release|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|x64.ActiveCfg = Release|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|x64.Build.0 = Release|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|x86.ActiveCfg = Release|Any CPU + {DCD1D32E-0F24-4D0F-A6B6-59941C0F9BB7}.Release|x86.Build.0 = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|x64.ActiveCfg = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|x64.Build.0 = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|x86.ActiveCfg = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Debug|x86.Build.0 = Debug|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|Any CPU.Build.0 = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|x64.ActiveCfg = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|x64.Build.0 = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|x86.ActiveCfg = Release|Any CPU + {3530C36E-E245-43E1-8C5C-9FBCA450728F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/EonaCat.Logger/Enums.cs b/EonaCat.Logger/Enums.cs index 6b99454..aa60994 100644 --- a/EonaCat.Logger/Enums.cs +++ b/EonaCat.Logger/Enums.cs @@ -35,8 +35,33 @@ namespace EonaCat.Logger return ELogType.WARNING; case LogLevel.Trace: return ELogType.TRACE; - default: + case LogLevel.Information: return ELogType.INFO; + default: + return ELogType.TRAFFIC; + } + } + + public static LogLevel ToLogLevel(this ELogType logLevel) + { + switch (logLevel) + { + case ELogType.NONE: + return LogLevel.None; + case ELogType.ERROR: + return LogLevel.Error; + case ELogType.DEBUG: + return LogLevel.Debug; + case ELogType.CRITICAL: + return LogLevel.Critical; + case ELogType.WARNING: + return LogLevel.Warning; + case ELogType.TRACE: + return LogLevel.Trace; + case ELogType.INFO: + return LogLevel.Information; + default: + return LogLevel.Trace; } } @@ -49,17 +74,38 @@ namespace EonaCat.Logger case ESeverity.Warn: return ELogType.WARNING; case ESeverity.Emergency: - return ELogType.CRITICAL; + return ELogType.TRACE; case ESeverity.Critical: return ELogType.CRITICAL; case ESeverity.Alert: - return ELogType.ERROR; + return ELogType.TRAFFIC; case ESeverity.Error: return ELogType.ERROR; default: return ELogType.INFO; } } + + public static ESeverity ToSeverity(this ELogType logLevel) + { + switch (logLevel) + { + case ELogType.DEBUG: + return ESeverity.Debug; + case ELogType.WARNING: + return ESeverity.Warn; + case ELogType.CRITICAL: + return ESeverity.Critical; + case ELogType.TRACE: + return ESeverity.Emergency; + case ELogType.ERROR: + return ESeverity.Error; + case ELogType.TRAFFIC: + return ESeverity.Alert; + default: + return ESeverity.Info; + } + } } /// diff --git a/EonaCat.Logger/EonaCat.Logger.csproj b/EonaCat.Logger/EonaCat.Logger.csproj index 1066dd7..ecf5819 100644 --- a/EonaCat.Logger/EonaCat.Logger.csproj +++ b/EonaCat.Logger/EonaCat.Logger.csproj @@ -8,7 +8,7 @@ net7.0; icon.ico - 1.1.1 + 1.1.4 EonaCat (Jeroen Saey) true EonaCat (Jeroen Saey) diff --git a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs index 374ce80..2291646 100644 --- a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs +++ b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs @@ -1,5 +1,6 @@ using System; using EonaCat.Logger.EonaCatCoreLogger.Models; +using EonaCat.Logger.Extensions; using EonaCat.Logger.Managers; using Microsoft.Extensions.Logging; diff --git a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs index aeb3faa..142de19 100644 --- a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs +++ b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using EonaCat.Logger.Managers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -40,7 +41,11 @@ namespace EonaCat.Logger.EonaCatCoreLogger.Internal private async Task ProcessLogQueueAsync(object state) { - await WriteMessagesAsync(new List { new LogMessage { Message = $"[{DllInfo.ApplicationName}] {DllInfo.ApplicationName} started.{Environment.NewLine}", Timestamp = DateTimeOffset.Now } }, _cancellationTokenSource.Token).ConfigureAwait(false); + var startupMessage = $"{DllInfo.ApplicationName} started.{Environment.NewLine}"; + startupMessage = LogHelper.FormatMessageWithHeader(new LoggerSettings(), ELogType.INFO, startupMessage, DateTime.Now); + + AddMessage(DateTimeOffset.Now, startupMessage); + while (!_cancellationTokenSource.IsCancellationRequested) { int limit = _batchSize <= 0 ? int.MaxValue : _batchSize; diff --git a/EonaCat.Logger/Extensions/ExceptionExtensions.cs b/EonaCat.Logger/Extensions/ExceptionExtensions.cs new file mode 100644 index 0000000..2ba23d5 --- /dev/null +++ b/EonaCat.Logger/Extensions/ExceptionExtensions.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.Text; + +namespace EonaCat.Logger.Extensions +{ + public static class ExceptionExtensions + { + public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null) + { + if (exception == null) + return string.Empty; + + var st = new StackTrace(exception, true); + var frame = st.GetFrame(0); + int fileLine = frame.GetFileLineNumber(); + string filename = frame.GetFileName(); + + StringBuilder sb = new StringBuilder(); + + sb.AppendLine(); + sb.AppendLine("--- Exception details provided by EonaCatLogger ---"); + if (!string.IsNullOrEmpty(module)) + sb.AppendLine(" Module : " + module); + if (!string.IsNullOrEmpty(method)) + sb.AppendLine(" Method : " + method); + sb.Append(" Type : ").AppendLine(exception.GetType().ToString()); + sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0 ? FormatExceptionData(exception.Data) : "(none)"); + sb.Append(" Inner : ").AppendLine(exception.InnerException != null ? FormatInnerException(exception.InnerException) : "(null)"); + sb.Append(" Message : ").AppendLine(exception.Message); + sb.Append(" Source : ").AppendLine(exception.Source); + sb.Append(" StackTrace : ").AppendLine(exception.StackTrace); + sb.Append(" Line : ").AppendLine(fileLine.ToString()); + sb.Append(" File : ").AppendLine(filename); + sb.Append(" ToString : ").AppendLine(exception.ToString()); + sb.AppendLine("---"); + + return sb.ToString(); + } + + private static string FormatExceptionData(IDictionary data) + { + StringBuilder sb = new StringBuilder(); + + foreach (DictionaryEntry entry in data) + { + sb.Append(" | ") + .Append(entry.Key) + .Append(": ") + .AppendLine(entry.Value.ToString()); + } + + return sb.ToString(); + } + + private static string FormatInnerException(Exception innerException) + { + StringBuilder sb = new StringBuilder(); + + sb.AppendLine(innerException.GetType().ToString()) + .AppendLine(" Message : " + innerException.Message) + .AppendLine(" Source : " + innerException.Source) + .AppendLine(" StackTrace : " + innerException.StackTrace) + .AppendLine(" ToString : " + innerException.ToString()) + .Append(" Data : ") + .AppendLine(innerException.Data != null && innerException.Data.Count > 0 ? FormatExceptionData(innerException.Data) : "(none)"); + + return sb.ToString(); + } + } +} diff --git a/EonaCat.Logger/Managers/EFileLoggingMode.cs b/EonaCat.Logger/Managers/EFileLoggingMode.cs deleted file mode 100644 index aa887b3..0000000 --- a/EonaCat.Logger/Managers/EFileLoggingMode.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace EonaCat.Logger.Managers -{ - public enum EFileLoggingMode - { - Enabled = 0, - Disabled = 1, - } -} \ No newline at end of file diff --git a/EonaCat.Logger/Managers/ILogManager.cs b/EonaCat.Logger/Managers/ILogManager.cs index b5ecc86..6427feb 100644 --- a/EonaCat.Logger/Managers/ILogManager.cs +++ b/EonaCat.Logger/Managers/ILogManager.cs @@ -1,7 +1,13 @@ -namespace EonaCat.Logger.Managers +using System; +using System.Threading.Tasks; + +namespace EonaCat.Logger.Managers { public interface ILogManager { void Write(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null); + + void Write(Exception exception, string module = null, string method = null, bool criticalException = false, + bool? writeToConsole = null); } } \ No newline at end of file diff --git a/EonaCat.Logger/Managers/LogHelper.cs b/EonaCat.Logger/Managers/LogHelper.cs index 4b2869f..e6992c6 100644 --- a/EonaCat.Logger/Managers/LogHelper.cs +++ b/EonaCat.Logger/Managers/LogHelper.cs @@ -1,160 +1,98 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Text; -using System.Threading; -using System.Threading.Tasks; using EonaCat.Logger.Syslog; using Microsoft.Extensions.Logging; namespace EonaCat.Logger.Managers { - public static class LogHelper + internal static class LogHelper { - private static readonly object FileLock = new object(); - internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage, DateTime dateTime) { if (string.IsNullOrWhiteSpace(currentMessage)) return currentMessage; - string header = settings?.HeaderFormat ?? "[EonaCatLogger]"; - - if (header.Contains("{ts}")) - header = header.Replace("{ts}", dateTime.ToString(settings?.TimestampFormat)); - - if (header.Contains("{host}")) - header = header.Replace("{host}", Dns.GetHostName()); - - if (header.Contains("{thread}")) - header = header.Replace("{thread}", Thread.CurrentThread.ManagedThreadId.ToString()); - - if (header.Contains("{sev}")) - header = header.Replace("{sev}", logType.ToString()); - - string fullMessage = AddHeaderIfNotExists(settings, header, currentMessage); - return fullMessage; - } - - private static string AddHeaderIfNotExists(LoggerSettings settings, string header, string currentMessage) - { - if (settings == null || !settings.RemoveMessagePrefix) - { - if (!currentMessage.Contains("[EonaCatLogger]")) - return "[EonaCatLogger] " + header + " " + currentMessage; - } - - return header + " " + currentMessage; - } - - public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null) - { - if (exception == null) - return string.Empty; - - var st = new StackTrace(exception, true); - var frame = st.GetFrame(0); - int fileLine = frame.GetFileLineNumber(); - string filename = frame.GetFileName(); - - string message = - Environment.NewLine + - "--- Exception details provided by EonaCatLogger ---" + Environment.NewLine + - (!string.IsNullOrEmpty(module) ? " Module : " + module + Environment.NewLine : "") + - (!string.IsNullOrEmpty(method) ? " Method : " + method + Environment.NewLine : "") + - " Type : " + exception.GetType().ToString() + Environment.NewLine + - " Data : " + (exception.Data != null && exception.Data.Count > 0 ? Environment.NewLine + FormatExceptionData(exception.Data) : "(none)") + Environment.NewLine + - " Inner : " + (exception.InnerException != null ? FormatInnerException(exception.InnerException) : "(null)") + Environment.NewLine + - " Message : " + exception.Message + Environment.NewLine + - " Source : " + exception.Source + Environment.NewLine + - " StackTrace : " + exception.StackTrace + Environment.NewLine + - " Line : " + fileLine + Environment.NewLine + - " File : " + filename + Environment.NewLine + - " ToString : " + exception.ToString() + Environment.NewLine + - "---"; - - return message; - } - - private static string FormatExceptionData(IDictionary data) - { StringBuilder sb = new StringBuilder(); - foreach (DictionaryEntry entry in data) + sb.Append(settings?.HeaderFormat ?? "[EonaCatLogger]"); + + if (settings != null) { - sb.Append(" | ") - .Append(entry.Key) - .Append(": ") - .Append(entry.Value) - .Append(Environment.NewLine); + if (sb.ToString().Contains("{ts}")) + sb.Replace("{ts}", dateTime.ToString(settings.TimestampFormat)); + + if (sb.ToString().Contains("{host}")) + sb.Replace("{host}", $"[Host:{Dns.GetHostName()}]"); + + if (sb.ToString().Contains("{thread}")) + sb.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId.ToString()}]"); + + if (sb.ToString().Contains("{sev}")) + sb.Replace("{sev}", $"[{logType.ToString()}]"); + + if (!settings.RemoveMessagePrefix && !currentMessage.Contains("[EonaCatLogger]")) + sb.Insert(0, "[EonaCatLogger] "); } + sb.Append(" "); + sb.Append(currentMessage); + return sb.ToString(); } - private static string FormatInnerException(Exception innerException) - { - StringBuilder sb = new StringBuilder(); + - sb.AppendLine(innerException.GetType().ToString()) - .AppendLine(" Message : " + innerException.Message) - .AppendLine(" Source : " + innerException.Source) - .AppendLine(" StackTrace : " + innerException.StackTrace) - .AppendLine(" ToString : " + innerException.ToString()) - .Append(" Data : ") - .AppendLine(innerException.Data != null && innerException.Data.Count > 0 ? Environment.NewLine + FormatExceptionData(innerException.Data) : "(none)"); - - return sb.ToString(); - } - - internal static void SendConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole) + internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole) { if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message)) return; - if (settings.EnableColors) + if (settings.EnableColors && settings.Colors != null) { ConsoleColor prevForeground = Console.ForegroundColor; ConsoleColor prevBackground = Console.BackgroundColor; - if (settings.Colors != null) + ConsoleColor foregroundColor; + ConsoleColor backgroundColor; + switch (logType) { - switch (logType) - { - case ELogType.DEBUG: - Console.ForegroundColor = settings.Colors.Debug.Foreground; - Console.BackgroundColor = settings.Colors.Debug.Background; - break; - case ELogType.INFO: - Console.ForegroundColor = settings.Colors.Info.Foreground; - Console.BackgroundColor = settings.Colors.Info.Background; - break; - case ELogType.WARNING: - Console.ForegroundColor = settings.Colors.Warning.Foreground; - Console.BackgroundColor = settings.Colors.Warning.Background; - break; - case ELogType.ERROR: - Console.ForegroundColor = settings.Colors.Error.Foreground; - Console.BackgroundColor = settings.Colors.Error.Background; - break; - case ELogType.TRAFFIC: - Console.ForegroundColor = settings.Colors.Traffic.Foreground; - Console.BackgroundColor = settings.Colors.Traffic.Background; - break; - case ELogType.CRITICAL: - Console.ForegroundColor = settings.Colors.Critical.Foreground; - Console.BackgroundColor = settings.Colors.Critical.Background; - break; - case ELogType.TRACE: - Console.ForegroundColor = settings.Colors.Trace.Foreground; - Console.BackgroundColor = settings.Colors.Trace.Background; - break; - } + case ELogType.DEBUG: + foregroundColor = settings.Colors.Debug.Foreground; + backgroundColor = settings.Colors.Debug.Background; + break; + case ELogType.INFO: + foregroundColor = settings.Colors.Info.Foreground; + backgroundColor = settings.Colors.Info.Background; + break; + case ELogType.WARNING: + foregroundColor = settings.Colors.Warning.Foreground; + backgroundColor = settings.Colors.Warning.Background; + break; + case ELogType.ERROR: + foregroundColor = settings.Colors.Error.Foreground; + backgroundColor = settings.Colors.Error.Background; + break; + case ELogType.TRAFFIC: + foregroundColor = settings.Colors.Traffic.Foreground; + backgroundColor = settings.Colors.Traffic.Background; + break; + case ELogType.CRITICAL: + foregroundColor = settings.Colors.Critical.Foreground; + backgroundColor = settings.Colors.Critical.Background; + break; + case ELogType.TRACE: + foregroundColor = settings.Colors.Trace.Foreground; + backgroundColor = settings.Colors.Trace.Background; + break; + default: + return; } + Console.ForegroundColor = foregroundColor; + Console.BackgroundColor = backgroundColor; Console.WriteLine(message); Console.ForegroundColor = prevForeground; Console.BackgroundColor = prevBackground; @@ -165,54 +103,20 @@ namespace EonaCat.Logger.Managers } } - internal static void SendFile(ILogger logger, LoggerSettings settings, ELogType logType, string message, int maxTries = 3) + internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message) { - lock (FileLock) - { - if (logger == null || settings == null || !settings.EnableFileLogging || string.IsNullOrWhiteSpace(message)) - return; + if (logger == null || settings == null || !settings.EnableFileLogging || string.IsNullOrWhiteSpace(message)) + return; - int tries = 0; - bool completed = false; - while (!completed) - { - try - { - switch (logType) - { - case ELogType.CRITICAL: - logger.LogCritical(message); - break; - case ELogType.DEBUG: - logger.LogDebug(message); - break; - case ELogType.ERROR: - logger.LogError(message); - break; - case ELogType.INFO: - logger.LogInformation(message); - break; - case ELogType.TRACE: - logger.LogTrace(message); - break; - case ELogType.TRAFFIC: - logger.LogTrace($"[TRAFFIC] {message}"); - break; - case ELogType.WARNING: - logger.LogWarning(message); - break; - } - completed = true; - } - catch (Exception exc) - { - tries++; - Task.Delay(100); - if (tries >= maxTries) - throw; - } - } - } + LogLevel logLevel = logType.ToLogLevel(); + + if (logLevel >= settings.MaxLogType.ToLogLevel()) // Filter out log levels + Log(logger, logLevel, message); + } + + private static void Log(ILogger logger, LogLevel logLevel, string message) + { + logger.Log(logLevel, message); } internal static void SendToSysLogServers(LoggerSettings settings, string message) @@ -227,31 +131,31 @@ namespace EonaCat.Logger.Managers byte[] data = Encoding.UTF8.GetBytes(message); - var sysLogServers = settings.SysLogServers.ToList(); - foreach (SyslogServer server in sysLogServers) + foreach (SyslogServer server in settings.SysLogServers) { + if (string.IsNullOrWhiteSpace(server.Hostname)) + { + Console.WriteLine("Server hostname not specified, skipping syslog server"); + continue; + } + if (server.Port < 0) + { + Console.WriteLine("Server port must be zero or greater, skipping syslog server"); + continue; + } + lock (server.SendLock) { - if (string.IsNullOrWhiteSpace(server.Hostname)) - { - Console.WriteLine("Server hostname not specified, skipping syslog server"); - } - if (server.Port < 0) - { - Console.WriteLine("Server port must be zero or greater, skipping syslog server"); - } - try { server.Udp.Send(data, data.Length); } - catch (Exception) + catch { - + // Do nothing } } } } } - -} \ No newline at end of file +} diff --git a/EonaCat.Logger/Managers/LogManager.cs b/EonaCat.Logger/Managers/LogManager.cs index 9f5d65f..e45748d 100644 --- a/EonaCat.Logger/Managers/LogManager.cs +++ b/EonaCat.Logger/Managers/LogManager.cs @@ -1,21 +1,19 @@ -using EonaCat.Logger.Exceptions; -using EonaCat.Logger.Syslog; +using EonaCat.Logger.Syslog; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using EonaCat.Logger.EonaCatCoreLogger; using EonaCat.Logger.EonaCatCoreLogger.Extensions; using EonaCat.Logger.EonaCatCoreLogger.Models; +using EonaCat.Logger.Extensions; namespace EonaCat.Logger.Managers { - // This file is part of the EonaCat project(s) which is released under the Apache License. - // See the LICENSE file or go to https://EonaCat.com/License for full license details. - public partial class LogManager : ILogManager, IDisposable { private DateTime _logDate; @@ -25,47 +23,41 @@ namespace EonaCat.Logger.Managers public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider ? fileLoggerProvider.LogFile : string.Empty; public bool IsRunning { get; private set; } - public string CategoryName { get; set; } - public string Id { get; } - private bool _disposed; private static LogManager _instance; - private LoggerSettings _settings; + private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource(); public static LogManager Instance => InstanceInit(); - public LoggerSettings Settings - { - get - { - _settings ??= new LoggerSettings(); - return _settings; - } - set => _settings = value; - } + public LoggerSettings Settings { get; } = CreateDefaultSettings(); private static LogManager InstanceInit() { - _instance ??= new LogManager(null, id: "EonaCat"); + if (_instance == null) + { + _instance = new LogManager(CreateDefaultSettings()); + } return _instance; } - protected virtual void Dispose(bool disposing) + private static LoggerSettings CreateDefaultSettings() { - if (_disposed) - return; - - if (disposing) - { - StopLogging(); - _tokenSource.Cancel(); - } - - _disposed = true; + var settings = new LoggerSettings(); + settings.Id = "EonaCatLogger"; + settings.MaxLogType = ELogType.TRACE; + return settings; } - private void StartNewLog() + protected virtual async Task DisposeAsync(bool disposing) + { + if (disposing) + { + await StopLoggingAsync().ConfigureAwait(false); + } + } + + public async Task StartNewLogAsync() { if (_tokenSource.IsCancellationRequested) return; @@ -73,10 +65,19 @@ namespace EonaCat.Logger.Managers DateTime now = DateTime.UtcNow; if (IsRunning && now.Date > _logDate.Date) - StopLogging(); + await StopLoggingAsync().ConfigureAwait(false); IsRunning = true; + CreateLogger(); + + Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory); + + _logDate = now; + } + + private void CreateLogger() + { IServiceCollection serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.AddEonaCatFileLogger(configuration => { @@ -95,55 +96,40 @@ namespace EonaCat.Logger.Managers var serviceProvider = serviceCollection.BuildServiceProvider(); LoggerProvider = serviceProvider.GetService(); LoggerFactory = serviceProvider.GetService(); - - CategoryName ??= string.Empty; - Logger = LoggerFactory.CreateLogger(CategoryName); - - Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory); - - _logDate = now; - - Write(now, $"{DllInfo.ApplicationName} started."); + Logger = LoggerFactory.CreateLogger(Settings.Id); } - public void Assert(bool condition, string message) + private void InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null) { - if (!condition) - throw new EonaCatLoggerAssertionException(message); - } - - private void Write(DateTime dateTime, string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null) - { - if (string.IsNullOrEmpty(message) || logType < ELogType.INFO) + if (string.IsNullOrEmpty(message) || logType == ELogType.NONE || (int)logType >= (int)Settings.MaxLogType) return; - string currentMessage = message.Length > _settings.MaxMessageLength ? message.Substring(0, _settings.MaxMessageLength) : message; - string remainder = message.Length > _settings.MaxMessageLength ? message.Substring(_settings.MaxMessageLength) : ""; + var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime); - var fullMessage = LogHelper.FormatMessageWithHeader(_settings, logType, currentMessage, dateTime); + writeToConsole ??= Settings.EnableConsole; + if (writeToConsole.Value) + { + LogHelper.SendToConsole(Settings, logType, messageWithHeader, true); + } - writeToConsole ??= _settings.EnableConsole; - LogHelper.SendConsole(_settings, logType, fullMessage, writeToConsole.Value); - LogHelper.SendFile(Logger, _settings, logType, fullMessage); - LogHelper.SendToSysLogServers(_settings, fullMessage); + Task.Run(() => { LogHelper.SendToFile(Logger, Settings, logType, message); }); - if (!string.IsNullOrEmpty(remainder)) - Write(dateTime, remainder, logType, writeToConsole); + Task.Run(() => { LogHelper.SendToSysLogServers(Settings, messageWithHeader); }); var logMessage = new EonaCatLogMessage { DateTime = dateTime, - Message = currentMessage, + Message = message, LogType = logType, - Origin = string.IsNullOrWhiteSpace(Settings?.LogOrigin) ? "LogManager" : Settings.LogOrigin + Origin = string.IsNullOrWhiteSpace(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin }; - Settings?.OnLogEvent(logMessage); + Settings.OnLogEvent(logMessage); } - public void Reset() => Settings?.ResetLogEvent(); + public void Reset() => Settings.ResetLogEvent(); - public LogManager(LoggerSettings settings, string serverIp, int serverPort, string id = "EonaCatLogger") + public LogManager(LoggerSettings settings, string serverIp, int serverPort) { if (string.IsNullOrEmpty(serverIp)) throw new ArgumentNullException(nameof(serverIp)); @@ -152,18 +138,16 @@ namespace EonaCat.Logger.Managers throw new ArgumentException("Server port must be zero or greater."); settings.SysLogServers = new List - { - new SyslogServer(serverIp, serverPort) - }; + { + new SyslogServer(serverIp, serverPort) + }; - Id = id; Settings = settings; SetupLogManager(); } - public LogManager(LoggerSettings settings, string id = "EonaCatLogger") + public LogManager(LoggerSettings settings) { - Id = id; Settings = settings; SetupFileLogger(settings, null, true); SetupLogManager(); @@ -193,25 +177,31 @@ namespace EonaCat.Logger.Managers private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) { - Dispose(true); + Dispose(); } private void ProcessExit(object sender, EventArgs e) { - Dispose(true); + Dispose(); } - private void StopLogging() + private Task StopLoggingAsync() { IsRunning = false; - Write(DateTime.UtcNow, $"{DllInfo.ApplicationName} stopped."); - Task.Delay(500, _tokenSource.Token); + InternalWriteAsync(DateTime.UtcNow, $"{DllInfo.ApplicationName} stopped."); + return Task.Delay(500); } - public LogManager(string logFolder = null, bool defaultPrefix = true) + public void DeleteCurrentLogFile() { - SetupFileLogger(null, logFolder, defaultPrefix); - SetupLogManager(); + if (CurrentLogFile != null) + File.Delete(CurrentLogFile); + } + + public void Dispose() + { + DisposeAsync(true).GetAwaiter().GetResult(); + GC.SuppressFinalize(this); } public void Write(Exception exception, string module = null, string method = null, bool criticalException = false, bool? writeToConsole = null) @@ -227,25 +217,12 @@ namespace EonaCat.Logger.Managers if (logType == ELogType.NONE) return; - DateTime now = DateTime.UtcNow; + var now = DateTime.UtcNow; if (!IsRunning) - StartNewLog(); + StartNewLogAsync().ConfigureAwait(false); - Write(now, message, logType, writeToConsole); - } - - public void DeleteCurrentLogFile() - { - if (!string.IsNullOrWhiteSpace(CurrentLogFile)) - File.Delete(CurrentLogFile); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); + InternalWriteAsync(now, message, logType, writeToConsole); } } - -} \ No newline at end of file +} diff --git a/EonaCat.Logger/Managers/LoggerSettings.cs b/EonaCat.Logger/Managers/LoggerSettings.cs index d3f219c..2d43dc5 100644 --- a/EonaCat.Logger/Managers/LoggerSettings.cs +++ b/EonaCat.Logger/Managers/LoggerSettings.cs @@ -14,6 +14,8 @@ namespace EonaCat.Logger.Managers public event LogDelegate OnLog; public delegate void LogDelegate(EonaCatLogMessage message); + public string Id { get; set; } = "EonaCatLogger"; + /// /// Determines if we need to remove the prefix [EonaCatLogger] from each message (default: false) /// @@ -100,6 +102,8 @@ namespace EonaCat.Logger.Managers } } + public ELogType MaxLogType { get; set; } = ELogType.TRACE; + public bool SendToSyslogServers { get; set; } public List SysLogServers { get; set; } @@ -136,22 +140,6 @@ namespace EonaCat.Logger.Managers return new FileLoggerOptions(); } - /// - /// Maximum message length. Must be greater than or equal to 32. Default is 1024. - /// - public int MaxMessageLength - { - get - { - return _maxMessageLength; - } - set - { - if (value < 32) throw new ArgumentException("Maximum message length must be at least 32."); - _maxMessageLength = value; - } - } - /// /// Set the origin of where the OnLog event was initiated /// diff --git a/LoggerTest/LoggerTest.csproj b/LoggerTest/LoggerTest.csproj new file mode 100644 index 0000000..2098092 --- /dev/null +++ b/LoggerTest/LoggerTest.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/LoggerTest/Program.cs b/LoggerTest/Program.cs new file mode 100644 index 0000000..0187bf7 --- /dev/null +++ b/LoggerTest/Program.cs @@ -0,0 +1,14 @@ +using EonaCat.Logger; +using EonaCat.Logger.Managers; + +LogManager.Instance.Write("INFO", ELogType.INFO, true); +LogManager.Instance.Write("WARNING", ELogType.WARNING, true); +LogManager.Instance.Write("ERROR", ELogType.ERROR, true); +LogManager.Instance.Write("DEBUG", ELogType.DEBUG, true); +LogManager.Instance.Write("CRITICAL", ELogType.CRITICAL, true); +LogManager.Instance.Write("TRACE", ELogType.TRACE, true); +LogManager.Instance.Write("TRAFFIC", ELogType.TRAFFIC, true); +LogManager.Instance.Write("NONE", ELogType.NONE, true); + +Console.WriteLine("Press a key to exit"); +Console.ReadKey(); \ No newline at end of file