Added some ObjectExtensions

This commit is contained in:
2026-01-05 15:38:08 +01:00
parent ec32464c5b
commit d385119ca2
6 changed files with 878 additions and 432 deletions

View File

@@ -2,9 +2,9 @@
<PropertyGroup>
<TargetFrameworks>.netstandard2.1; net8.0; net4.8;</TargetFrameworks>
<ApplicationIcon>icon.ico</ApplicationIcon>
<Version>1.4.8</Version>
<Version>1.4.9</Version>
<LangVersion>latest</LangVersion>
<FileVersion>1.4.8</FileVersion>
<FileVersion>1.4.9</FileVersion>
<Authors>EonaCat (Jeroen Saey)</Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Company>EonaCat (Jeroen Saey)</Company>
@@ -25,7 +25,7 @@
</PropertyGroup>
<PropertyGroup>
<EVRevisionFormat>1.4.8+{chash:10}.{c:ymd}</EVRevisionFormat>
<EVRevisionFormat>1.4.9+{chash:10}.{c:ymd}</EVRevisionFormat>
<EVDefault>true</EVDefault>
<EVInfo>true</EVInfo>
<EVTagMatch>v[0-9]*</EVTagMatch>

View File

@@ -2,6 +2,9 @@
namespace EonaCat.Logger.Extensions;
// 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 static class DateTimeExtensions
{
public static long ToUnixTimestamp(this DateTime dateTime)

View File

@@ -1,98 +1,101 @@
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 = -1;
string filename = "Unknown";
if (frame != null)
{
fileLine = frame.GetFileLineNumber();
filename = frame.GetFileName();
}
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
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)
{
var sb = new StringBuilder();
foreach (DictionaryEntry entry in data)
{
using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
namespace EonaCat.Logger.Extensions;
// 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 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 = -1;
string filename = "Unknown";
if (frame != null)
{
fileLine = frame.GetFileLineNumber();
filename = frame.GetFileName();
}
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
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)
{
var sb = new StringBuilder();
foreach (DictionaryEntry entry in data)
{
if (entry.Key != null)
{
sb.Append(" | ")
sb.Append(" | ")
.Append(entry.Key);
}
}
if (entry.Value != null)
{
sb.Append(": ")
sb.Append(": ")
.AppendLine(entry.Value.ToString());
}
}
return sb.ToString();
}
private static string FormatInnerException(Exception innerException)
{
var sb = new StringBuilder();
sb.AppendLine(innerException.GetType().ToString())
.AppendLine(" Message : " + innerException.Message)
.AppendLine(" Source : " + innerException.Source)
.AppendLine(" StackTrace : " + innerException.StackTrace)
.AppendLine(" ToString : " + innerException)
.Append(" Data : ")
.AppendLine(innerException.Data != null && innerException.Data.Count > 0
? FormatExceptionData(innerException.Data)
: "(none)");
return sb.ToString();
}
}
}
return sb.ToString();
}
private static string FormatInnerException(Exception innerException)
{
var sb = new StringBuilder();
sb.AppendLine(innerException.GetType().ToString())
.AppendLine(" Message : " + innerException.Message)
.AppendLine(" Source : " + innerException.Source)
.AppendLine(" StackTrace : " + innerException.StackTrace)
.AppendLine(" ToString : " + innerException)
.Append(" Data : ")
.AppendLine(innerException.Data != null && innerException.Data.Count > 0
? FormatExceptionData(innerException.Data)
: "(none)");
return sb.ToString();
}
}

View File

