Added some ObjectExtensions
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>.netstandard2.1; net8.0; net4.8;</TargetFrameworks>
|
<TargetFrameworks>.netstandard2.1; net8.0; net4.8;</TargetFrameworks>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<Version>1.4.8</Version>
|
<Version>1.4.9</Version>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<FileVersion>1.4.8</FileVersion>
|
<FileVersion>1.4.9</FileVersion>
|
||||||
<Authors>EonaCat (Jeroen Saey)</Authors>
|
<Authors>EonaCat (Jeroen Saey)</Authors>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Company>EonaCat (Jeroen Saey)</Company>
|
<Company>EonaCat (Jeroen Saey)</Company>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<EVRevisionFormat>1.4.8+{chash:10}.{c:ymd}</EVRevisionFormat>
|
<EVRevisionFormat>1.4.9+{chash:10}.{c:ymd}</EVRevisionFormat>
|
||||||
<EVDefault>true</EVDefault>
|
<EVDefault>true</EVDefault>
|
||||||
<EVInfo>true</EVInfo>
|
<EVInfo>true</EVInfo>
|
||||||
<EVTagMatch>v[0-9]*</EVTagMatch>
|
<EVTagMatch>v[0-9]*</EVTagMatch>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace EonaCat.Logger.Extensions;
|
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 class DateTimeExtensions
|
||||||
{
|
{
|
||||||
public static long ToUnixTimestamp(this DateTime dateTime)
|
public static long ToUnixTimestamp(this DateTime dateTime)
|
||||||
|
|||||||
@@ -1,98 +1,101 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace EonaCat.Logger.Extensions;
|
namespace EonaCat.Logger.Extensions;
|
||||||
|
|
||||||
public static class ExceptionExtensions
|
// 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 string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
|
|
||||||
{
|
public static class ExceptionExtensions
|
||||||
if (exception == null)
|
{
|
||||||
{
|
public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
|
||||||
return string.Empty;
|
{
|
||||||
}
|
if (exception == null)
|
||||||
|
{
|
||||||
var st = new StackTrace(exception, true);
|
return string.Empty;
|
||||||
var frame = st.GetFrame(0);
|
}
|
||||||
int fileLine = -1;
|
|
||||||
string filename = "Unknown";
|
var st = new StackTrace(exception, true);
|
||||||
|
var frame = st.GetFrame(0);
|
||||||
if (frame != null)
|
int fileLine = -1;
|
||||||
{
|
string filename = "Unknown";
|
||||||
fileLine = frame.GetFileLineNumber();
|
|
||||||
filename = frame.GetFileName();
|
if (frame != null)
|
||||||
}
|
{
|
||||||
|
fileLine = frame.GetFileLineNumber();
|
||||||
var sb = new StringBuilder();
|
filename = frame.GetFileName();
|
||||||
|
}
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
|
var sb = new StringBuilder();
|
||||||
if (!string.IsNullOrEmpty(module))
|
|
||||||
{
|
sb.AppendLine();
|
||||||
sb.AppendLine(" Module : " + module);
|
sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
|
||||||
}
|
if (!string.IsNullOrEmpty(module))
|
||||||
|
{
|
||||||
if (!string.IsNullOrEmpty(method))
|
sb.AppendLine(" Module : " + module);
|
||||||
{
|
}
|
||||||
sb.AppendLine(" Method : " + method);
|
|
||||||
}
|
if (!string.IsNullOrEmpty(method))
|
||||||
|
{
|
||||||
sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
|
sb.AppendLine(" Method : " + method);
|
||||||
sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
|
}
|
||||||
? FormatExceptionData(exception.Data)
|
|
||||||
: "(none)");
|
sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
|
||||||
sb.Append(" Inner : ").AppendLine(exception.InnerException != null
|
sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
|
||||||
? FormatInnerException(exception.InnerException)
|
? FormatExceptionData(exception.Data)
|
||||||
: "(null)");
|
: "(none)");
|
||||||
sb.Append(" Message : ").AppendLine(exception.Message);
|
sb.Append(" Inner : ").AppendLine(exception.InnerException != null
|
||||||
sb.Append(" Source : ").AppendLine(exception.Source);
|
? FormatInnerException(exception.InnerException)
|
||||||
sb.Append(" StackTrace : ").AppendLine(exception.StackTrace);
|
: "(null)");
|
||||||
sb.Append(" Line : ").AppendLine(fileLine.ToString());
|
sb.Append(" Message : ").AppendLine(exception.Message);
|
||||||
sb.Append(" File : ").AppendLine(filename);
|
sb.Append(" Source : ").AppendLine(exception.Source);
|
||||||
sb.Append(" ToString : ").AppendLine(exception.ToString());
|
sb.Append(" StackTrace : ").AppendLine(exception.StackTrace);
|
||||||
sb.AppendLine("---");
|
sb.Append(" Line : ").AppendLine(fileLine.ToString());
|
||||||
|
sb.Append(" File : ").AppendLine(filename);
|
||||||
return sb.ToString();
|
sb.Append(" ToString : ").AppendLine(exception.ToString());
|
||||||
}
|
sb.AppendLine("---");
|
||||||
|
|
||||||
private static string FormatExceptionData(IDictionary data)
|
return sb.ToString();
|
||||||
{
|
}
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
private static string FormatExceptionData(IDictionary data)
|
||||||
foreach (DictionaryEntry entry in data)
|
{
|
||||||
{
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (DictionaryEntry entry in data)
|
||||||
|
{
|
||||||
if (entry.Key != null)
|
if (entry.Key != null)
|
||||||
{
|
{
|
||||||
sb.Append(" | ")
|
sb.Append(" | ")
|
||||||
.Append(entry.Key);
|
.Append(entry.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.Value != null)
|
if (entry.Value != null)
|
||||||
{
|
{
|
||||||
sb.Append(": ")
|
sb.Append(": ")
|
||||||
.AppendLine(entry.Value.ToString());
|
.AppendLine(entry.Value.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FormatInnerException(Exception innerException)
|
private static string FormatInnerException(Exception innerException)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
sb.AppendLine(innerException.GetType().ToString())
|
sb.AppendLine(innerException.GetType().ToString())
|
||||||
.AppendLine(" Message : " + innerException.Message)
|
.AppendLine(" Message : " + innerException.Message)
|
||||||
.AppendLine(" Source : " + innerException.Source)
|
.AppendLine(" Source : " + innerException.Source)
|
||||||
.AppendLine(" StackTrace : " + innerException.StackTrace)
|
.AppendLine(" StackTrace : " + innerException.StackTrace)
|
||||||
.AppendLine(" ToString : " + innerException)
|
.AppendLine(" ToString : " + innerException)
|
||||||
.Append(" Data : ")
|
.Append(" Data : ")
|
||||||
.AppendLine(innerException.Data != null && innerException.Data.Count > 0
|
.AppendLine(innerException.Data != null && innerException.Data.Count > 0
|
||||||
? FormatExceptionData(innerException.Data)
|
? FormatExceptionData(innerException.Data)
|
||||||
: "(none)");
|
: "(none)");
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
425
EonaCat.Logger/Extensions/ObjectExtensions.cs
Normal file
425
EonaCat.Logger/Extensions/ObjectExtensions.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,6 +76,21 @@ namespace EonaCat.Logger.Managers
|
|||||||
GC.SuppressFinalize(this);
|
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,
|
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
||||||
bool criticalException = false,
|
bool criticalException = false,
|
||||||
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
|
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
|
||||||
|
|||||||
@@ -1,343 +1,343 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using EonaCat.Json.Linq;
|
using EonaCat.Json.Linq;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger;
|
using EonaCat.Logger.EonaCatCoreLogger;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
||||||
using EonaCat.Logger.Servers.GrayLog;
|
using EonaCat.Logger.Servers.GrayLog;
|
||||||
|
|
||||||
namespace EonaCat.Logger.Managers;
|
namespace EonaCat.Logger.Managers;
|
||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
// 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.
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logger settings.
|
/// Logger settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LoggerSettings
|
public class LoggerSettings
|
||||||
{
|
{
|
||||||
public delegate void LogDelegate(EonaCatLogMessage message);
|
public delegate void LogDelegate(EonaCatLogMessage message);
|
||||||
|
|
||||||
private ColorSchema _colors = new();
|
private ColorSchema _colors = new();
|
||||||
private bool _enableConsole = true;
|
private bool _enableConsole = true;
|
||||||
|
|
||||||
private FileLoggerOptions _fileLoggerOptions;
|
private FileLoggerOptions _fileLoggerOptions;
|
||||||
|
|
||||||
private string _headerFormat = "{ts} {host} {category} {thread} {sev}";
|
private string _headerFormat = "{ts} {host} {category} {thread} {sev}";
|
||||||
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
|
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if we need to use the local time in the logging or UTC (default:false)
|
/// Determines if we need to use the local time in the logging or UTC (default:false)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseLocalTime { get; set; }
|
public bool UseLocalTime { get; set; }
|
||||||
|
|
||||||
public string Id { get; set; } = DllInfo.ApplicationName;
|
public string Id { get; set; } = DllInfo.ApplicationName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Header format. Provide a string that specifies how the preamble of each message should be structured. You can use
|
/// Header format. Provide a string that specifies how the preamble of each message should be structured. You can use
|
||||||
/// variables including:
|
/// variables including:
|
||||||
/// {ts}: UTC timestamp
|
/// {ts}: UTC timestamp
|
||||||
/// {host}: Hostname
|
/// {host}: Hostname
|
||||||
/// {category}: Category
|
/// {category}: Category
|
||||||
/// {thread}: Thread ID
|
/// {thread}: Thread ID
|
||||||
/// {sev}: Severity
|
/// {sev}: Severity
|
||||||
/// Default: {ts} {host} {category} {thread} {sev}
|
/// Default: {ts} {host} {category} {thread} {sev}
|
||||||
/// A space will be inserted between the header and the message.
|
/// A space will be inserted between the header and the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string HeaderFormat
|
public string HeaderFormat
|
||||||
{
|
{
|
||||||
get => _headerFormat;
|
get => _headerFormat;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
{
|
{
|
||||||
_headerFormat = "";
|
_headerFormat = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_headerFormat = value;
|
_headerFormat = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timestamp format.
|
/// Timestamp format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TimestampFormat
|
public string TimestampFormat
|
||||||
{
|
{
|
||||||
get => _timestampFormat;
|
get => _timestampFormat;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(HeaderFormat));
|
throw new ArgumentNullException(nameof(HeaderFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
_timestampFormat = value;
|
_timestampFormat = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable or disable console logging.
|
/// Enable or disable console logging.
|
||||||
/// Settings this to true will first validate if a console exists.
|
/// Settings this to true will first validate if a console exists.
|
||||||
/// If a console is not available, it will be set to false.
|
/// If a console is not available, it will be set to false.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableConsole
|
public bool EnableConsole
|
||||||
{
|
{
|
||||||
get => _enableConsole;
|
get => _enableConsole;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
_enableConsole = ConsoleExists();
|
_enableConsole = ConsoleExists();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_enableConsole = false;
|
_enableConsole = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable or disable use of color for console messages.
|
/// Enable or disable use of color for console messages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableColors { get; set; } = true;
|
public bool EnableColors { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Colors to use for console messages based on message severity.
|
/// Colors to use for console messages based on message severity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ColorSchema Colors
|
public ColorSchema Colors
|
||||||
{
|
{
|
||||||
get => _colors;
|
get => _colors;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(Colors));
|
throw new ArgumentNullException(nameof(Colors));
|
||||||
}
|
}
|
||||||
|
|
||||||
_colors = value;
|
_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 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 };
|
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
|
public List<ELogType> TypesToLog
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_logTypes == null)
|
if (_logTypes == null)
|
||||||
{
|
{
|
||||||
_logTypes = _defaultLogTypes;
|
_logTypes = _defaultLogTypes;
|
||||||
}
|
}
|
||||||
return _logTypes;
|
return _logTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_logTypes = value;
|
_logTypes = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Servers.Syslog.Syslog> SysLogServers { get; internal set; }
|
public List<Servers.Syslog.Syslog> SysLogServers { get; internal set; }
|
||||||
public List<Servers.Splunk.Splunk> SplunkServers { get; internal set; }
|
public List<Servers.Splunk.Splunk> SplunkServers { get; internal set; }
|
||||||
|
|
||||||
public List<Graylog> GrayLogServers { get; internal set; }
|
public List<Graylog> GrayLogServers { get; internal set; }
|
||||||
public List<Servers.Tcp.Tcp> TcpServers { get; internal set; }
|
public List<Servers.Tcp.Tcp> TcpServers { get; internal set; }
|
||||||
|
|
||||||
public List<Servers.Udp.Udp> UdpServers { get; internal set; }
|
public List<Servers.Udp.Udp> UdpServers { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the fileLogging is enabled
|
/// Determines if the fileLogging is enabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableFileLogging { get; set; } = true;
|
public bool EnableFileLogging { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// FileLogger settings.
|
/// FileLogger settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FileLoggerOptions FileLoggerOptions
|
public FileLoggerOptions FileLoggerOptions
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_fileLoggerOptions == null)
|
if (_fileLoggerOptions == null)
|
||||||
{
|
{
|
||||||
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
|
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _fileLoggerOptions;
|
return _fileLoggerOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
set => _fileLoggerOptions = value;
|
set => _fileLoggerOptions = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the origin of where the OnLog event was initiated
|
/// Set the origin of where the OnLog event was initiated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LogOrigin { get; set; }
|
public string LogOrigin { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if we need to mask certain keywords
|
/// Determines if we need to mask certain keywords
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseMask { get; set; }
|
public bool UseMask { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines the keywords to mask
|
/// Determines the keywords to mask
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> MaskedKeywords { get; set; } = new List<string>();
|
public List<string> MaskedKeywords { get; set; } = new List<string>();
|
||||||
public string Mask { get; set; } = "***MASKED***";
|
public string Mask { get; set; } = "***MASKED***";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines that if masking is enabled we also need to use the default masking options:
|
/// Determines that if masking is enabled we also need to use the default masking options:
|
||||||
/// IP addresses
|
/// IP addresses
|
||||||
/// MAC addresses
|
/// MAC addresses
|
||||||
/// Emails
|
/// Emails
|
||||||
/// Passwords
|
/// Passwords
|
||||||
/// Credit card numbers
|
/// Credit card numbers
|
||||||
/// Social security numbers (SSN) and BSN (Dutch Citizen Service Number)
|
/// Social security numbers (SSN) and BSN (Dutch Citizen Service Number)
|
||||||
/// API keys/tokens
|
/// API keys/tokens
|
||||||
/// Phone numbers (generic and Dutch specific)
|
/// Phone numbers (generic and Dutch specific)
|
||||||
/// Dates of birth (DOB) or other date formats
|
/// Dates of birth (DOB) or other date formats
|
||||||
/// IBAN/Bank account numbers (generic and Dutch specific)
|
/// IBAN/Bank account numbers (generic and Dutch specific)
|
||||||
/// JWT tokens
|
/// JWT tokens
|
||||||
/// URLs with sensitive query strings
|
/// URLs with sensitive query strings
|
||||||
/// License keys
|
/// License keys
|
||||||
/// Public and private keys (e.g., PEM format)
|
/// Public and private keys (e.g., PEM format)
|
||||||
/// Dutch KVK number (8 or 12 digits)
|
/// Dutch KVK number (8 or 12 digits)
|
||||||
/// Dutch BTW-nummer (VAT number)
|
/// Dutch BTW-nummer (VAT number)
|
||||||
/// Dutch driving license number (10-12 characters)
|
/// Dutch driving license number (10-12 characters)
|
||||||
/// Dutch health insurance number (Zorgnummer)
|
/// Dutch health insurance number (Zorgnummer)
|
||||||
/// Other Dutch Bank Account numbers (9-10 digits)
|
/// Other Dutch Bank Account numbers (9-10 digits)
|
||||||
/// Dutch Passport Numbers (9 alphanumeric characters
|
/// Dutch Passport Numbers (9 alphanumeric characters
|
||||||
/// Dutch Identification Document Numbers (varying formats)
|
/// Dutch Identification Document Numbers (varying formats)
|
||||||
/// Custom keywords specified in LoggerSettings
|
/// Custom keywords specified in LoggerSettings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseDefaultMasking { get; set; } = true;
|
public bool UseDefaultMasking { get; set; } = true;
|
||||||
|
|
||||||
public event LogDelegate OnLog;
|
public event LogDelegate OnLog;
|
||||||
|
|
||||||
private static FileLoggerOptions CreateDefaultFileLoggerOptions()
|
private static FileLoggerOptions CreateDefaultFileLoggerOptions()
|
||||||
{
|
{
|
||||||
return new FileLoggerOptions();
|
return new FileLoggerOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static bool ConsoleExists()
|
private static bool ConsoleExists()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var test1 = Environment.UserInteractive;
|
var test1 = Environment.UserInteractive;
|
||||||
var test2 = Console.WindowHeight > 0;
|
var test2 = Console.WindowHeight > 0;
|
||||||
return test1 && test2;
|
return test1 && test2;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnLogEvent(EonaCatLogMessage eonaCatLogMessage)
|
internal void OnLogEvent(EonaCatLogMessage eonaCatLogMessage)
|
||||||
{
|
{
|
||||||
OnLog?.Invoke(eonaCatLogMessage);
|
OnLog?.Invoke(eonaCatLogMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ResetLogEvent()
|
internal void ResetLogEvent()
|
||||||
{
|
{
|
||||||
OnLog = null;
|
OnLog = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AllowAllLogTypes()
|
public void AllowAllLogTypes()
|
||||||
{
|
{
|
||||||
TypesToLog.Clear();
|
TypesToLog.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogInfo()
|
public void LogInfo()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.INFO))
|
if (!TypesToLog.Contains(ELogType.INFO))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.INFO);
|
TypesToLog.Add(ELogType.INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogWarning()
|
public void LogWarning()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.WARNING))
|
if (!TypesToLog.Contains(ELogType.WARNING))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.WARNING);
|
TypesToLog.Add(ELogType.WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogError()
|
public void LogError()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.ERROR))
|
if (!TypesToLog.Contains(ELogType.ERROR))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.ERROR);
|
TypesToLog.Add(ELogType.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogCritical()
|
public void LogCritical()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.CRITICAL))
|
if (!TypesToLog.Contains(ELogType.CRITICAL))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.CRITICAL);
|
TypesToLog.Add(ELogType.CRITICAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogTraffic()
|
public void LogTraffic()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.TRAFFIC))
|
if (!TypesToLog.Contains(ELogType.TRAFFIC))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.TRAFFIC);
|
TypesToLog.Add(ELogType.TRAFFIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogTrace()
|
public void LogTrace()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.TRACE))
|
if (!TypesToLog.Contains(ELogType.TRACE))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.TRACE);
|
TypesToLog.Add(ELogType.TRACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogDebug()
|
public void LogDebug()
|
||||||
{
|
{
|
||||||
if (TypesToLog == null)
|
if (TypesToLog == null)
|
||||||
{
|
{
|
||||||
TypesToLog = new List<ELogType>();
|
TypesToLog = new List<ELogType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypesToLog.Contains(ELogType.DEBUG))
|
if (!TypesToLog.Contains(ELogType.DEBUG))
|
||||||
{
|
{
|
||||||
TypesToLog.Add(ELogType.DEBUG);
|
TypesToLog.Add(ELogType.DEBUG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user