diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5c1398d..2382477 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -40,6 +40,8 @@ Copyright © $(Company) $([System.DateTime]::Now.ToString(`yyyy`)). All rights reserved. $(Company);Nikita Petko + 1.0.9 + https://github.com/mfdlabs/grid-bot-libraries git diff --git a/src/clients/client-settings-client/ClientSettings.Client.csproj b/src/clients/client-settings-client/ClientSettings.Client.csproj index 96a117d..3b2ffc1 100644 --- a/src/clients/client-settings-client/ClientSettings.Client.csproj +++ b/src/clients/client-settings-client/ClientSettings.Client.csproj @@ -1,8 +1,6 @@ HTTP client used to interact with Roblox's Client Settings API Site. - - 1.0.4 diff --git a/src/clients/thumbnails-client/Thumbnails.Client.csproj b/src/clients/thumbnails-client/Thumbnails.Client.csproj index 1ddb23c..c7891e2 100644 --- a/src/clients/thumbnails-client/Thumbnails.Client.csproj +++ b/src/clients/thumbnails-client/Thumbnails.Client.csproj @@ -1,8 +1,6 @@  HTTP client used to interact with Roblox's Thumbnails API Site. - - 1.0.4 diff --git a/src/clients/users-client/Users.Client.csproj b/src/clients/users-client/Users.Client.csproj index 19ebb59..c628829 100644 --- a/src/clients/users-client/Users.Client.csproj +++ b/src/clients/users-client/Users.Client.csproj @@ -1,8 +1,6 @@  HTTP client used to interact with Roblox's Users API Site. - - 1.0.4 diff --git a/src/configuration/configuration/Configuration.csproj b/src/configuration/configuration/Configuration.csproj index a0455a8..3d38dd9 100644 --- a/src/configuration/configuration/Configuration.csproj +++ b/src/configuration/configuration/Configuration.csproj @@ -1,8 +1,6 @@  C# adaptation for @mfdlabs/environment. - - 1.0.8 diff --git a/src/configuration/configuration/Implementation/EnvironmentProvider.cs b/src/configuration/configuration/Implementation/EnvironmentProvider.cs index 1749e2b..35c8d26 100644 --- a/src/configuration/configuration/Implementation/EnvironmentProvider.cs +++ b/src/configuration/configuration/Implementation/EnvironmentProvider.cs @@ -1,8 +1,6 @@ namespace Configuration; using System; -using System.Linq; -using System.Collections; /// /// Implementation for that uses Environment variables. diff --git a/src/configuration/configuration/Implementation/VaultProvider.cs b/src/configuration/configuration/Implementation/VaultProvider.cs index 458c17d..861fd09 100644 --- a/src/configuration/configuration/Implementation/VaultProvider.cs +++ b/src/configuration/configuration/Implementation/VaultProvider.cs @@ -15,8 +15,10 @@ using Vault; using Logging; + using Threading.Extensions; + /// /// Implementation for via Vault. /// @@ -40,19 +42,25 @@ private static TimeSpan _defaultRefreshInterval nameof(Path), }; - private static readonly ConcurrentBag _providers = new(); + private static readonly ConcurrentDictionary _providers = new(); - private IDictionary _cachedValues = new Dictionary(); + private bool _disposed = false; + + /// + /// The raw cached values. + /// + protected IDictionary _CachedValues = new Dictionary(); + private static readonly ManualResetEvent _refreshRequestEvent = new(false); private static readonly Thread _refreshThread; private static readonly IVaultClient _client = VaultClientFactory.Singleton.GetClient(); private static readonly ILogger _staticLogger = Logger.Singleton; /// - public abstract string Mount { get; } + public virtual string Mount { get; set; } /// - public abstract string Path { get; } + public virtual string Path { get; set; } /// /// Gets the refresh interval for the settings provider. @@ -78,16 +86,25 @@ static VaultProvider() _staticLogger?.Debug("VaultProvider: Started refresh thread!"); } + /// + /// Refresh all the currently registered providers immediately, this method is asynchronous + /// and will return immediately. + /// + public static void RefreshAllProviders() + { + _refreshRequestEvent.Set(); + } + /// protected override void SetRawValue(string variable, T value) { if (_client == null) return; - _logger?.Debug("VaultProvider: Set value in vault at path '{0}/{1}/{2}'", Mount, Path, variable); + _logger?.Information("VaultProvider: Set value in vault at path '{0}/{1}/{2}'", Mount, Path, variable); var realValue = ConvertFrom(value, typeof(T)); - _cachedValues[variable] = realValue; + _CachedValues[variable] = realValue; ApplyCurrent(); } @@ -100,7 +117,7 @@ public void ApplyCurrent() // Build the current from the getters. var values = GetLatestValues(); - _logger?.Debug("VaultProvider: Writing secret '{0}/{1}' to Vault!", Mount, Path); + _logger?.Information("VaultProvider: Writing secret '{0}/{1}' to Vault!", Mount, Path); _client?.V1.Secrets.KeyValue.V2.WriteSecretAsync( mountPoint: Mount, @@ -128,7 +145,7 @@ private Dictionary GetLatestValues() try { - _logger?.Debug("VaultProvider: Fetching initial value for {0}.{1}", GetType().Name, getterName); + _logger?.Verbose("VaultProvider: Fetching initial value for {0}.{1}", GetType().Name, getterName); var value = getter.GetGetMethod().Invoke(this, Array.Empty()); var realValue = value?.ToString() ?? string.Empty; @@ -140,7 +157,7 @@ private Dictionary GetLatestValues() } catch (TargetInvocationException ex) { - _logger?.Debug("VaultProvider: Error occurred when fetching getter for '{0}.{1}': {2}", GetType().Name, getterName, ex.InnerException.Message); + _logger?.Verbose("VaultProvider: Error occurred when fetching getter for '{0}.{1}': {2}", GetType().Name, getterName, ex.InnerException.Message); newCachedValues.Add(getterName, string.Empty); } @@ -153,37 +170,55 @@ private Dictionary GetLatestValues() /// Construct a new instance of /// /// The - protected VaultProvider(ILogger logger = null) + /// Should this periodically refresh? + protected VaultProvider(ILogger logger = null, bool periodicRefresh = true) { logger ??= Logger.Singleton; SetLogger(logger); - _logger?.Debug("VaultProvider: Setup for '{0}/{1}' to refresh every '{2}' interval!", Mount, Path, RefreshInterval); - - if (_providers.Contains(this)) + if (periodicRefresh) { - _logger?.Debug("VaultProvider: Skipping setup for '{0}/{1}' because it is already setup!", Mount, Path); + _logger?.Debug("VaultProvider: Setup for '{0}/{1}' to refresh every '{2}' interval!", Mount, Path, RefreshInterval); - return; - } + if (_providers.TryGetValue(GetType().ToString(), out _)) + { + _logger?.Debug("VaultProvider: Skipping setup for '{0}/{1}' because it is already setup!", Mount, Path); + + return; + } - _providers.Add(this); + _providers.TryAdd(GetType().ToString(), this); + } DoRefresh(); } + /// + /// Construct a new instance of + /// + /// The + /// The + /// The + /// Should this periodically refresh? + protected VaultProvider(string mount, string path = "", ILogger logger = null, bool periodicRefresh = true) + : this(logger, periodicRefresh) + { + Mount = mount; + Path = path; + } + private static void RefreshThread() { while (true) { var providers = _providers.ToArray(); - foreach (var provider in providers) + foreach (var kvp in providers) { try { - provider.DoRefresh(); + kvp.Value.DoRefresh(); } catch (Exception ex) { @@ -191,7 +226,8 @@ private static void RefreshThread() } } - Thread.Sleep(RefreshInterval); // SetClient makes DoRefresh call. + _refreshRequestEvent.WaitOne(RefreshInterval); // SetClient makes DoRefresh call. + _refreshRequestEvent.Reset(); } } @@ -211,8 +247,8 @@ private void DoRefresh() var values = secret.Data.Data; InvokePropertyChangedForChangedValues(values); - lock (_cachedValues) - _cachedValues = values; + lock (_CachedValues) + _CachedValues = values; } catch (VaultApiException ex) { @@ -245,7 +281,6 @@ private bool HasProperty(ref string name) if (property == null) { _logger?.Debug("VaultProvider: Skipping property changed handler for '{0}' because settings provider '{1}' does not define it!", name, this); - _logger?.Warning("{0}: Unknown property '{1}', make sure it is defined in the settings provider or has a appropriate [{2}] attribute!", GetType().Name, name, nameof(SettingNameAttribute)); return false; } @@ -258,7 +293,7 @@ private bool HasProperty(ref string name) private void InvokePropertyChangedForChangedValues(IDictionary newValues) { - if (_cachedValues.Count == 0) + if (_CachedValues.Count == 0) { foreach (var kvp in newValues) { @@ -272,7 +307,7 @@ private void InvokePropertyChangedForChangedValues(IDictionary n var propertyName = kvp.Key; if (!HasProperty(ref propertyName)) continue; - _logger?.Debug("VaultProvider: Invoking property changed handler for '{0}'", propertyName); + _logger?.Verbose("VaultProvider: Invoking property changed handler for '{0}'", propertyName); PropertyChanged?.Invoke(this, new(propertyName)); } @@ -282,7 +317,7 @@ private void InvokePropertyChangedForChangedValues(IDictionary n foreach (var kvp in newValues) { - if (_cachedValues.TryGetValue(kvp.Key, out var value)) + if (_CachedValues.TryGetValue(kvp.Key, out var value)) if (value.ToString().Equals(kvp.Value.ToString())) continue; if (_propertyNamesIgnored.Contains(kvp.Key)) @@ -309,8 +344,8 @@ protected override bool GetRawValue(string key, out string value) { object v; - lock (_cachedValues) - if (!_cachedValues.TryGetValue(key, out v)) + lock (_CachedValues) + if (!_CachedValues.TryGetValue(key, out v)) return base.GetRawValue(key, out value); if (v is JsonElement element) @@ -320,4 +355,15 @@ protected override bool GetRawValue(string key, out string value) return true; } + + /// + public void Dispose() + { + if (_disposed) return; + + GC.SuppressFinalize(this); + + _providers.TryRemove(GetType().ToString(), out _); + _disposed = true; + } } \ No newline at end of file diff --git a/src/configuration/configuration/Interfaces/IVaultProvider.cs b/src/configuration/configuration/Interfaces/IVaultProvider.cs index a340d6d..b8c4eb4 100644 --- a/src/configuration/configuration/Interfaces/IVaultProvider.cs +++ b/src/configuration/configuration/Interfaces/IVaultProvider.cs @@ -1,11 +1,11 @@ namespace Configuration; -using VaultSharp; +using System; /// /// Represents a backed by Vault. /// -public interface IVaultProvider : IConfigurationProvider +public interface IVaultProvider : IConfigurationProvider, IDisposable { /// /// Gets the mount path. diff --git a/src/configuration/core/Configuration.Core.csproj b/src/configuration/core/Configuration.Core.csproj index 51b512f..d3df9cd 100644 --- a/src/configuration/core/Configuration.Core.csproj +++ b/src/configuration/core/Configuration.Core.csproj @@ -1,8 +1,6 @@ Helpers for configuration in applications. - - 1.0.5 diff --git a/src/file-system/file-system/FileSystem.csproj b/src/file-system/file-system/FileSystem.csproj index a974152..3570f45 100644 --- a/src/file-system/file-system/FileSystem.csproj +++ b/src/file-system/file-system/FileSystem.csproj @@ -1,8 +1,6 @@  File system helpers and more! - - 1.0.5 diff --git a/src/floodcheckers/core/FloodCheckers.Core.csproj b/src/floodcheckers/core/FloodCheckers.Core.csproj index bbeba35..b127e4d 100644 --- a/src/floodcheckers/core/FloodCheckers.Core.csproj +++ b/src/floodcheckers/core/FloodCheckers.Core.csproj @@ -1,8 +1,6 @@  Core library for flood checker implementation! - - 1.0.4 diff --git a/src/floodcheckers/redis/FloodCheckers.Redis.csproj b/src/floodcheckers/redis/FloodCheckers.Redis.csproj index 828f9db..56d2b0d 100644 --- a/src/floodcheckers/redis/FloodCheckers.Redis.csproj +++ b/src/floodcheckers/redis/FloodCheckers.Redis.csproj @@ -1,8 +1,6 @@  Library for interacting with Redis based flood checkers! - - 1.0.5 diff --git a/src/grid/client/Grid.Client.csproj b/src/grid/client/Grid.Client.csproj index 05affb9..730d7ff 100644 --- a/src/grid/client/Grid.Client.csproj +++ b/src/grid/client/Grid.Client.csproj @@ -1,8 +1,6 @@  SOAP library shared by grid-server processes! - - 1.0.4 diff --git a/src/grid/commands/Grid.Commands.csproj b/src/grid/commands/Grid.Commands.csproj index 5c0ad03..37cbfbc 100644 --- a/src/grid/commands/Grid.Commands.csproj +++ b/src/grid/commands/Grid.Commands.csproj @@ -1,8 +1,6 @@  Shared library containing models used by grid-servers for specific script execution actions. - - 1.0.4 diff --git a/src/grid/port-management/Grid.PortManagement.csproj b/src/grid/port-management/Grid.PortManagement.csproj index f782629..cde2123 100644 --- a/src/grid/port-management/Grid.PortManagement.csproj +++ b/src/grid/port-management/Grid.PortManagement.csproj @@ -1,8 +1,6 @@  Shared library for port allocation on grid-servers! - - 1.0.5 Grid diff --git a/src/grid/process-management-core/Grid.ProcessManagement.Core.csproj b/src/grid/process-management-core/Grid.ProcessManagement.Core.csproj index e022a83..3888b51 100644 --- a/src/grid/process-management-core/Grid.ProcessManagement.Core.csproj +++ b/src/grid/process-management-core/Grid.ProcessManagement.Core.csproj @@ -1,8 +1,6 @@  Shared library for core interaction with grid server processes! - - 1.0.5 Grid diff --git a/src/grid/process-management-docker/Grid.ProcessManagement.Docker.csproj b/src/grid/process-management-docker/Grid.ProcessManagement.Docker.csproj index eb29fa9..33c800e 100644 --- a/src/grid/process-management-docker/Grid.ProcessManagement.Docker.csproj +++ b/src/grid/process-management-docker/Grid.ProcessManagement.Docker.csproj @@ -1,8 +1,6 @@ Shared library for interaction with Docker based grid server processes! - - 1.0.4 Grid diff --git a/src/grid/process-management/Grid.ProcessManagement.csproj b/src/grid/process-management/Grid.ProcessManagement.csproj index b1e7ebb..a514cb8 100644 --- a/src/grid/process-management/Grid.ProcessManagement.csproj +++ b/src/grid/process-management/Grid.ProcessManagement.csproj @@ -1,8 +1,6 @@  Shared library for allocating grid-server processes! - - 1.0.5 Grid diff --git a/src/hashing/hashing/Hashing.csproj b/src/hashing/hashing/Hashing.csproj index a4b52e5..6e5194a 100644 --- a/src/hashing/hashing/Hashing.csproj +++ b/src/hashing/hashing/Hashing.csproj @@ -1,7 +1,5 @@ Shared library to help with hashing. - - 1.0.4 diff --git a/src/logging/logging/Enums/LogLevel.cs b/src/logging/logging/Enums/LogLevel.cs index 85471eb..2607438 100644 --- a/src/logging/logging/Enums/LogLevel.cs +++ b/src/logging/logging/Enums/LogLevel.cs @@ -1,38 +1,37 @@ -namespace Logging +namespace Logging; + +/// +/// Represents the logging level. +/// +public enum LogLevel { /// - /// Represents the logging level. + /// NoOp log, no log messages are ever written. /// - public enum LogLevel - { - /// - /// No-Op - /// - None, + None, - /// - /// Error messagw - /// - Error, + /// + /// Only critical error messages are written. + /// + Error, - /// - /// Warn - /// - Warning, + /// + /// Error messages as well as warning type messages are written. + /// + Warning, - /// - /// Info - /// - Information, + /// + /// More chatty information based messages are written as well. + /// + Information, - /// - /// Debug - /// - Debug, + /// + /// Verbose logging information is written. + /// + Debug, - /// - /// Trace - /// - Trace - } -} + /// + /// Extremely verbose and possibly spammy logging messages are written. + /// + Verbose +} \ No newline at end of file diff --git a/src/logging/logging/Implementation/Logger.cs b/src/logging/logging/Implementation/Logger.cs index 0fdc859..52f1710 100644 --- a/src/logging/logging/Implementation/Logger.cs +++ b/src/logging/logging/Implementation/Logger.cs @@ -17,6 +17,9 @@ using System.Threading.Tasks; #endif +using Windows.Win32; +using Windows.Win32.System.Console; + // ReSharper disable LocalizableElement // ReSharper disable InconsistentNaming // ReSharper disable UseStringInterpolationWhenPossible @@ -134,6 +137,35 @@ static Logger() ) { AutoFlush = true } ); + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return; + + unsafe + { + CONSOLE_MODE lpMode; + + var hStdout = PInvoke.GetStdHandle(STD_HANDLE.STD_OUTPUT_HANDLE); + if (PInvoke.GetConsoleMode(hStdout, &lpMode)) + { + if (!lpMode.HasFlag(CONSOLE_MODE.ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + { + lpMode |= CONSOLE_MODE.ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + PInvoke.SetConsoleMode(hStdout, lpMode); + } + } + + var hStderr = PInvoke.GetStdHandle(STD_HANDLE.STD_ERROR_HANDLE); + if (PInvoke.GetConsoleMode(hStderr, &lpMode)) + { + if (!lpMode.HasFlag(CONSOLE_MODE.ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + { + lpMode |= CONSOLE_MODE.ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + PInvoke.SetConsoleMode(hStderr, lpMode); + } + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -240,7 +272,7 @@ private static LogLevel _defaultLogLevel ////////////////////////////////////////////////////////////////////////////// private string _name; - private LogLevel _logLevel; + private Func _logLevelGetter; private bool _logToConsole; private bool _logToFileSystem; private bool _logThreadId; @@ -301,6 +333,11 @@ private static bool _terminalAvailable() } } + private static string _format(string format, params object[] args) + => args is { Length: > 0 } + ? string.Format(format, args) + : format; + private static string _getCurrentThreadIdFormatted() => Thread.CurrentThread.ManagedThreadId .ToString("x") .PadLeft(4, '0'); @@ -479,15 +516,10 @@ protected static string _getConstructedCustomColorLogPrefix(List> p /// Constructs the full non-color log message. /// /// The log level. - /// The format string. - /// The args for the format. + /// The message getter. /// The constructed string. - protected string _constructNonColorLogMessage(LogLevel logLevel, string format, params object[] args) + protected string _constructNonColorLogMessage(LogLevel logLevel, Func messageGetter) { - var formattedMessage = args is { Length: 0 } - ? format - : string.Format(format, args); - if (_cutLogPrefix) return string.Format( "[{0}]{1}{2}{3}{4}[{5}] {6}\n", @@ -497,7 +529,7 @@ protected string _constructNonColorLogMessage(LogLevel logLevel, string format, Logger._getConstructedCustomNonColorLogPrefix(this._logPrefixes), Logger._getConstructedCustomNonColorLogPrefix(Logger._globalLogPrefixes), logLevel.ToString().ToUpper(), - formattedMessage + messageGetter() ); return string.Format( @@ -509,7 +541,7 @@ protected string _constructNonColorLogMessage(LogLevel logLevel, string format, Logger._getConstructedCustomNonColorLogPrefix(this._logPrefixes), Logger._getConstructedCustomNonColorLogPrefix(Logger._globalLogPrefixes), logLevel.ToString().ToUpper(), - formattedMessage + messageGetter() ); } @@ -518,15 +550,10 @@ protected string _constructNonColorLogMessage(LogLevel logLevel, string format, /// /// The log level. /// The log color. - /// The format string. - /// The args for the format. + /// The format string. /// The constructed string. - protected string _constructColorLogMessage(LogLevel logLevel, Logger.LogColor color, string format, params object[] args) + protected string _constructColorLogMessage(LogLevel logLevel, Logger.LogColor color, Func messageGetter) { - var formattedMessage = args is { Length: 0 } - ? format - : string.Format(format, args); - if (_cutLogPrefix) return string.Format( "{0}{1}{2}{3}{4}{5} {6}{7}{8}\n", @@ -537,7 +564,7 @@ protected string _constructColorLogMessage(LogLevel logLevel, Logger.LogColor co Logger._getConstructedCustomColorLogPrefix(Logger._globalLogPrefixes), Logger._getColorSection(color, logLevel.ToString().ToUpper()), Logger._getAnsiColorByLogColor(color), - formattedMessage, + messageGetter(), Logger._getAnsiColorByLogColor(LogColor.Reset) ); @@ -551,12 +578,12 @@ protected string _constructColorLogMessage(LogLevel logLevel, Logger.LogColor co Logger._getConstructedCustomColorLogPrefix(Logger._globalLogPrefixes), Logger._getColorSection(color, logLevel.ToString().ToUpper()), Logger._getAnsiColorByLogColor(color), - formattedMessage, + messageGetter(), Logger._getAnsiColorByLogColor(LogColor.Reset) ); } - private void _writeLogToFileSystem(LogLevel logLevel, string format, params object[] args) + private void _writeLogToFileSystem(LogLevel logLevel, Func messageGetter) { lock (this._fileSystemLock) { @@ -570,7 +597,7 @@ private void _writeLogToFileSystem(LogLevel logLevel, string format, params obje try { - this._lockedFileWriteStream?.Write(this._constructNonColorLogMessage(logLevel, format, args)); + this._lockedFileWriteStream?.Write(this._constructNonColorLogMessage(logLevel, messageGetter)); } catch (Exception ex) { @@ -582,31 +609,31 @@ private void _writeLogToFileSystem(LogLevel logLevel, string format, params obje } } - private void _writeLogToConsole(LogLevel logLevel, Logger.LogColor color, string format, params object[] args) + private void _writeLogToConsole(LogLevel logLevel, Logger.LogColor color, Func messageGetter) { lock (this._consoleLock) { if (!this._logToConsole) return; - var message = this._logWithColor - ? this._constructColorLogMessage(logLevel, color, format, args) - : this._constructNonColorLogMessage(logLevel, format, args); + var result = this._logWithColor + ? this._constructColorLogMessage(logLevel, color, messageGetter) + : this._constructNonColorLogMessage(logLevel, messageGetter); if (logLevel == LogLevel.Error) - Console.Error.Write(message); + Console.Error.Write(result); else - Console.Out.Write(message); + Console.Out.Write(result); } } - private void _queueOrLog(LogLevel logLevel, Logger.LogColor color, string format, params object[] args) + private void _queueOrLog(LogLevel logLevel, Logger.LogColor color, Func messageGetter) { if (this._disposed) throw new ObjectDisposedException(this.GetType().Name); #if CONCURRENT_LOGGING_ENABLED Task.Factory.StartNew(() => { - try { this._writeLog(logLevel, color, format, args); } + try { this._writeLog(logLevel, color, messageGetter); } catch (Exception ex) { #if DEBUG @@ -615,7 +642,7 @@ private void _queueOrLog(LogLevel logLevel, Logger.LogColor color, string format } }); #else - try { this._writeLog(logLevel, color, format, args); } + try { this._writeLog(logLevel, color, messageGetter); } catch (Exception ex) { #if DEBUG @@ -630,15 +657,14 @@ private void _queueOrLog(LogLevel logLevel, Logger.LogColor color, string format /// /// The log level. /// The color. - /// The format. - /// The format arga. - protected virtual void _writeLog(LogLevel logLevel, Logger.LogColor color, string format, params object[] args) + /// The message getter. + protected virtual void _writeLog(LogLevel logLevel, Logger.LogColor color, Func messageGetter) { - this._writeLogToConsole(logLevel, color, format, args); - this._writeLogToFileSystem(logLevel, format, args); + this._writeLogToConsole(logLevel, color, messageGetter); + this._writeLogToFileSystem(logLevel, messageGetter); } - private bool _checkLogLevel(LogLevel logLevel) => this._logLevel >= logLevel; + private bool _checkLogLevel(LogLevel logLevel) => this._logLevelGetter() >= logLevel; private void _createFileStream() => this._lockedFileWriteStream ??= new(this._fullyQualifiedFileName); private void _closeFileStream() { @@ -692,7 +718,7 @@ private void _createFileName() /// public static void TryClearLocalLog() { - Logger.Singleton.Log("Try clear local log files..."); + Logger.Singleton.Information("Try clear local log files..."); var fileSystemLoggers = Logger._loggers.Where(logger => logger._logToFileSystem == true); @@ -735,7 +761,7 @@ public static void TryClearLocalLog() /// public static void TryClearAllLoggers() { - Logger.Singleton.Log("Try clear all loggers..."); + Logger.Singleton.Information("Try clear all loggers..."); try { @@ -756,7 +782,7 @@ public static void TryClearAllLoggers() /// Construct a new instance of . /// /// The name of the logger. - /// The log level of the logger. + /// The log level of the logger. /// If true, the logger will log to the file system. /// If true, the logger will log to the console. /// If true, the logger will cut the log prefix. @@ -771,7 +797,7 @@ public static void TryClearAllLoggers() // ReSharper disable once MemberCanBeProtected.Global public Logger( string name, - LogLevel logLevel = LogLevel.Information, + Func logLevelGetter = default, bool logToFileSystem = true, bool logToConsole = true, bool cutLogPrefix = true, @@ -793,8 +819,10 @@ public Logger( lock (Logger._loggers) Logger._loggers.Add(this); + if (logLevelGetter == default) logLevelGetter = () => LogLevel.Information; + this._name = name; - this._logLevel = logLevel; + this._logLevelGetter = logLevelGetter; this._logToFileSystem = logToFileSystem; this._logToConsole = logToConsole; this._cutLogPrefix = cutLogPrefix; @@ -821,7 +849,7 @@ public static Logger Singleton lock (Logger._singletonLock) return Logger._singleton ??= new( _defaultLoggerName, - _defaultLogLevel + () => _defaultLogLevel ); } } @@ -836,7 +864,7 @@ public static Logger NoopSingleton lock (Logger._noopSingletonLock) return Logger._noopSingleton ??= new( "_noop", - LogLevel.None, + () => LogLevel.None, false, false ); @@ -873,12 +901,13 @@ public string Name /// public LogLevel LogLevel { - get => this._logLevel; + get => this._logLevelGetter(); set { if (this._disposed) throw new ObjectDisposedException(this.GetType().Name); + if (this._logLevelGetter() == value) return; - this._logLevel = value; + this._logLevelGetter = () => value; } } @@ -972,36 +1001,13 @@ public List> CustomLogPrefixes // Public Log Methods //////////////////////////////////////////////////////////////////////////////// - /// - public void Log(string format, params object[] args) - { - if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format)); - if (args == null) throw new ArgumentNullException(nameof(args)); - - if (!this._checkLogLevel(LogLevel.Information)) return; - - this._queueOrLog(LogLevel.Information, Logger.LogColor.BrightWhite, format, args); - } - - /// - public void Log(Func messageGetter) - { - if (messageGetter == null) throw new ArgumentNullException(nameof(messageGetter)); - - if (!this._checkLogLevel(LogLevel.Information)) return; - - this._queueOrLog(LogLevel.Information, Logger.LogColor.BrightWhite, messageGetter()); - } - /// public void Warning(string format, params object[] args) { if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format)); if (args == null) throw new ArgumentNullException(nameof(args)); - if (!this._checkLogLevel(LogLevel.Warning)) return; - - this._queueOrLog(LogLevel.Warning, Logger.LogColor.BrightYellow, format, args); + this.Warning(() => Logger._format(format, args)); } /// @@ -1011,36 +1017,28 @@ public void Warning(Func messageGetter) if (!this._checkLogLevel(LogLevel.Warning)) return; - this._queueOrLog(LogLevel.Warning, Logger.LogColor.BrightYellow, messageGetter()); + this._queueOrLog(LogLevel.Warning, Logger.LogColor.BrightYellow, messageGetter); } - /// - public void Trace(string format, params object[] args) + /// + public void Verbose(string format, params object[] args) { if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format)); if (args == null) throw new ArgumentNullException(nameof(args)); - if (!this._checkLogLevel(LogLevel.Trace)) return; - - var formattedMessage = args is { Length: 0 } - ? format - : string.Format(format, args); - - var message = string.Format("{0}\n{1}", formattedMessage, Environment.StackTrace); + if (!this._checkLogLevel(LogLevel.Verbose)) return; - this._queueOrLog(LogLevel.Trace, Logger.LogColor.BrightMagenta, message); + this.Verbose(() => Logger._format(format, args)); } - /// - public void Trace(Func messageGetter) + /// + public void Verbose(Func messageGetter) { if (messageGetter == null) throw new ArgumentNullException(nameof(messageGetter)); - if (!this._checkLogLevel(LogLevel.Trace)) return; + if (!this._checkLogLevel(LogLevel.Verbose)) return; - var message = string.Format("{0}\n{1}", messageGetter(), Environment.StackTrace); - - this._queueOrLog(LogLevel.Trace, Logger.LogColor.BrightMagenta, message); + this._queueOrLog(LogLevel.Verbose, Logger.LogColor.BrightMagenta, messageGetter); } /// @@ -1049,9 +1047,7 @@ public void Debug(string format, params object[] args) if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format)); if (args == null) throw new ArgumentNullException(nameof(args)); - if (!this._checkLogLevel(LogLevel.Debug)) return; - - this._queueOrLog(LogLevel.Debug, Logger.LogColor.BrightMagenta, format, args); + this.Debug(() => Logger._format(format, args)); } /// @@ -1061,7 +1057,7 @@ public void Debug(Func messageGetter) if (!this._checkLogLevel(LogLevel.Debug)) return; - this._queueOrLog(LogLevel.Debug, Logger.LogColor.BrightMagenta, messageGetter()); + this._queueOrLog(LogLevel.Debug, Logger.LogColor.BrightMagenta, messageGetter); } /// @@ -1070,9 +1066,7 @@ public void Information(string format, params object[] args) if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format)); if (args == null) throw new ArgumentNullException(nameof(args)); - if (!this._checkLogLevel(LogLevel.Information)) return; - - this._queueOrLog(LogLevel.Information, Logger.LogColor.BrightBlue, format, args); + this.Information(() => Logger._format(format, args)); } /// @@ -1082,7 +1076,7 @@ public void Information(Func messageGetter) if (!this._checkLogLevel(LogLevel.Information)) return; - this._queueOrLog(LogLevel.Information, Logger.LogColor.BrightBlue, messageGetter()); + this._queueOrLog(LogLevel.Information, Logger.LogColor.BrightBlue, messageGetter); } /// @@ -1090,9 +1084,16 @@ public void Error(Exception ex) { if (ex == null) throw new ArgumentNullException(nameof(ex)); - if (!this._checkLogLevel(LogLevel.Error)) return; + this.Error(() => ex.ToString()); + } - this._queueOrLog(LogLevel.Error, Logger.LogColor.BrightRed, ex.ToString()); + /// + public void Error(Exception ex, string message) + { + if (ex == null) throw new ArgumentNullException(nameof(ex)); + if (string.IsNullOrEmpty(message)) throw new ArgumentNullException(nameof(message)); + + this.Error(() => string.Format("{0}\nTrace Back: {1}", message, ex.ToString())); } /// @@ -1101,9 +1102,7 @@ public void Error(string format, params object[] args) if (format == null) throw new ArgumentNullException(nameof(format)); if (args == null) throw new ArgumentNullException(nameof(args)); - if (!this._checkLogLevel(LogLevel.Error)) return; - - this._queueOrLog(LogLevel.Error, Logger.LogColor.BrightRed, format, args); + this.Error(() => Logger._format(format, args)); } /// @@ -1113,7 +1112,7 @@ public void Error(Func messageGetter) if (!this._checkLogLevel(LogLevel.Error)) return; - this._queueOrLog(LogLevel.Error, Logger.LogColor.BrightRed, messageGetter()); + this._queueOrLog(LogLevel.Error, Logger.LogColor.BrightRed, messageGetter); } /// @@ -1128,8 +1127,9 @@ public void Dispose() lock (Logger._loggers) Logger._loggers.Remove(this); + this._closeFileStream(); this._disposed = true; } -} +} \ No newline at end of file diff --git a/src/logging/logging/Interfaces/ILogger.cs b/src/logging/logging/Interfaces/ILogger.cs index 0b010b0..37725e1 100644 --- a/src/logging/logging/Interfaces/ILogger.cs +++ b/src/logging/logging/Interfaces/ILogger.cs @@ -42,6 +42,9 @@ public interface ILogger : IDisposable /// /// Gets or sets the value that determines if the logger should log with color to the console. /// + /// + /// This is only applicable when the OS supports ANSI escape codes. + /// bool LogWithColor { get; set; } /// @@ -60,86 +63,99 @@ public interface ILogger : IDisposable string FullyQualifiedFileName { get; } /// - /// Log a log message. - /// - /// The message format - /// Optional arguments. - void Log(string format, params object[] args); - - /// - /// Log a log message. - /// - /// A function that returns a message - void Log(Func messageGetter); - - /// - /// Log a warning message. + /// Log a warning message, usually suited for messages that are not too important + /// but are not expected behaviour. /// /// The message format /// Optional arguments. void Warning(string format, params object[] args); /// - /// Log a warning message. + /// Log a warning message, usually suited for messages that are not too important + /// but are not expected behaviour. /// /// A function that returns a message void Warning(Func messageGetter); /// - /// Log a trace message. + /// Logs a verbose message, suited for extremely verbose logging, very + /// expensive logging, and even very spammy logging, usually this should be + /// disabled if you wish to reduce resource usage on the app. + /// ignore /// /// The message format /// Optional arguments. - void Trace(string format, params object[] args); + void Verbose(string format, params object[] args); /// - /// Log a trace message. + /// Logs a verbose message, suited for extremely verbose logging, very + /// expensive logging, and even very spammy logging, usually this should be + /// disabled if you wish to reduce resource usage on the app. /// /// A function that returns a message - void Trace(Func messageGetter); + void Verbose(Func messageGetter); /// - /// Log a debug message. + /// Logs a debug message, typically verbose information that + /// reveals workings behind the code. This differs from + /// in the way that it is for more basic verbose logging, stuff that + /// can assist in debugging. /// /// The message format /// Optional arguments. void Debug(string format, params object[] args); /// - /// Log a debug message. + /// Logs a debug message, typically verbose information that + /// reveals workings behind the code. This differs from + /// in the way that it is for more basic verbose logging, stuff that + /// can assist in debugging. /// /// A function that returns a message void Debug(Func messageGetter); /// - /// Log an information message. + /// Logs an informational message, usually used for logging information + /// such as starting points, life cycle events and general basic information. /// /// The message format /// Optional arguments. void Information(string format, params object[] args); /// - /// Log an information message. + /// Logs an informational message, usually used for logging information + /// such as starting points, life cycle events and general basic information. /// /// A function that returns a message void Information(Func messageGetter); /// - /// Log an error message. + /// Log an error message, this should be used for critical + /// errors that should be seen. /// /// An exception to format. void Error(Exception ex); /// - /// Log an error message. + /// Log an error message, this should be used for critical + /// errors that should be seen. + /// + /// An exception to format. + /// The message format + void Error(Exception ex, string message); + + /// + /// Log an error message, this should be used for critical + /// errors that should be seen. /// /// The message format /// Optional arguments. void Error(string format, params object[] args); /// - /// Log an error message. + /// Log an error message, this should be used for critical + /// errors that should be seen. /// /// A function that returns a message void Error(Func messageGetter); -} +} \ No newline at end of file diff --git a/src/logging/logging/Logging.csproj b/src/logging/logging/Logging.csproj index 9f9b4d9..f435258 100644 --- a/src/logging/logging/Logging.csproj +++ b/src/logging/logging/Logging.csproj @@ -1,11 +1,18 @@  Shared logging library! - - 1.0.4 $(DefineConstants);CONCURRENT_LOGGING_ENABLED + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/src/logging/logging/NativeMethods.txt b/src/logging/logging/NativeMethods.txt new file mode 100644 index 0000000..a3973bf --- /dev/null +++ b/src/logging/logging/NativeMethods.txt @@ -0,0 +1,6 @@ +GetStdHandle +GetConsoleMode +SetConsoleMode + +STD_HANDLE +CONSOLE_MODE \ No newline at end of file diff --git a/src/networking/networking/Networking.csproj b/src/networking/networking/Networking.csproj index d58b5e9..4aa452e 100644 --- a/src/networking/networking/Networking.csproj +++ b/src/networking/networking/Networking.csproj @@ -1,8 +1,6 @@  Library used for IP address parsing and more! - - 1.0.6 diff --git a/src/random/random/Random.csproj b/src/random/random/Random.csproj index 9881586..a222192 100644 --- a/src/random/random/Random.csproj +++ b/src/random/random/Random.csproj @@ -1,7 +1,5 @@ Random helpers and more! - - 1.0.4 diff --git a/src/redis/redis/Redis.csproj b/src/redis/redis/Redis.csproj index 28ccf47..5e9a1db 100644 --- a/src/redis/redis/Redis.csproj +++ b/src/redis/redis/Redis.csproj @@ -1,8 +1,6 @@  Redis client used for easy interaction with Redis servers. - - 1.0.4 diff --git a/src/service-discovery/service-discovery/ServiceDiscovery.csproj b/src/service-discovery/service-discovery/ServiceDiscovery.csproj index 5b5344d..7c4afee 100644 --- a/src/service-discovery/service-discovery/ServiceDiscovery.csproj +++ b/src/service-discovery/service-discovery/ServiceDiscovery.csproj @@ -1,8 +1,6 @@  Shared library to help with resolution of addresses from sources like Consul. - - 1.0.5 diff --git a/src/text/text/Text.csproj b/src/text/text/Text.csproj index f1a9ad7..0bcd385 100644 --- a/src/text/text/Text.csproj +++ b/src/text/text/Text.csproj @@ -1,8 +1,6 @@ Shared text helpers! - - 1.0.4 diff --git a/src/threading/threading/Threading.csproj b/src/threading/threading/Threading.csproj index 1bd1007..cd39130 100644 --- a/src/threading/threading/Threading.csproj +++ b/src/threading/threading/Threading.csproj @@ -1,8 +1,6 @@  Helpers to aid with multi-threaded environments. - - 1.0.4 preview diff --git a/src/vault/vault/Vault.csproj b/src/vault/vault/Vault.csproj index e1b4a7f..4e9ba66 100644 --- a/src/vault/vault/Vault.csproj +++ b/src/vault/vault/Vault.csproj @@ -1,8 +1,6 @@ Helper to aid with creation of a shared Vault client. - - 1.0.5