@@ -0,0 +1,425 @@
using EonaCat.Json;
using EonaCat.Json.Serialization;
using EonaCat.Logger.Managers;
using Microsoft.Extensions.Logging;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace EonaCat.Logger.Extensions
{
// 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 enum DumpFormat
{
Json,
Xml,
Tree
}
public static class ObjectExtensions
{
/// <summary>
/// Dumps any object to a string in JSON, XML, or detailed tree format.
/// </summary>
/// <param name="currentObject">Object to dump</param>
/// <param name="format">"json" (default), "xml", or "tree"</param>
/// <param name="detailed">For JSON: include private/internal fields. Ignored for tree format</param>
/// <param name="maxDepth">Optional max depth for tree dump. Null = no limit</param>
/// <param name="maxCollectionItems">Optional max items to display in collections. Null = show all</param>
/// <returns>String representation of the object</returns>
public static string Dump(this object currentObject, DumpFormat format = DumpFormat.Json, bool detailed = false, int? maxDepth = null, int? maxCollectionItems = null)
{
if (currentObject == null)
{
return "null";
}
try
{
switch (format)
{
case DumpFormat.Xml:
return DumpXml(currentObject);
case DumpFormat.Tree:
return DumpTree(currentObject, maxDepth, maxCollectionItems);
case DumpFormat.Json:
default:
return DumpJson(currentObject, detailed);
}
}
catch (Exception ex)
{
return $"Error dumping object: {ex.Message}";
}
}
private static string DumpJson(object currentObject, bool isDetailed)
{
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
if (isDetailed)
{
settings.ContractResolver = new DefaultContractResolver
{
IgnoreSerializableAttribute = false,
IgnoreSerializableInterface = false
};
}
return JsonHelper.ToJson(currentObject, settings);
}
private static string DumpXml(object currentObject)
{
try
{
var xmlSerializer = new XmlSerializer(currentObject.GetType());
using (var stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, currentObject);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
return $"XML serialization failed: {ex.Message}";
}
}
private static string DumpTree(object currentObject, int? maxDepth, int? maxCollectionItems)
{
var stringBuilder = new StringBuilder();
var visitedHashSet = new HashSet<object>(new ReferenceEqualityComparer());
DumpTreeInternal(currentObject, stringBuilder, 0, visitedHashSet, maxDepth, maxCollectionItems);
return stringBuilder.ToString();
}
private static void DumpTreeInternal(object currentObject, StringBuilder stringBuilder, int indent, HashSet<object> visited, int? maxDepth, int? maxCollectionItems)
{
string indentation = new string(' ', indent * 2);
if (currentObject == null)
{
stringBuilder.AppendLine($"{indentation}null");
return;
}
Type type = currentObject.GetType();
string typeName = type.FullName;
if (IsPrimitive(type))
{
stringBuilder.AppendLine($"{indentation}{currentObject} ({typeName})");
return;
}
if (visited.Contains(currentObject))
{
stringBuilder.AppendLine($"{indentation}<<circular reference to {typeName}>>");
return;
}
if (maxDepth.HasValue && indent >= maxDepth.Value)
{
stringBuilder.AppendLine($"{indentation}<<max depth reached: {typeName}>>");
return;
}
visited.Add(currentObject);
if (currentObject is IEnumerable enumerable && !(currentObject is string))
{
int count = 0;
foreach (var _ in enumerable)
{
count++;
}
if (maxCollectionItems.HasValue && count > maxCollectionItems.Value)
{
stringBuilder.AppendLine($"{indentation}{typeName} [<<{count} items, collapsed>>]");
return;
}
stringBuilder.AppendLine($"{indentation}{typeName} [");
foreach (var item in enumerable)
{
DumpTreeInternal(item, stringBuilder, indent + 1, visited, maxDepth, maxCollectionItems);
}
stringBuilder.AppendLine($"{indentation}]");
}
else
{
stringBuilder.AppendLine($"{indentation}{typeName} {{");
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var members = type.GetFields(flags);
foreach (var field in members)
{
object value = null;
try
{
value = field.GetValue(currentObject);
}
catch
{
value = "<<unavailable>>";
}
stringBuilder.Append($"{indentation} {field.Name} = ");
DumpTreeInternal(value, stringBuilder, indent + 1, visited, maxDepth, maxCollectionItems);
}
var properties = type.GetProperties(flags);
foreach (var current in properties)
{
if (current.GetIndexParameters().Length > 0)
{
continue;
}
object value = null;
try { value = current.GetValue(currentObject); } catch { value = "<<unavailable>>"; }
stringBuilder.Append($"{indentation} {current.Name} = ");
DumpTreeInternal(value, stringBuilder, indent + 1, visited, maxDepth, maxCollectionItems);
}
stringBuilder.AppendLine($"{indentation}}}");
}
}
private static bool IsPrimitive(Type type)
{
return type.IsPrimitive
|| type.IsEnum
|| type == typeof(string)
|| type == typeof(decimal)
|| type == typeof(DateTime)
|| type == typeof(DateTimeOffset)
|| type == typeof(Guid)
|| type == typeof(TimeSpan);
}
private class ReferenceEqualityComparer : IEqualityComparer<object>
{
public new bool Equals(object x, object y) => ReferenceEquals(x, y);
public int GetHashCode(object obj) => System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
}
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
if (items == null || action == null)
{
return;
}
foreach (var item in items)
{
action(item);
}
}
/// <summary>Check if collection is null or empty</summary>
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items) => items == null || !items.Any();
/// <summary>Check if collection has items</summary>
public static bool HasItems<T>(this IEnumerable<T> items) => !items.IsNullOrEmpty();
/// <summary>Safe get by index</summary>
public static T SafeGet<T>(this IList<T> list, int index, T defaultValue = default)
{
if (list == null || index < 0 || index >= list.Count)
{
return defaultValue;
}
return list[index];
}
/// <summary>Convert collection to delimited string</summary>
public static string ToDelimitedString<T>(this IEnumerable<T> items, string delimiter = ", ")
{
return items == null ? "" : string.Join(delimiter, items);
}
public static bool IsNullOrWhiteSpace(this string s) => string.IsNullOrWhiteSpace(s);
public static string Truncate(this string s, int maxLength)
{
if (string.IsNullOrEmpty(s))
{
return s;
}
return s.Length <= maxLength ? s : s.Substring(0, maxLength);
}
public static bool ContainsIgnoreCase(this string s, string value) =>
s?.IndexOf(value ?? "", StringComparison.OrdinalIgnoreCase) >= 0;
public static string OrDefault(this string s, string defaultValue) =>
string.IsNullOrEmpty(s) ? defaultValue : s;
public static bool IsWeekend(this DateTime date) =>
date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
public static DateTime StartOfDay(this DateTime date) =>
date.Date;
public static DateTime EndOfDay(this DateTime date) =>
date.Date.AddDays(1).AddTicks(-1);
/// <summary>
/// Log an object only if a condition is true.
/// </summary>
public static async Task LogIfAsync(this LogManager logger, object currentObject, Func<object, bool> condition,
ELogType logType = ELogType.INFO, string message = null)
{
if (logger == null || currentObject == null || condition == null)
{
return;
}
if (condition(currentObject))
{
string output = message ?? currentObject.Dump();
await logger.WriteAsync(output, logType);
}
}
public static IDisposable BeginLoggingScope(this ILogger logger, object context)
{
if (logger == null || context == null)
{
return null;
}
return logger.BeginScope(context.ToDictionary());
}
public static void LogExecutionTime(this ILogger logger, Action action, string operationName)
{
if (logger == null || action == null)
{
return;
}
var sw = System.Diagnostics.Stopwatch.StartNew();
action();
sw.Stop();
logger.LogInformation("{Operation} executed in {ElapsedMilliseconds}ms", operationName, sw.ElapsedMilliseconds);
}
/// <summary>
/// Converts a Unix timestamp, expressed as the number of seconds since the Unix epoch, to a local DateTime
/// value.
/// </summary>
/// <remarks>The returned DateTime is expressed in the local time zone. To obtain a UTC DateTime,
/// use DateTimeOffset.FromUnixTimeSeconds(timestamp).UtcDateTime instead.</remarks>
/// <param name="timestamp">The Unix timestamp representing the number of seconds that have elapsed since 00:00:00 UTC on 1 January
/// 1970.</param>
/// <returns>A DateTime value that represents the local date and time equivalent of the specified Unix timestamp.</returns>
public static DateTime FromUnixTimestamp(this long timestamp) =>
DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
/// <summary>
/// Executes the specified task without waiting for its completion and handles any exceptions that occur during
/// its execution.
/// </summary>
/// <remarks>Use this method to start a task when you do not need to await its completion but want
/// to ensure that exceptions are observed. This method should be used with caution, as exceptions may be
/// handled asynchronously and may not be propagated to the calling context. Avoid using this method for tasks
/// that must complete before continuing execution.</remarks>
/// <param name="task">The task to execute in a fire-and-forget manner. Cannot be null.</param>
/// <param name="onError">An optional callback that is invoked if the task throws an exception. If not provided, exceptions are
/// written to the console.</param>
public static async void FireAndForget(this Task task, Action<Exception> onError = null)
{
if (task == null)
{
return;
}
try { await task; }
catch (Exception ex)
{
if (onError != null)
{
onError(ex);
}
else
{
Console.WriteLine("FireAndForget Exception: " + ex.FormatExceptionToMessage());
}
}
}
/// <summary>Check if object has property</summary>
public static bool HasProperty(this object obj, string name) =>
obj != null && obj.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null;
/// <summary>Get property value safely</summary>
public static object GetPropertyValue(this object obj, string name)
{
if (obj == null)
{
return null;
}
var prop = obj.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
return prop?.GetValue(obj);
}
/// <summary>
/// Creates a dictionary containing the public and non-public instance properties and fields of the specified
/// object.
/// </summary>
/// <remarks>Indexed properties are excluded from the resulting dictionary. Both public and
/// non-public instance members are included. If multiple members share the same name, property values will
/// overwrite field values with the same name.</remarks>
/// <param name="obj">The object whose properties and fields are to be included in the dictionary. Can be null.</param>
/// <returns>A dictionary with the names and values of the object's properties and fields. If the object is null, returns
/// an empty dictionary.</returns>
public static Dictionary<string, object> ToDictionary(this object obj)
{
if (obj == null)
{
return new Dictionary<string, object>();
}
var dict = new Dictionary<string, object>();
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
foreach (var prop in obj.GetType().GetProperties(flags))
{
if (prop.GetIndexParameters().Length > 0)
{
continue;
}
dict[prop.Name] = prop.GetValue(obj);
}
foreach (var field in obj.GetType().GetFields(flags))
{
dict[field.Name] = field.GetValue(obj);
}
return dict;
}
}
}

