diff --git a/EonaCat.Logger.LogClient/EonaCat.Logger.LogClient.csproj b/EonaCat.Logger.LogClient/EonaCat.Logger.LogClient.csproj
index 134926f..edc9919 100644
--- a/EonaCat.Logger.LogClient/EonaCat.Logger.LogClient.csproj
+++ b/EonaCat.Logger.LogClient/EonaCat.Logger.LogClient.csproj
@@ -25,9 +25,11 @@
-
+
+
+
True
diff --git a/EonaCat.Logger/EonaCatCoreLogger/FileLoggerOptions.cs b/EonaCat.Logger/EonaCatCoreLogger/FileLoggerOptions.cs
index 8008735..42c9ebe 100644
--- a/EonaCat.Logger/EonaCatCoreLogger/FileLoggerOptions.cs
+++ b/EonaCat.Logger/EonaCatCoreLogger/FileLoggerOptions.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using EonaCat.Logger.EonaCatCoreLogger.Internal;
+using EonaCat.Logger.Managers;
namespace EonaCat.Logger.EonaCatCoreLogger;
// This file is part of the EonaCat project(s) which is released under the Apache License.
@@ -144,4 +145,6 @@ public class FileLoggerOptions : BatchingLoggerOptions
/// Determines if we need to include the correlation ID in the log (default: false)
///
public bool IncludeCorrelationId { get; set; }
+ public LoggerSettings Settings { get; internal set; }
+ public LoggerSettings LoggerSettings { get; internal set; }
}
\ No newline at end of file
diff --git a/EonaCat.Logger/EonaCatCoreLogger/FileLoggerProvider.cs b/EonaCat.Logger/EonaCatCoreLogger/FileLoggerProvider.cs
index 17aa586..05511a4 100644
--- a/EonaCat.Logger/EonaCatCoreLogger/FileLoggerProvider.cs
+++ b/EonaCat.Logger/EonaCatCoreLogger/FileLoggerProvider.cs
@@ -94,7 +94,6 @@ public class FileLoggerProvider : BatchingLoggerProvider
foreach (var group in messages.GroupBy(GetGrouping))
{
LogFile = GetFullName(group.Key);
-
var currentMessages = string.Join(string.Empty, group.Select(item =>
{
if (IncludeCorrelationId)
diff --git a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs
index 5bd70a9..dadf54f 100644
--- a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs
+++ b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLogger.cs
@@ -13,13 +13,13 @@ namespace EonaCat.Logger.EonaCatCoreLogger.Internal
{
private readonly string _category;
private readonly BatchingLoggerProvider _provider;
- private readonly LoggerSettings _loggerSettings;
+ private LoggerSettings _loggerSettings;
public BatchingLogger(BatchingLoggerProvider loggerProvider, string categoryName, LoggerSettings loggerSettings)
{
+ _loggerSettings = loggerSettings ?? throw new ArgumentNullException(nameof(loggerSettings));
_provider = loggerProvider ?? throw new ArgumentNullException(nameof(loggerProvider));
_category = categoryName ?? throw new ArgumentNullException(nameof(categoryName));
- _loggerSettings = loggerSettings ?? throw new ArgumentNullException(nameof(loggerSettings));
}
private DateTimeOffset CurrentDateTimeOffset => CurrentDateTime;
diff --git a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs
index 07be424..21ed824 100644
--- a/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs
+++ b/EonaCat.Logger/EonaCatCoreLogger/Internal/BatchingLoggerProvider.cs
@@ -25,6 +25,7 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
private CancellationTokenSource _cancellationTokenSource;
private Task _outputTask;
private bool _isDisposed;
+ private LoggerSettings _loggerSettings;
protected BatchingLoggerProvider(IOptions options)
{
@@ -40,6 +41,7 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
{
UseLocalTime = fileLoggerOptions.UseLocalTime;
UseMask = fileLoggerOptions.UseMask;
+ LoggerSettings = fileLoggerOptions.LoggerSettings;
}
_batchSize = loggerOptions.BatchSize > 0 ? loggerOptions.BatchSize : 100;
@@ -51,30 +53,27 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
protected bool UseLocalTime { get; set; }
+ public bool IsStarted { get; set; }
+ public bool UseMask { get; set; }
+ public string Category { get; set; } = "General";
+
protected LoggerSettings LoggerSettings
{
get
{
- if (_loggerSettings != null)
+ if (_loggerSettings == null)
{
- return _loggerSettings;
+ _loggerSettings = new LoggerSettings();
+ _loggerSettings.UseLocalTime = UseLocalTime;
+ _loggerSettings.UseMask = UseMask;
+ //TODO: Add the tokens and custom tokens
}
-
- _loggerSettings = new LoggerSettings();
- _loggerSettings.UseLocalTime = UseLocalTime;
- _loggerSettings.UseMask = UseMask;
return _loggerSettings;
}
set => _loggerSettings = value;
}
- public bool IsStarted { get; set; }
- public bool UseMask { get; set; }
- public string Category { get; set; } = "General";
-
- private LoggerSettings _loggerSettings;
-
///
/// Creates a new logger instance for the specified category name.
///
diff --git a/EonaCat.Logger/Logger.cs b/EonaCat.Logger/Logger.cs
index 34e8ac6..19d3827 100644
--- a/EonaCat.Logger/Logger.cs
+++ b/EonaCat.Logger/Logger.cs
@@ -48,9 +48,6 @@ namespace EonaCat.Logger
IsEnabled = true,
},
};
-
- _logManager = new LogManager(LoggerSettings);
- _logManager.Settings.TypesToLog.Clear();
}
///
@@ -87,9 +84,20 @@ namespace EonaCat.Logger
return;
}
+ InitLogger();
await _logManager.WriteAsync(message, logType, writeToConsole).ConfigureAwait(false);
}
+ private void InitLogger()
+ {
+ if (_logManager == null)
+ {
+ // Initialize LogManager
+ _logManager = new LogManager(LoggerSettings);
+ _logManager.Settings.TypesToLog.Clear();
+ }
+ }
+
///
/// Asynchronously logs the specified exception and an optional message, with the option to also write the log
/// entry to the console.
@@ -108,6 +116,7 @@ namespace EonaCat.Logger
return;
}
+ InitLogger();
if (LoggerSettings.TypesToLog.Contains(ELogType.ERROR))
{
await _logManager.WriteAsync(exception, message, writeToConsole: writeToConsole).ConfigureAwait(false);
diff --git a/EonaCat.Logger/Managers/HeaderTokens.cs b/EonaCat.Logger/Managers/HeaderTokens.cs
new file mode 100644
index 0000000..37e5548
--- /dev/null
+++ b/EonaCat.Logger/Managers/HeaderTokens.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using static EonaCat.Logger.Managers.LogHelper;
+
+// 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.
+
+namespace EonaCat.Logger.Managers;
+
+///
+/// Provides a collection of predefined and customizable header token resolvers for formatting log or message headers.
+///
+/// HeaderTokens exposes a set of standard tokens that can be used to insert runtime, environment, and
+/// contextual information into header strings, such as timestamps, process details, thread information, and more.
+/// Custom tokens can be added or overridden to support application-specific formatting needs. All token keys are
+/// case-insensitive. This class is thread-safe for read operations, but adding or overriding tokens is not guaranteed
+/// to be thread-safe and should be synchronized if used concurrently.
+public class HeaderTokens
+{
+ private readonly Dictionary> _tokenResolvers =
+ new(StringComparer.OrdinalIgnoreCase)
+ {
+ ["date"] = ctx => $"[Date: {ctx.Timestamp:yyyy-MM-dd}]",
+
+ ["time"] = ctx => $"[Time: {ctx.Timestamp:HH:mm:ss.fff}]",
+
+ ["ticks"] = ctx => $"[Ticks: {ctx.Timestamp.Ticks}]",
+
+ ["ts"] = ctx => $"[{ctx.Timestamp.ToString(ctx.TimestampFormat)}]",
+
+ ["tz"] = ctx => $"[{(ctx.Timestamp.Kind == DateTimeKind.Utc ? "UTC" : "LOCAL")}]",
+
+ ["unix"] = ctx => $"[Unix: {new DateTimeOffset(ctx.Timestamp).ToUnixTimeSeconds()}]",
+
+ ["procstart"] = _ =>
+ {
+ var p = Process.GetCurrentProcess();
+ return $"[ProcStart: {p.StartTime:O}]";
+ },
+
+ ["uptime"] = _ =>
+ {
+ var p = Process.GetCurrentProcess();
+ return $"[Uptime: {(DateTime.Now - p.StartTime).TotalSeconds:F0}s]";
+ },
+
+ ["framework"] = _ =>
+ $"[Runtime: {RuntimeInformation.FrameworkDescription}]",
+
+ ["os"] = _ =>
+ $"[OS: {RuntimeInformation.OSDescription}]",
+
+ ["arch"] = _ =>
+ $"[Arch: {RuntimeInformation.ProcessArchitecture}]",
+
+ ["mem"] = _ => $"[Memory: {GC.GetTotalMemory(false) / 1024 / 1024}MB]",
+
+ ["gc"] = _ => $"[GC: {GC.CollectionCount(0)}/{GC.CollectionCount(1)}/{GC.CollectionCount(2)}]",
+
+ ["cwd"] = _ => $"[CWD: {Environment.CurrentDirectory}]",
+
+ ["app"] = _ => $"[App: {AppDomain.CurrentDomain.FriendlyName}]",
+
+ ["appbase"] = _ => $"[AppBase: {AppDomain.CurrentDomain.BaseDirectory}]",
+
+ ["domain"] = _ => $"[Domain: {AppDomain.CurrentDomain.Id}]",
+
+ ["threadname"] = _ => $"[ThreadName: {Thread.CurrentThread.Name ?? "n/a"}]",
+
+ ["task"] = _ => $"[TaskId: {Task.CurrentId?.ToString() ?? "n/a"}]",
+
+ ["host"] = ctx => $"[Host: {ctx.HostName}]",
+
+ ["machine"] = _ => $"[Machine: {Environment.MachineName}]",
+
+ ["category"] = ctx => $"[Category: {ctx.Category}]",
+
+ ["thread"] = _ => $"[Thread: {Environment.CurrentManagedThreadId}]",
+
+ ["process"] = _ =>
+ {
+ var p = Process.GetCurrentProcess();
+ return $"[Process: {p.ProcessName}]";
+ },
+
+ ["pid"] = _ => $"[PID: {Process.GetCurrentProcess().Id}]",
+
+ ["sev"] = ctx => $"[Severity: {ctx.LogType}]",
+
+ ["LogType"] = ctx => $"[{ctx.LogType}]",
+
+ ["user"] = _ => $"[User: {Environment.UserName}]",
+
+ ["env"] = ctx => $"[Env: {ctx.EnvironmentName}]",
+
+ ["newline"] = _ => Environment.NewLine
+ };
+
+ ///
+ /// Gets a read-only dictionary of token resolver functions used to generate header values based on a token name and
+ /// header context.
+ ///
+ /// Each entry maps a token name to a function that produces the corresponding header value for a
+ /// given . The dictionary is static and cannot be modified at runtime.
+ public IReadOnlyDictionary> TokenResolvers => _tokenResolvers;
+
+ ///
+ /// Adds or overrides a custom token.
+ ///
+ public void AddCustomToken(string key, Func resolver)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ {
+ throw new ArgumentException("Token key cannot be null or whitespace.", nameof(key));
+ }
+
+ if (resolver == null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ _tokenResolvers[key] = resolver;
+ }
+}
diff --git a/EonaCat.Logger/Managers/LogHelper.cs b/EonaCat.Logger/Managers/LogHelper.cs
index efb702a..6f50d89 100644
--- a/EonaCat.Logger/Managers/LogHelper.cs
+++ b/EonaCat.Logger/Managers/LogHelper.cs
@@ -1,9 +1,12 @@
using EonaCat.Json;
+using EonaCat.Logger.EonaCatCoreLogger;
+using EonaCat.Logger.EonaCatCoreLogger.Internal;
using EonaCat.Logger.Extensions;
using EonaCat.Logger.Servers.GrayLog;
using EonaCat.Logger.Servers.Splunk.Models;
using Microsoft.Extensions.Logging;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -20,120 +23,6 @@ using static EonaCat.Logger.Managers.LogHelper;
namespace EonaCat.Logger.Managers;
-///
-/// Provides a collection of predefined and customizable header token resolvers for formatting log or message headers.
-///
-/// HeaderTokens exposes a set of standard tokens that can be used to insert runtime, environment, and
-/// contextual information into header strings, such as timestamps, process details, thread information, and more.
-/// Custom tokens can be added or overridden to support application-specific formatting needs. All token keys are
-/// case-insensitive. This class is thread-safe for read operations, but adding or overriding tokens is not guaranteed
-/// to be thread-safe and should be synchronized if used concurrently.
-public class HeaderTokens
-{
- private readonly Dictionary> _tokenResolvers =
- new(StringComparer.OrdinalIgnoreCase)
- {
- ["date"] = ctx => $"[Date: {ctx.Timestamp:yyyy-MM-dd}]",
-
- ["time"] = ctx => $"[Time: {ctx.Timestamp:HH:mm:ss.fff}]",
-
- ["ticks"] = ctx => $"[Ticks: {ctx.Timestamp.Ticks}]",
-
- ["ts"] = ctx => $"[{ctx.Timestamp.ToString(ctx.TimestampFormat)}]",
-
- ["tz"] = ctx => $"[{(ctx.Timestamp.Kind == DateTimeKind.Utc ? "UTC" : "LOCAL")}]",
-
- ["unix"] = ctx => $"[Unix: {new DateTimeOffset(ctx.Timestamp).ToUnixTimeSeconds()}]",
-
- ["procstart"] = _ =>
- {
- var p = Process.GetCurrentProcess();
- return $"[ProcStart: {p.StartTime:O}]";
- },
-
- ["uptime"] = _ =>
- {
- var p = Process.GetCurrentProcess();
- return $"[Uptime: {(DateTime.Now - p.StartTime).TotalSeconds:F0}s]";
- },
-
- ["framework"] = _ =>
- $"[Runtime: {RuntimeInformation.FrameworkDescription}]",
-
- ["os"] = _ =>
- $"[OS: {RuntimeInformation.OSDescription}]",
-
- ["arch"] = _ =>
- $"[Arch: {RuntimeInformation.ProcessArchitecture}]",
-
- ["mem"] = _ => $"[Memory: {GC.GetTotalMemory(false) / 1024 / 1024}MB]",
-
- ["gc"] = _ => $"[GC: {GC.CollectionCount(0)}/{GC.CollectionCount(1)}/{GC.CollectionCount(2)}]",
-
- ["cwd"] = _ => $"[CWD: {Environment.CurrentDirectory}]",
-
- ["app"] = _ => $"[App: {AppDomain.CurrentDomain.FriendlyName}]",
-
- ["appbase"] = _ => $"[AppBase: {AppDomain.CurrentDomain.BaseDirectory}]",
-
- ["domain"] = _ => $"[Domain: {AppDomain.CurrentDomain.Id}]",
-
- ["threadname"] = _ => $"[ThreadName: {Thread.CurrentThread.Name ?? "n/a"}]",
-
- ["task"] = _ => $"[TaskId: {Task.CurrentId?.ToString() ?? "n/a"}]",
-
- ["host"] = ctx => $"[Host: {ctx.HostName}]",
-
- ["machine"] = _ => $"[Machine: {Environment.MachineName}]",
-
- ["category"] = ctx => $"[Category: {ctx.Category}]",
-
- ["thread"] = _ => $"[Thread: {Environment.CurrentManagedThreadId}]",
-
- ["process"] = _ =>
- {
- var p = Process.GetCurrentProcess();
- return $"[Process: {p.ProcessName}]";
- },
-
- ["pid"] = _ => $"[PID: {Process.GetCurrentProcess().Id}]",
-
- ["sev"] = ctx => $"[Severity: {ctx.LogType}]",
-
- ["user"] = _ => $"[User: {Environment.UserName}]",
-
- ["env"] = ctx => $"[Env: {ctx.EnvironmentName}]",
-
- ["newline"] = _ => Environment.NewLine
- };
-
- ///
- /// Gets a read-only dictionary of token resolver functions used to generate header values based on a token name and
- /// header context.
- ///
- /// Each entry maps a token name to a function that produces the corresponding header value for a
- /// given . The dictionary is static and cannot be modified at runtime.
- public IReadOnlyDictionary> TokenResolvers => _tokenResolvers;
-
- ///
- /// Adds or overrides a custom token.
- ///
- public void AddCustomToken(string key, Func resolver)
- {
- if (string.IsNullOrWhiteSpace(key))
- {
- throw new ArgumentException("Token key cannot be null or whitespace.", nameof(key));
- }
-
- if (resolver == null)
- {
- throw new ArgumentNullException(nameof(resolver));
- }
-
- _tokenResolvers[key] = resolver;
- }
-}
-
public class ErrorMessage
{
public Exception Exception { get; set; }
@@ -160,10 +49,15 @@ public static class LogHelper
private static readonly string MachineName = Environment.MachineName;
private static readonly string HostName = Dns.GetHostName();
+ private static readonly object _settingsLock = new object();
+
+ private static readonly object _consoleLock = new object();
+
+ private static readonly ConcurrentDictionary _regexCache = new ConcurrentDictionary();
+
internal static string ConvertToSyslogRfc5424(LoggerSettings settings, ELogType logType, string currentMessage, DateTime dateTime, string category = null)
{
string formattedMessage = FormatMessageWithHeader(settings, logType, currentMessage, dateTime, category);
-
if (string.IsNullOrWhiteSpace(formattedMessage))
{
return formattedMessage;
@@ -188,7 +82,6 @@ public static class LogHelper
internal static string ConvertToSyslogRfc3164(LoggerSettings settings, ELogType logType, string currentMessage, DateTime dateTime, string category = null)
{
string formattedMessage = FormatMessageWithHeader(settings, logType, currentMessage, dateTime, category);
-
if (string.IsNullOrWhiteSpace(formattedMessage))
{
return formattedMessage;
@@ -210,7 +103,9 @@ public static class LogHelper
return string.Empty;
}
- return Regex.Replace(format, @"\{([^}]+)\}", match =>
+ var regex = _regexCache.GetOrAdd(@"\{([^}]+)\}", pattern => new Regex(pattern, RegexOptions.Compiled));
+
+ return regex.Replace(format, match =>
{
var tokenText = match.Groups[1].Value;
@@ -230,15 +125,15 @@ public static class LogHelper
});
}
-
-
-
- internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string message, DateTime dateTime, string category = null)
+ internal static string FormatMessageWithHeader(
+ LoggerSettings settings,
+ ELogType logType,
+ string message,
+ DateTime dateTime,
+ string category = null)
{
if (string.IsNullOrWhiteSpace(message))
- {
return message;
- }
var ctx = new HeaderContext
{
@@ -251,19 +146,28 @@ public static class LogHelper
EnvironmentName = settings?.EnvironmentName
};
- string header = settings?.CustomHeaderFormatter != null
- ? settings.CustomHeaderFormatter(ctx)
- : ResolveHeader(settings?.HeaderFormat, ctx);
+ string header = string.Empty;
- if (!string.IsNullOrEmpty(header))
+ if (!string.IsNullOrWhiteSpace(settings?.HeaderFormat) || settings?.CustomHeaderFormatter != null)
{
- header += " ";
+ if (settings.CustomHeaderFormatter != null)
+ {
+ header = settings.CustomHeaderFormatter(ctx) ?? string.Empty;
+ }
+ else
+ {
+ header = ResolveHeader(settings.HeaderFormat, ctx);
+ }
+
+ if (!string.IsNullOrEmpty(header))
+ header += " ";
}
return header + message;
}
+
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message)
{
if (settings == null || string.IsNullOrWhiteSpace(message))
@@ -271,24 +175,27 @@ public static class LogHelper
return;
}
- if (settings.EnableColors && settings.Colors != null)
+ lock (_consoleLock)
{
- var prevForeground = Console.ForegroundColor;
- var prevBackground = Console.BackgroundColor;
-
- if (TryGetLogColor(settings.Colors, logType, out var foregroundColor, out var backgroundColor))
+ if (settings.EnableColors && settings.Colors != null)
{
- Console.ForegroundColor = foregroundColor;
- Console.BackgroundColor = backgroundColor;
- }
+ var prevForeground = Console.ForegroundColor;
+ var prevBackground = Console.BackgroundColor;
- Console.WriteLine(message);
- Console.ForegroundColor = prevForeground;
- Console.BackgroundColor = prevBackground;
- }
- else
- {
- Console.WriteLine(message);
+ if (TryGetLogColor(settings.Colors, logType, out var foregroundColor, out var backgroundColor))
+ {
+ Console.ForegroundColor = foregroundColor;
+ Console.BackgroundColor = backgroundColor;
+ }
+
+ Console.WriteLine(message);
+ Console.ForegroundColor = prevForeground;
+ Console.BackgroundColor = prevBackground;
+ }
+ else
+ {
+ Console.WriteLine(message);
+ }
}
}
@@ -338,7 +245,9 @@ public static class LogHelper
return false;
}
- var isEnabled = loggerSettings?.TypesToLog == null || loggerSettings.TypesToLog.Count == 0 || loggerSettings.TypesToLog.Contains(logType);
+ var typesToLog = loggerSettings?.TypesToLog;
+ var isEnabled = typesToLog == null || typesToLog.Count == 0 || typesToLog.Contains(logType);
+
if (!isEnabled)
{
OnLogLevelDisabled?.Invoke(null, new ErrorMessage { Message = $"Logtype '{logType}' is not enabled." });
@@ -351,39 +260,44 @@ public static class LogHelper
public static void AddLogLevel(LoggerSettings settings, ELogType logType)
{
- if (logType == ELogType.NONE)
+ if (logType == ELogType.NONE || settings == null)
{
return;
}
- if (settings.TypesToLog == null || settings.TypesToLog.Count == 0)
+ lock (_settingsLock)
{
- settings.TypesToLog = new List();
- }
+ if (settings.TypesToLog == null)
+ {
+ settings.TypesToLog = new List();
+ }
- if (!settings.TypesToLog.Contains(logType))
- {
- settings.TypesToLog.Add(logType);
+ if (!settings.TypesToLog.Contains(logType))
+ {
+ settings.TypesToLog.Add(logType);
+ }
}
}
public static void RemoveLogLevel(LoggerSettings settings, ELogType logType)
{
- if (logType == ELogType.NONE)
+ if (logType == ELogType.NONE || settings == null)
{
return;
}
- if (settings.TypesToLog == null || settings.TypesToLog.Count == 0)
+ lock (_settingsLock)
{
- settings.TypesToLog = new List();
- }
+ if (settings.TypesToLog == null)
+ {
+ settings.TypesToLog = new List();
+ }
- if (!settings.TypesToLog.Contains(logType))
- {
- return;
+ if (settings.TypesToLog.Contains(logType))
+ {
+ settings.TypesToLog.Remove(logType);
+ }
}
- settings.TypesToLog.Remove(logType);
}
private static void Log(ILogger logger, LogLevel logLevel, string message)
@@ -403,12 +317,13 @@ public static class LogHelper
return;
}
- if (settings.SplunkServers == null || settings.SplunkServers.Count() == 0)
+ var servers = settings.SplunkServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
- var tasks = settings.SplunkServers?
+ var tasks = servers
.Where(splunkServer => splunkServer.HasHecUrl && splunkServer.HasHecToken)
.Select(async splunkServer =>
{
@@ -422,7 +337,8 @@ public static class LogHelper
return;
}
- var isEnabled = (splunkServer?.TypesToLog == null || splunkServer?.TypesToLog.Count == 0 || splunkServer.TypesToLog.Contains(currentLogType));
+ var serverTypesToLog = splunkServer?.TypesToLog;
+ var isEnabled = (serverTypesToLog == null || serverTypesToLog.Count == 0 || serverTypesToLog.Contains(currentLogType));
if (!isEnabled)
{
splunkServer?.DisposeHttpClient();
@@ -431,7 +347,7 @@ public static class LogHelper
}
var response = await splunkServer?.SendAsync(splunkPayload, disableSplunkSSL);
- if (!response.IsSuccessStatusCode)
+ if (response != null && !response.IsSuccessStatusCode)
{
LogError($"Failed to send log to Splunk '{splunkServer?.SplunkHecUrl}'. Status code: {response.StatusCode}");
}
@@ -440,7 +356,7 @@ public static class LogHelper
{
LogError($"Error logging to Splunk '{splunkServer?.SplunkHecUrl}': {ex.Message}", ex);
}
- }) ?? new List();
+ });
await Task.WhenAll(tasks);
}
@@ -455,7 +371,8 @@ public static class LogHelper
return;
}
- if (settings.SplunkServers == null || settings.SplunkServers.Count() == 0)
+ var servers = settings.SplunkServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
@@ -487,7 +404,8 @@ public static class LogHelper
return;
}
- if (settings.GrayLogServers == null || settings.GrayLogServers.Count() == 0)
+ var servers = settings.GrayLogServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
@@ -507,7 +425,7 @@ public static class LogHelper
var messageBytes = Encoding.UTF8.GetBytes(JsonHelper.ToJson(gelfMessage));
- var tasks = settings.GrayLogServers?
+ var tasks = servers
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
.Select(async grayLogServer =>
{
@@ -519,7 +437,8 @@ public static class LogHelper
return;
}
- var isEnabled = (grayLogServer?.TypesToLog == null || grayLogServer.TypesToLog.Count == 0 || grayLogServer.TypesToLog.Contains(logType));
+ var serverTypesToLog = grayLogServer?.TypesToLog;
+ var isEnabled = (serverTypesToLog == null || serverTypesToLog.Count == 0 || serverTypesToLog.Contains(logType));
if (!isEnabled)
{
grayLogServer?.DisposeUdp();
@@ -555,7 +474,7 @@ public static class LogHelper
Message = $"Error logging to GrayLog Server '{grayLogServer.Hostname}': {ex.Message}"
});
}
- }) ?? new List();
+ });
await Task.WhenAll(tasks);
}
@@ -599,12 +518,13 @@ public static class LogHelper
return;
}
- if (settings.SysLogServers == null || settings.SysLogServers.Count() == 0)
+ var servers = settings.SysLogServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
- var tasks = settings.SysLogServers?
+ var tasks = servers
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
.Select(async server =>
{
@@ -616,27 +536,30 @@ public static class LogHelper
return;
}
- var isEnabled = (server?.TypesToLog == null || server.TypesToLog.Count == 0 || server.TypesToLog.Contains(logType));
+ var serverTypesToLog = server?.TypesToLog;
+ var isEnabled = (serverTypesToLog == null || serverTypesToLog.Count == 0 || serverTypesToLog.Contains(logType));
if (!isEnabled)
{
server?.DisposeUdp();
return;
}
+ string serverMessage = message;
+
if (server.ConvertToRfc5424)
{
- message = ConvertToSyslogRfc5424(settings, logType, message, dateTime, category);
+ serverMessage = ConvertToSyslogRfc5424(settings, logType, serverMessage, dateTime, category);
}
else if (server.ConvertToRfc3164)
{
- message = ConvertToSyslogRfc3164(settings, logType, message, dateTime, category);
+ serverMessage = ConvertToSyslogRfc3164(settings, logType, serverMessage, dateTime, category);
}
if (!server.IsConnected)
{
server.SetUdp();
}
- await server.WriteAsync(message);
+ await server.WriteAsync(serverMessage);
}
catch (Exception ex)
{
@@ -646,7 +569,7 @@ public static class LogHelper
Message = $"Error logging to SysLog Server '{server.Hostname}': {ex.Message}"
});
}
- }) ?? new List();
+ });
await Task.WhenAll(tasks);
}
@@ -658,12 +581,13 @@ public static class LogHelper
return;
}
- if (settings.TcpServers == null || settings.TcpServers.Count() == 0)
+ var servers = settings.TcpServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
- var tasks = settings.TcpServers?
+ var tasks = servers
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
.Select(async server =>
{
@@ -675,7 +599,8 @@ public static class LogHelper
return;
}
- var isEnabled = (server?.TypesToLog == null || server.TypesToLog.Count == 0 || server.TypesToLog.Contains(logType));
+ var serverTypesToLog = server?.TypesToLog;
+ var isEnabled = (serverTypesToLog == null || serverTypesToLog.Count == 0 || serverTypesToLog.Contains(logType));
if (!isEnabled)
{
server?.DisposeTcp();
@@ -698,7 +623,7 @@ public static class LogHelper
Message = $"Error logging to Tcp Server '{server.Hostname}': {ex.Message}"
});
}
- }) ?? new List();
+ });
await Task.WhenAll(tasks);
}
@@ -710,12 +635,13 @@ public static class LogHelper
return;
}
- if (settings.UdpServers == null || settings.UdpServers.Count() == 0)
+ var servers = settings.UdpServers?.ToList();
+ if (servers == null || servers.Count == 0)
{
return;
}
- var tasks = settings.UdpServers?
+ var tasks = servers
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
.Select(async server =>
{
@@ -727,7 +653,8 @@ public static class LogHelper
return;
}
- var isEnabled = (server?.TypesToLog == null || server.TypesToLog.Count == 0 || server.TypesToLog.Contains(logType));
+ var serverTypesToLog = server?.TypesToLog;
+ var isEnabled = (serverTypesToLog == null || serverTypesToLog.Count == 0 || serverTypesToLog.Contains(logType));
if (!isEnabled)
{
server?.DisposeUdp();
@@ -750,10 +677,11 @@ public static class LogHelper
Message = $"Error logging to Udp Server '{server.Hostname}': {ex.Message}"
});
}
- }) ?? new List();
+ });
await Task.WhenAll(tasks);
}
+
internal static string GetStartupMessage()
{
return $"{DllInfo.ApplicationName} started.";
diff --git a/EonaCat.Logger/Managers/LogManager.cs b/EonaCat.Logger/Managers/LogManager.cs
index ea43d2b..9ef12f7 100644
--- a/EonaCat.Logger/Managers/LogManager.cs
+++ b/EonaCat.Logger/Managers/LogManager.cs
@@ -1,12 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using EonaCat.Logger.EonaCatCoreLogger;
+using EonaCat.Logger.EonaCatCoreLogger;
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
+using EonaCat.Logger.EonaCatCoreLogger.Internal;
using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.Extensions;
using EonaCat.Logger.Servers.GrayLog;
@@ -16,6 +10,13 @@ using EonaCat.Logger.Servers.Tcp;
using EonaCat.Logger.Servers.Udp;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
// 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.
@@ -171,6 +172,7 @@ namespace EonaCat.Logger.Managers
.AddEonaCatFileLogger(config =>
{
var options = Settings.FileLoggerOptions;
+ config.LoggerSettings = Settings;
config.MaxWriteTries = options.MaxWriteTries;
config.RetainedFileCountLimit = options.RetainedFileCountLimit;
config.FlushPeriod = options.FlushPeriod;
@@ -185,13 +187,13 @@ namespace EonaCat.Logger.Managers
config.Mask = options.Mask;
config.UseDefaultMasking = Settings.UseDefaultMasking;
config.MaskedKeywords = options.MaskedKeywords;
+ config.Settings = Settings;
}));
- var serviceProvider = serviceCollection.BuildServiceProvider();
- LoggerProvider = serviceProvider.GetService();
- LoggerFactory = serviceProvider.GetService();
+ var serviceProvider = serviceCollection.BuildServiceProvider();
+ LoggerProvider = serviceProvider.GetService();
+ LoggerFactory = serviceProvider.GetService();
Logger = LoggerFactory.CreateLogger(Settings.Id);
-
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
}
@@ -212,6 +214,7 @@ namespace EonaCat.Logger.Managers
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
var writeToConsoleValue = writeToConsole.GetValueOrDefault(Settings.EnableConsole);
+ // Send message without header to the fileProvider
LogHelper.SendToFile(Logger, Settings, logType, message);
if (writeToConsoleValue)
@@ -240,7 +243,7 @@ namespace EonaCat.Logger.Managers
Settings.OnLogEvent(new EonaCatLogMessage
{
DateTime = dateTime,
- Message = message,
+ Message = messageWithHeader,
LogType = logType,
Origin = string.IsNullOrEmpty(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin,
Category = _category
diff --git a/EonaCat.Logger/Managers/LoggerSettings.cs b/EonaCat.Logger/Managers/LoggerSettings.cs
index 9eda9bf..ce95f87 100644
--- a/EonaCat.Logger/Managers/LoggerSettings.cs
+++ b/EonaCat.Logger/Managers/LoggerSettings.cs
@@ -24,7 +24,7 @@ public class LoggerSettings
private FileLoggerOptions _fileLoggerOptions;
- private string _headerFormat = "{ts} {tz} {host} {category} {thread} {sev}";
+ private string _headerFormat = "{ts} {tz} {host} {category} {thread} {LogType}";
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
///
@@ -51,8 +51,8 @@ public class LoggerSettings
/// {host}: Hostname
/// {category}: Category
/// {thread}: Thread ID
- /// {sev}: Severity
- /// Default: {ts} {tz} {host} {category} {thread} {sev}
+ /// {LogType}: LogType
+ /// Default: {ts} {tz} {host} {category} {thread} {LogType}
/// A space will be inserted between the header and the message.
///
public string HeaderFormat
diff --git a/Testers/EonaCat.Logger.Test.Web/Logger.cs b/Testers/EonaCat.Logger.Test.Web/Logger.cs
index c113505..851ec7f 100644
--- a/Testers/EonaCat.Logger.Test.Web/Logger.cs
+++ b/Testers/EonaCat.Logger.Test.Web/Logger.cs
@@ -37,22 +37,6 @@ public class Logger
UseLocalTime = UseLocalTime,
},
};
-
- LoggerSettings.CustomHeaderFormatter = ctx =>
- {
- if (ctx.LogType == ELogType.ERROR)
- {
- return $"{ctx.Timestamp:HH:mm:ss} [{ctx.LogType}]";
- }
-
- return $"{ctx.Timestamp:HH:mm:ss} [{ctx.LogType}]";
- };
-
- LoggerSettings.Toke
-
- _logManager = new LogManager(LoggerSettings);
- _logManager.Settings.TypesToLog.Clear();
- _logManager.Settings.LogInfo();
}
public void DeleteCurrentLogFile()
@@ -139,9 +123,20 @@ public class Logger
return;
}
+ InitLogger();
await _logManager.WriteAsync(message, logType, writeToConsole).ConfigureAwait(false);
}
+ private void InitLogger()
+ {
+ if (_logManager == null)
+ {
+ // Initialize LogManager
+ _logManager = new LogManager(LoggerSettings);
+ _logManager.Settings.TypesToLog.Clear();
+ }
+ }
+
public async Task LogAsync(Exception exception, string message = "", bool writeToConsole = true)
{
if (IsDisabled)
@@ -149,6 +144,7 @@ public class Logger
return;
}
+ InitLogger();
if (LoggerSettings.TypesToLog.Contains(ELogType.ERROR))
{
await _logManager.WriteAsync(exception, message, writeToConsole: writeToConsole).ConfigureAwait(false);
diff --git a/Testers/EonaCat.Logger.Test.Web/Program.cs b/Testers/EonaCat.Logger.Test.Web/Program.cs
index 4f457ad..a077139 100644
--- a/Testers/EonaCat.Logger.Test.Web/Program.cs
+++ b/Testers/EonaCat.Logger.Test.Web/Program.cs
@@ -39,16 +39,16 @@
int onLogCounter = 0;
var defaultColor = Console.ForegroundColor;
- _ = Task.Run(() =>
- {
- var logman = LogManager.Instance;
- var i = 0;
- while (true)
- {
- logman.WriteAsync($"Logman test {++i}", ELogType.TRACE).ConfigureAwait(false);
- Task.Delay(10).ConfigureAwait(false);
- }
- }).ConfigureAwait(false);
+ //_ = Task.Run(() =>
+ //{
+ // var logman = LogManager.Instance;
+ // var i = 0;
+ // while (true)
+ // {
+ // logman.WriteAsync($"Logman test {++i}", ELogType.TRACE).ConfigureAwait(false);
+ // Task.Delay(10).ConfigureAwait(false);
+ // }
+ //}).ConfigureAwait(false);
// Add services to the container.
Logger logger = new Logger();
@@ -64,6 +64,20 @@
logger.LoggerSettings.OnLog += LoggerSettings_OnLog;
logger.LoggerSettings.UseMask = true;
+ //LoggerSettings.CustomHeaderFormatter = ctx =>
+ //{
+ // if (ctx.LogType == ELogType.ERROR)
+ // {
+ // return $"{ctx.Timestamp:HH:mm:ss} [{ctx.LogType}]";
+ // }
+
+ // return $"{ctx.Timestamp:HH:mm:ss} [{ctx.LogType}]";
+ //};
+
+ logger.LoggerSettings.CustomHeaderFormatter = null; // remove the lambda
+ logger.LoggerSettings.HeaderTokens.AddCustomToken("AppName", x => "[JIJ BENT EEN BRASSER!]");
+ logger.LoggerSettings.HeaderFormat = "{AppName} {LogType} {ts}";
+
// Configure the client
var centralOptions = new LogCentralOptions
{