View File

@@ -76,6 +76,21 @@ namespace EonaCat.Logger.Managers
GC.SuppressFinalize(this);
}
public async Task WriteAsync(object currentObject, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
string customSplunkSourceType = null,
string grayLogFacility = null, string grayLogSource = null,
string grayLogVersion = "1.1", bool disableSplunkSSL = false, DumpFormat dumpFormat = DumpFormat.Json, bool isDetailedDump = false, int? dumpDepth = null, int? maxCollectionItems = null)
{
if (currentObject == null)
{
return;
}
await WriteAsync(currentObject.Dump(dumpFormat, isDetailedDump, dumpDepth, maxCollectionItems), logType, writeToConsole,
customSplunkSourceType, grayLogFacility, grayLogSource,
grayLogVersion, disableSplunkSSL);
}
public async Task WriteAsync(Exception exception, string module = null, string method = null,
bool criticalException = false,
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,

View File

@@ -1,343 +1,343 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using EonaCat.Json.Linq;
using EonaCat.Logger.EonaCatCoreLogger;
using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.Servers.GrayLog;
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.
/// <summary>
/// Logger settings.
/// </summary>
public class LoggerSettings
{
public delegate void LogDelegate(EonaCatLogMessage message);
private ColorSchema _colors = new();
private bool _enableConsole = true;
private FileLoggerOptions _fileLoggerOptions;
private string _headerFormat = "{ts} {host} {category} {thread} {sev}";
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
/// <summary>
/// Determines if we need to use the local time in the logging or UTC (default:false)
/// </summary>
public bool UseLocalTime { get; set; }
public string Id { get; set; } = DllInfo.ApplicationName;
/// <summary>
/// Header format. Provide a string that specifies how the preamble of each message should be structured. You can use
/// variables including:
/// {ts}: UTC timestamp
/// {host}: Hostname
/// {category}: Category
/// {thread}: Thread ID
/// {sev}: Severity
/// Default: {ts} {host} {category} {thread} {sev}
/// A space will be inserted between the header and the message.
/// </summary>
public string HeaderFormat
{
get => _headerFormat;
set
{
if (string.IsNullOrEmpty(value))
{
_headerFormat = "";
}
else
{
_headerFormat = value;
}
}
}
/// <summary>
/// Timestamp format.
/// </summary>
public string TimestampFormat
{
get => _timestampFormat;
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException(nameof(HeaderFormat));
}
_timestampFormat = value;
}
}
/// <summary>
/// Enable or disable console logging.
/// Settings this to true will first validate if a console exists.
/// If a console is not available, it will be set to false.
/// </summary>
public bool EnableConsole
{
get => _enableConsole;
set
{
if (value)
{
_enableConsole = ConsoleExists();
}
else
{
_enableConsole = false;
}
}
}
/// <summary>
/// Enable or disable use of color for console messages.
/// </summary>
public bool EnableColors { get; set; } = true;
/// <summary>
/// Colors to use for console messages based on message severity.
/// </summary>
public ColorSchema Colors
{
get => _colors;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(Colors));
}
_colors = value;
}
}
private readonly List<ELogType> _defaultLogTypes = new List<ELogType> { ELogType.INFO, ELogType.WARNING, ELogType.ERROR, ELogType.TRAFFIC, ELogType.DEBUG, ELogType.CRITICAL, ELogType.TRACE };
private List<ELogType> _logTypes = new List<ELogType> { ELogType.INFO, ELogType.WARNING, ELogType.ERROR, ELogType.TRAFFIC, ELogType.DEBUG, ELogType.CRITICAL, ELogType.TRACE };
public List<ELogType> TypesToLog
{
get
{
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using EonaCat.Json.Linq;
using EonaCat.Logger.EonaCatCoreLogger;
using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.Servers.GrayLog;
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.
/// <summary>
/// Logger settings.
/// </summary>
public class LoggerSettings
{
public delegate void LogDelegate(EonaCatLogMessage message);
private ColorSchema _colors = new();
private bool _enableConsole = true;
private FileLoggerOptions _fileLoggerOptions;
private string _headerFormat = "{ts} {host} {category} {thread} {sev}";
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
/// <summary>
/// Determines if we need to use the local time in the logging or UTC (default:false)
/// </summary>
public bool UseLocalTime { get; set; }
public string Id { get; set; } = DllInfo.ApplicationName;
/// <summary>
/// Header format. Provide a string that specifies how the preamble of each message should be structured. You can use
/// variables including:
/// {ts}: UTC timestamp
/// {host}: Hostname
/// {category}: Category
/// {thread}: Thread ID
/// {sev}: Severity
/// Default: {ts} {host} {category} {thread} {sev}
/// A space will be inserted between the header and the message.
/// </summary>
public string HeaderFormat
{
get => _headerFormat;
set
{
if (string.IsNullOrEmpty(value))
{
_headerFormat = "";
}
else
{
_headerFormat = value;
}
}
}
/// <summary>
/// Timestamp format.
/// </summary>
public string TimestampFormat
{
get => _timestampFormat;
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException(nameof(HeaderFormat));
}
_timestampFormat = value;
}
}
/// <summary>
/// Enable or disable console logging.
/// Settings this to true will first validate if a console exists.
/// If a console is not available, it will be set to false.
/// </summary>
public bool EnableConsole
{
get => _enableConsole;
set
{
if (value)
{
_enableConsole = ConsoleExists();
}
else
{
_enableConsole = false;
}
}
}
/// <summary>
/// Enable or disable use of color for console messages.
/// </summary>
public bool EnableColors { get; set; } = true;
/// <summary>
/// Colors to use for console messages based on message severity.
/// </summary>
public ColorSchema Colors
{
get => _colors;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(Colors));
}
_colors = value;
}
}
private readonly List<ELogType> _defaultLogTypes = new List<ELogType> { ELogType.INFO, ELogType.WARNING, ELogType.ERROR, ELogType.TRAFFIC, ELogType.DEBUG, ELogType.CRITICAL, ELogType.TRACE };
private List<ELogType> _logTypes = new List<ELogType> { ELogType.INFO, ELogType.WARNING, ELogType.ERROR, ELogType.TRAFFIC, ELogType.DEBUG, ELogType.CRITICAL, ELogType.TRACE };
public List<ELogType> TypesToLog
{
get
{
if (_logTypes == null)
{
_logTypes = _defaultLogTypes;
}
return _logTypes;
}
set
}
return _logTypes;
}
set
{
_logTypes = value;
}
}
public List<Servers.Syslog.Syslog> SysLogServers { get; internal set; }
public List<Servers.Splunk.Splunk> SplunkServers { get; internal set; }
public List<Graylog> GrayLogServers { get; internal set; }
public List<Servers.Tcp.Tcp> TcpServers { get; internal set; }
public List<Servers.Udp.Udp> UdpServers { get; internal set; }
/// <summary>
/// Determines if the fileLogging is enabled
/// </summary>
public bool EnableFileLogging { get; set; } = true;
/// <summary>
/// FileLogger settings.
/// </summary>
public FileLoggerOptions FileLoggerOptions
{
get
{
if (_fileLoggerOptions == null)
{
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
}
return _fileLoggerOptions;
}
set => _fileLoggerOptions = value;
}
/// <summary>
/// Set the origin of where the OnLog event was initiated
/// </summary>
public string LogOrigin { get; set; }
/// <summary>
/// Determines if we need to mask certain keywords
/// </summary>
public bool UseMask { get; set; }
/// <summary>
/// Determines the keywords to mask
/// </summary>
public List<string> MaskedKeywords { get; set; } = new List<string>();
public string Mask { get; set; } = "***MASKED***";
/// <summary>
/// Determines that if masking is enabled we also need to use the default masking options:
/// IP addresses
/// MAC addresses
/// Emails
/// Passwords
/// Credit card numbers
/// Social security numbers (SSN) and BSN (Dutch Citizen Service Number)
/// API keys/tokens
/// Phone numbers (generic and Dutch specific)
/// Dates of birth (DOB) or other date formats
/// IBAN/Bank account numbers (generic and Dutch specific)
/// JWT tokens
/// URLs with sensitive query strings
/// License keys
/// Public and private keys (e.g., PEM format)
/// Dutch KVK number (8 or 12 digits)
/// Dutch BTW-nummer (VAT number)
/// Dutch driving license number (10-12 characters)
/// Dutch health insurance number (Zorgnummer)
/// Other Dutch Bank Account numbers (9-10 digits)
/// Dutch Passport Numbers (9 alphanumeric characters
/// Dutch Identification Document Numbers (varying formats)
/// Custom keywords specified in LoggerSettings
/// </summary>
public bool UseDefaultMasking { get; set; } = true;
public event LogDelegate OnLog;
private static FileLoggerOptions CreateDefaultFileLoggerOptions()
{
return new FileLoggerOptions();
}
private static bool ConsoleExists()
{
try
{
var test1 = Environment.UserInteractive;
var test2 = Console.WindowHeight > 0;
return test1 && test2;
}
catch (Exception)
{
return false;
}
}
internal void OnLogEvent(EonaCatLogMessage eonaCatLogMessage)
{
OnLog?.Invoke(eonaCatLogMessage);
}
internal void ResetLogEvent()
{
OnLog = null;
}
public void AllowAllLogTypes()
{
TypesToLog.Clear();
}
public void LogInfo()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.INFO))
{
TypesToLog.Add(ELogType.INFO);
}
}
public void LogWarning()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.WARNING))
{
TypesToLog.Add(ELogType.WARNING);
}
}
public void LogError()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.ERROR))
{
TypesToLog.Add(ELogType.ERROR);
}
}
public void LogCritical()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.CRITICAL))
{
TypesToLog.Add(ELogType.CRITICAL);
}
}
public void LogTraffic()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.TRAFFIC))
{
TypesToLog.Add(ELogType.TRAFFIC);
}
}
public void LogTrace()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.TRACE))
{
TypesToLog.Add(ELogType.TRACE);
}
}
public void LogDebug()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.DEBUG))
{
TypesToLog.Add(ELogType.DEBUG);
}
}
_logTypes = value;
}
}
public List<Servers.Syslog.Syslog> SysLogServers { get; internal set; }
public List<Servers.Splunk.Splunk> SplunkServers { get; internal set; }
public List<Graylog> GrayLogServers { get; internal set; }
public List<Servers.Tcp.Tcp> TcpServers { get; internal set; }
public List<Servers.Udp.Udp> UdpServers { get; internal set; }
/// <summary>
/// Determines if the fileLogging is enabled
/// </summary>
public bool EnableFileLogging { get; set; } = true;
/// <summary>
/// FileLogger settings.
/// </summary>
public FileLoggerOptions FileLoggerOptions
{
get
{
if (_fileLoggerOptions == null)
{
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
}
return _fileLoggerOptions;
}
set => _fileLoggerOptions = value;
}
/// <summary>
/// Set the origin of where the OnLog event was initiated
/// </summary>
public string LogOrigin { get; set; }
/// <summary>
/// Determines if we need to mask certain keywords
/// </summary>
public bool UseMask { get; set; }
/// <summary>
/// Determines the keywords to mask
/// </summary>
public List<string> MaskedKeywords { get; set; } = new List<string>();
public string Mask { get; set; } = "***MASKED***";
/// <summary>
/// Determines that if masking is enabled we also need to use the default masking options:
/// IP addresses
/// MAC addresses
/// Emails
/// Passwords
/// Credit card numbers
/// Social security numbers (SSN) and BSN (Dutch Citizen Service Number)
/// API keys/tokens
/// Phone numbers (generic and Dutch specific)
/// Dates of birth (DOB) or other date formats
/// IBAN/Bank account numbers (generic and Dutch specific)
/// JWT tokens
/// URLs with sensitive query strings
/// License keys
/// Public and private keys (e.g., PEM format)
/// Dutch KVK number (8 or 12 digits)
/// Dutch BTW-nummer (VAT number)
/// Dutch driving license number (10-12 characters)
/// Dutch health insurance number (Zorgnummer)
/// Other Dutch Bank Account numbers (9-10 digits)
/// Dutch Passport Numbers (9 alphanumeric characters
/// Dutch Identification Document Numbers (varying formats)
/// Custom keywords specified in LoggerSettings
/// </summary>
public bool UseDefaultMasking { get; set; } = true;
public event LogDelegate OnLog;
private static FileLoggerOptions CreateDefaultFileLoggerOptions()
{
return new FileLoggerOptions();
}
private static bool ConsoleExists()
{
try
{
var test1 = Environment.UserInteractive;
var test2 = Console.WindowHeight > 0;
return test1 && test2;
}
catch (Exception)
{
return false;
}
}
internal void OnLogEvent(EonaCatLogMessage eonaCatLogMessage)
{
OnLog?.Invoke(eonaCatLogMessage);
}
internal void ResetLogEvent()
{
OnLog = null;
}
public void AllowAllLogTypes()
{
TypesToLog.Clear();
}
public void LogInfo()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.INFO))
{
TypesToLog.Add(ELogType.INFO);
}
}
public void LogWarning()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.WARNING))
{
TypesToLog.Add(ELogType.WARNING);
}
}
public void LogError()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.ERROR))
{
TypesToLog.Add(ELogType.ERROR);
}
}
public void LogCritical()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.CRITICAL))
{
TypesToLog.Add(ELogType.CRITICAL);
}
}
public void LogTraffic()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.TRAFFIC))
{
TypesToLog.Add(ELogType.TRAFFIC);
}
}
public void LogTrace()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.TRACE))
{
TypesToLog.Add(ELogType.TRACE);
}
}
public void LogDebug()
{
if (TypesToLog == null)
{
TypesToLog = new List<ELogType>();
}
if (!TypesToLog.Contains(ELogType.DEBUG))
{
TypesToLog.Add(ELogType.DEBUG);
}
}
}