Merge branch 'master' of https://git.saey.me/EonaCat/EonaCat.Logger
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<TargetFrameworks>.netstandard2.1; net6.0; net7.0; net8.0; net4.8;</TargetFrameworks>
|
<TargetFrameworks>.netstandard2.1; net6.0; net7.0; net8.0; net4.8;</TargetFrameworks>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<FileVersion>1.3.2</FileVersion>
|
<FileVersion>1.3.5</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>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<EVRevisionFormat>1.3.2+{chash:10}.{c:ymd}</EVRevisionFormat>
|
<EVRevisionFormat>1.3.5+{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>
|
||||||
|
|||||||
@@ -63,10 +63,17 @@ public static class ExceptionExtensions
|
|||||||
|
|
||||||
foreach (DictionaryEntry entry in data)
|
foreach (DictionaryEntry entry in data)
|
||||||
{
|
{
|
||||||
sb.Append(" | ")
|
if (entry.Key != null)
|
||||||
.Append(entry.Key)
|
{
|
||||||
.Append(": ")
|
sb.Append(" | ")
|
||||||
.AppendLine(entry.Value.ToString());
|
.Append(entry.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.Value != null)
|
||||||
|
{
|
||||||
|
sb.Append(": ")
|
||||||
|
.AppendLine(entry.Value.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ public class GrayLogServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// IP:port of the server.
|
/// IP:port of the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string IpPort => _Hostname + ":" + _Port;
|
public string IpPort => _Hostname + ":" + _Port;
|
||||||
|
|
||||||
|
public bool SupportsTcp { get; set; }
|
||||||
|
|
||||||
private void SetUdp()
|
private void SetUdp()
|
||||||
{
|
{
|
||||||
Udp = null;
|
Udp = null;
|
||||||
|
|||||||
@@ -1,306 +1,366 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Net.Sockets;
|
||||||
using EonaCat.Json;
|
using System.Text;
|
||||||
using EonaCat.Logger.Extensions;
|
using System.Threading.Tasks;
|
||||||
using EonaCat.Logger.GrayLog;
|
using EonaCat.Json;
|
||||||
using EonaCat.Logger.Splunk.Models;
|
using EonaCat.Logger.Extensions;
|
||||||
using EonaCat.Logger.Syslog;
|
using EonaCat.Logger.GrayLog;
|
||||||
using Microsoft.Extensions.Logging;
|
using EonaCat.Logger.Splunk.Models;
|
||||||
|
using EonaCat.Logger.Syslog;
|
||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
using Microsoft.Extensions.Logging;
|
||||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
|
||||||
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||||
namespace EonaCat.Logger.Managers;
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||||
|
|
||||||
public class ErrorMessage
|
namespace EonaCat.Logger.Managers;
|
||||||
{
|
|
||||||
public Exception Exception { get; set; }
|
public class ErrorMessage
|
||||||
public string Message { get; set; }
|
{
|
||||||
}
|
public Exception Exception { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
internal static class LogHelper
|
}
|
||||||
{
|
|
||||||
internal static event EventHandler<ErrorMessage> OnException;
|
internal static class LogHelper
|
||||||
|
{
|
||||||
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
|
internal static event EventHandler<ErrorMessage> OnException;
|
||||||
DateTime dateTime, string category = null)
|
|
||||||
{
|
internal static event EventHandler<ErrorMessage> OnLogLevelDisabled;
|
||||||
if (string.IsNullOrWhiteSpace(currentMessage))
|
|
||||||
{
|
private static readonly string MachineName = Environment.MachineName;
|
||||||
return currentMessage;
|
private static readonly string HostName = Dns.GetHostName();
|
||||||
}
|
|
||||||
|
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
|
||||||
if (string.IsNullOrWhiteSpace(category))
|
DateTime dateTime, string category = null)
|
||||||
{
|
{
|
||||||
category = "General";
|
if (string.IsNullOrWhiteSpace(currentMessage)) return currentMessage;
|
||||||
}
|
|
||||||
|
category ??= "General";
|
||||||
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
|
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
|
||||||
|
var timestamp = dateTime.ToString(settings?.TimestampFormat ?? "yyyy-MM-dd HH:mm:ss");
|
||||||
sb.Replace("{ts}",
|
var timeLabel = settings?.UseLocalTime ?? false ? "[LOCAL]" : "[UTC]";
|
||||||
dateTime.ToString(settings?.TimestampFormat ?? "yyyy-MM-dd HH:mm:ss") + " " +
|
|
||||||
(settings?.UseLocalTime ?? false ? "[LOCAL]" : "[UTC]"))
|
sb.Replace("{ts}", $"{timestamp} {timeLabel}")
|
||||||
.Replace("{host}", $"[Host:{Dns.GetHostName()}]")
|
.Replace("{host}", $"[Host:{HostName}]")
|
||||||
.Replace("{category}", $"[Category:{category}]")
|
.Replace("{category}", $"[Category:{category}]")
|
||||||
.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId}]")
|
.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId}]")
|
||||||
.Replace("{sev}", $"[{logType}]");
|
.Replace("{sev}", $"[{logType}]");
|
||||||
|
|
||||||
if (!settings?.RemoveMessagePrefix ?? (false && !currentMessage.Contains("[EonaCatLogger]")))
|
if (!(settings?.RemoveMessagePrefix ?? false) && !currentMessage.Contains("[EonaCatLogger]"))
|
||||||
{
|
{
|
||||||
sb.Insert(0, "[EonaCatLogger] ");
|
sb.Insert(0, "[EonaCatLogger] ");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.Append(" ").Append(currentMessage);
|
sb.Append(" ").Append(currentMessage);
|
||||||
|
return sb.ToString();
|
||||||
return sb.ToString();
|
}
|
||||||
}
|
|
||||||
|
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole)
|
||||||
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole)
|
{
|
||||||
{
|
if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message)) return;
|
||||||
if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message))
|
|
||||||
{
|
if (settings.EnableColors && settings.Colors != null)
|
||||||
return;
|
{
|
||||||
}
|
var prevForeground = Console.ForegroundColor;
|
||||||
|
var prevBackground = Console.BackgroundColor;
|
||||||
if (settings.EnableColors && settings.Colors != null)
|
|
||||||
{
|
if (TryGetLogColor(settings.Colors, logType, out var foregroundColor, out var backgroundColor))
|
||||||
var prevForeground = Console.ForegroundColor;
|
{
|
||||||
var prevBackground = Console.BackgroundColor;
|
Console.ForegroundColor = foregroundColor;
|
||||||
|
Console.BackgroundColor = backgroundColor;
|
||||||
ConsoleColor foregroundColor;
|
}
|
||||||
ConsoleColor backgroundColor;
|
|
||||||
switch (logType)
|
Console.WriteLine(message);
|
||||||
{
|
Console.ForegroundColor = prevForeground;
|
||||||
case ELogType.DEBUG:
|
Console.BackgroundColor = prevBackground;
|
||||||
foregroundColor = settings.Colors.Debug.Foreground;
|
}
|
||||||
backgroundColor = settings.Colors.Debug.Background;
|
else
|
||||||
break;
|
{
|
||||||
case ELogType.INFO:
|
Console.WriteLine(message);
|
||||||
foregroundColor = settings.Colors.Info.Foreground;
|
}
|
||||||
backgroundColor = settings.Colors.Info.Background;
|
}
|
||||||
break;
|
|
||||||
case ELogType.WARNING:
|
private static bool TryGetLogColor(ColorSchema colors, ELogType logType, out ConsoleColor foreground, out ConsoleColor background)
|
||||||
foregroundColor = settings.Colors.Warning.Foreground;
|
{
|
||||||
backgroundColor = settings.Colors.Warning.Background;
|
foreground = default;
|
||||||
break;
|
background = default;
|
||||||
case ELogType.ERROR:
|
|
||||||
foregroundColor = settings.Colors.Error.Foreground;
|
return logType switch
|
||||||
backgroundColor = settings.Colors.Error.Background;
|
{
|
||||||
break;
|
ELogType.DEBUG => TrySetColors(colors.Debug, out foreground, out background),
|
||||||
case ELogType.TRAFFIC:
|
ELogType.INFO => TrySetColors(colors.Info, out foreground, out background),
|
||||||
foregroundColor = settings.Colors.Traffic.Foreground;
|
ELogType.WARNING => TrySetColors(colors.Warning, out foreground, out background),
|
||||||
backgroundColor = settings.Colors.Traffic.Background;
|
ELogType.ERROR => TrySetColors(colors.Error, out foreground, out background),
|
||||||
break;
|
ELogType.TRAFFIC => TrySetColors(colors.Traffic, out foreground, out background),
|
||||||
case ELogType.CRITICAL:
|
ELogType.CRITICAL => TrySetColors(colors.Critical, out foreground, out background),
|
||||||
foregroundColor = settings.Colors.Critical.Foreground;
|
ELogType.TRACE => TrySetColors(colors.Trace, out foreground, out background),
|
||||||
backgroundColor = settings.Colors.Critical.Background;
|
_ => false,
|
||||||
break;
|
};
|
||||||
case ELogType.TRACE:
|
}
|
||||||
foregroundColor = settings.Colors.Trace.Foreground;
|
|
||||||
backgroundColor = settings.Colors.Trace.Background;
|
private static bool TrySetColors(ColorScheme color, out ConsoleColor foreground, out ConsoleColor background)
|
||||||
break;
|
{
|
||||||
default:
|
foreground = color.Foreground;
|
||||||
return;
|
background = color.Background;
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
Console.ForegroundColor = foregroundColor;
|
|
||||||
Console.BackgroundColor = backgroundColor;
|
internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message)
|
||||||
Console.WriteLine(message);
|
{
|
||||||
Console.ForegroundColor = prevForeground;
|
if (logger == null || settings == null || !settings.EnableFileLogging || string.IsNullOrWhiteSpace(message)) return;
|
||||||
Console.BackgroundColor = prevBackground;
|
|
||||||
}
|
if (IsLogLevelEnabled(settings, logType))
|
||||||
else
|
{
|
||||||
{
|
Log(logger, logType.ToLogLevel(), message);
|
||||||
Console.WriteLine(message);
|
}
|
||||||
}
|
}
|
||||||
}
|
private static bool IsLogLevelEnabled(LoggerSettings loggerSettings, ELogType logType)
|
||||||
|
{
|
||||||
internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message)
|
if (loggerSettings == null)
|
||||||
{
|
{
|
||||||
if (logger == null || settings == null || !settings.EnableFileLogging ||
|
OnLogLevelDisabled?.Invoke(null, new ErrorMessage { Message = "Settings is null." });
|
||||||
string.IsNullOrWhiteSpace(message))
|
return false;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
var isEnabled = loggerSettings.MaxLogType != ELogType.NONE && logType <= loggerSettings.MaxLogType;
|
||||||
|
if (!isEnabled)
|
||||||
var logLevel = logType.ToLogLevel();
|
{
|
||||||
if (IsLogLevelEnabled(settings, logType))
|
OnLogLevelDisabled?.Invoke(null, new ErrorMessage { Message = $"Logtype '{logType}' is not enabled." });
|
||||||
{
|
}
|
||||||
Log(logger, logLevel, message);
|
|
||||||
}
|
return isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsLogLevelEnabled(LoggerSettings settings, ELogType logType)
|
public static void SetLogLevel(LoggerSettings settings, ELogType logType)
|
||||||
{
|
{
|
||||||
return settings.MaxLogType != ELogType.NONE && logType <= settings.MaxLogType;
|
settings.MaxLogType = logType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Log(ILogger logger, LogLevel logLevel, string message)
|
private static void Log(ILogger logger, LogLevel logLevel, string message)
|
||||||
{
|
{
|
||||||
logger.Log(logLevel, message);
|
logger.Log(logLevel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, SplunkPayload splunkPayload,
|
public static async Task SendToSplunkServersAsync(LoggerSettings settings, SplunkPayload splunkPayload, bool sendToSplunkServer)
|
||||||
bool sendToSplunkServer)
|
{
|
||||||
{
|
if (settings == null || !sendToSplunkServer || splunkPayload == null)
|
||||||
if (settings == null || !sendToSplunkServer || splunkPayload == null)
|
{
|
||||||
{
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
var tasks = settings.SplunkServers?
|
||||||
if (settings.SplunkServers == null)
|
.Where(splunkServer => splunkServer.HasHecUrl && splunkServer.HasHecToken)
|
||||||
{
|
.Select(async splunkServer =>
|
||||||
settings.SplunkServers = new List<SplunkServer.SplunkServer>();
|
{
|
||||||
}
|
try
|
||||||
|
{
|
||||||
foreach (var splunkServer in settings.SplunkServers)
|
var response = await splunkServer.SendAsync(splunkPayload);
|
||||||
{
|
if (!response.IsSuccessStatusCode)
|
||||||
if (!splunkServer.HasHecUrl || !splunkServer.HasHecToken)
|
{
|
||||||
{
|
LogError($"Failed to send log to Splunk '{splunkServer.SplunkHecUrl}'. Status code: {response.StatusCode}");
|
||||||
OnException?.Invoke(null,
|
}
|
||||||
new ErrorMessage
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
Message =
|
{
|
||||||
$"Splunk server HecUrl or HecToken not specified, skipping splunkServer '{splunkServer.SplunkHecUrl}'"
|
LogError($"Error logging to Splunk '{splunkServer.SplunkHecUrl}': {ex.Message}", ex);
|
||||||
});
|
}
|
||||||
continue;
|
}) ?? new List<Task>();
|
||||||
}
|
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
try
|
}
|
||||||
{
|
|
||||||
var response = await splunkServer.SendAsync(splunkPayload);
|
/// <summary>
|
||||||
|
/// Overload for sending a simple log message to Splunk.
|
||||||
if (!response.IsSuccessStatusCode)
|
/// </summary>
|
||||||
{
|
public static async Task SendToSplunkServersAsync(LoggerSettings settings, string logType, string message, bool sendToSplunkServer)
|
||||||
OnException?.Invoke(null,
|
{
|
||||||
new ErrorMessage
|
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
|
||||||
{
|
{
|
||||||
Message =
|
return;
|
||||||
$"Failed to send log to Splunk '{splunkServer.SplunkHecUrl}'. Status code: {response.StatusCode}"
|
}
|
||||||
});
|
|
||||||
}
|
var splunkPayload = new SplunkPayload
|
||||||
}
|
{
|
||||||
catch (Exception exception)
|
Host = Environment.MachineName,
|
||||||
{
|
EventData = message,
|
||||||
OnException?.Invoke(null,
|
SourceType = logType
|
||||||
new ErrorMessage
|
};
|
||||||
{
|
|
||||||
Exception = exception,
|
await SendToSplunkServersAsync(settings, splunkPayload, sendToSplunkServer);
|
||||||
Message =
|
}
|
||||||
$"Error while logging to Splunk Server '{splunkServer.SplunkHecUrl}': {exception.Message}"
|
|
||||||
});
|
/// <summary>
|
||||||
}
|
/// Logs an error using the OnException event.
|
||||||
}
|
/// </summary>
|
||||||
}
|
private static void LogError(string message, Exception ex = null)
|
||||||
|
{
|
||||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, string logType, string message,
|
OnException?.Invoke(null, new ErrorMessage { Message = message, Exception = ex });
|
||||||
bool sendToSplunkServer)
|
}
|
||||||
{
|
|
||||||
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
|
|
||||||
{
|
internal static async Task SendToGrayLogServersAsync(LoggerSettings settings, string message, ELogType logLevel,
|
||||||
return;
|
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
|
||||||
}
|
{
|
||||||
|
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
|
||||||
var splunkPayload = new SplunkPayload
|
{
|
||||||
{
|
return;
|
||||||
Host = Environment.MachineName,
|
}
|
||||||
EventData = message,
|
|
||||||
SourceType = logType
|
const int MaxUdpPacketSize = 4096;
|
||||||
};
|
|
||||||
|
var gelfMessage = new
|
||||||
await SendToSplunkServersAsync(settings, splunkPayload, sendToSplunkServer);
|
{
|
||||||
}
|
version,
|
||||||
|
host = MachineName,
|
||||||
internal static async Task SendToGrayLogServersAsync(LoggerSettings settings, string message, ELogType logLevel,
|
short_message = message,
|
||||||
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
|
level = logLevel.ToGrayLogLevel(),
|
||||||
{
|
facility,
|
||||||
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
|
source,
|
||||||
{
|
timestamp = DateTime.UtcNow.ToUnixTimestamp()
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
|
var messageBytes = Encoding.UTF8.GetBytes(JsonHelper.ToJson(gelfMessage));
|
||||||
foreach (var grayLogServer in settings.GrayLogServers ?? new List<GrayLogServer> { new("127.0.0.1") })
|
|
||||||
{
|
var tasks = settings.GrayLogServers?
|
||||||
try
|
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
|
||||||
{
|
.Select(async grayLogServer =>
|
||||||
var gelfMessage = new
|
{
|
||||||
{
|
try
|
||||||
version,
|
{
|
||||||
host = Environment.MachineName,
|
if (messageBytes.Length <= MaxUdpPacketSize)
|
||||||
short_message = message,
|
{
|
||||||
level = logLevel.ToGrayLogLevel(),
|
// Send via UDP (single packet)
|
||||||
facility,
|
await grayLogServer.Udp.SendAsync(messageBytes, messageBytes.Length);
|
||||||
source,
|
}
|
||||||
timestamp = DateTime.UtcNow.ToUnixTimestamp()
|
else if (grayLogServer.SupportsTcp)
|
||||||
};
|
{
|
||||||
|
// Send via TCP if supported
|
||||||
var messageBytes = Encoding.UTF8.GetBytes(JsonHelper.ToJson(gelfMessage));
|
await SendViaTcpAsync(grayLogServer, messageBytes);
|
||||||
await grayLogServer.Udp.SendAsync(messageBytes, messageBytes.Length);
|
}
|
||||||
}
|
else
|
||||||
catch (Exception exception)
|
{
|
||||||
{
|
// Chunk large messages for UDP
|
||||||
OnException?.Invoke(null,
|
await SendUdpInChunksAsync(grayLogServer, messageBytes, MaxUdpPacketSize);
|
||||||
new ErrorMessage
|
}
|
||||||
{
|
}
|
||||||
Exception = exception,
|
catch (Exception ex)
|
||||||
Message =
|
{
|
||||||
$"Error while logging to GrayLog Server '{grayLogServer.Hostname}': {exception.Message}"
|
OnException?.Invoke(null, new ErrorMessage
|
||||||
});
|
{
|
||||||
}
|
Exception = ex,
|
||||||
}
|
Message = $"Error logging to GrayLog Server '{grayLogServer.Hostname}': {ex.Message}"
|
||||||
}
|
});
|
||||||
|
}
|
||||||
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message,
|
}) ?? new List<Task>();
|
||||||
bool sendToSyslogServers)
|
|
||||||
{
|
await Task.WhenAll(tasks);
|
||||||
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
|
}
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Sends a message via TCP to a GrayLog server.
|
||||||
foreach (var server in settings.SysLogServers ?? new List<SyslogServer> { new("127.0.0.1") })
|
/// </summary>
|
||||||
{
|
private static async Task SendViaTcpAsync(GrayLogServer server, byte[] data)
|
||||||
try
|
{
|
||||||
{
|
using var tcpClient = new TcpClient();
|
||||||
if (string.IsNullOrWhiteSpace(server.Hostname))
|
await tcpClient.ConnectAsync(server.Hostname, server.Port);
|
||||||
{
|
using var stream = tcpClient.GetStream();
|
||||||
OnException?.Invoke(null,
|
await stream.WriteAsync(data, 0, data.Length);
|
||||||
new ErrorMessage { Message = "Server hostname not specified, skipping SysLog Server" });
|
await stream.FlushAsync();
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
if (server.Port < 0)
|
/// Sends large messages in chunks over UDP.
|
||||||
{
|
/// </summary>
|
||||||
OnException?.Invoke(null,
|
private static async Task SendUdpInChunksAsync(GrayLogServer server, byte[] data, int chunkSize)
|
||||||
new ErrorMessage { Message = "Server port must be zero or greater, skipping SysLog Server" });
|
{
|
||||||
continue;
|
for (int i = 0; i < data.Length; i += chunkSize)
|
||||||
}
|
{
|
||||||
|
var chunk = data.Skip(i).Take(chunkSize).ToArray();
|
||||||
var data = Encoding.UTF8.GetBytes(message);
|
await server.Udp.SendAsync(chunk, chunk.Length);
|
||||||
await server.Udp.SendAsync(data, data.Length);
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
|
||||||
{
|
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message, bool sendToSyslogServers)
|
||||||
OnException?.Invoke(null,
|
{
|
||||||
new ErrorMessage
|
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
|
||||||
{
|
{
|
||||||
Exception = exception,
|
return;
|
||||||
Message = $"Error while logging to SysLog Server '{server.Hostname}': {exception.Message}"
|
}
|
||||||
});
|
|
||||||
}
|
const int MaxUdpPacketSize = 4096;
|
||||||
}
|
|
||||||
}
|
var tasks = settings.SysLogServers?
|
||||||
|
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
|
||||||
internal static string GetStartupMessage()
|
.Select(async server =>
|
||||||
{
|
{
|
||||||
return $"{DllInfo.ApplicationName} started.";
|
try
|
||||||
}
|
{
|
||||||
|
var data = Encoding.UTF8.GetBytes(message);
|
||||||
internal static string GetStopMessage()
|
|
||||||
{
|
if (data.Length <= MaxUdpPacketSize)
|
||||||
return $"{DllInfo.ApplicationName} stopped.";
|
{
|
||||||
}
|
// Send via UDP (single packet)
|
||||||
|
await server.Udp.SendAsync(data, data.Length);
|
||||||
|
}
|
||||||
|
else if (server.SupportsTcp)
|
||||||
|
{
|
||||||
|
// Send via TCP if supported
|
||||||
|
await SendViaTcpAsync(server, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Chunk large messages for UDP
|
||||||
|
await SendUdpInChunksAsync(server, data, MaxUdpPacketSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
OnException?.Invoke(null, new ErrorMessage
|
||||||
|
{
|
||||||
|
Exception = ex,
|
||||||
|
Message = $"Error logging to SysLog Server '{server.Hostname}': {ex.Message}"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}) ?? new List<Task>();
|
||||||
|
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a message via TCP to a syslog server.
|
||||||
|
/// </summary>
|
||||||
|
private static async Task SendViaTcpAsync(SyslogServer server, byte[] data)
|
||||||
|
{
|
||||||
|
using var tcpClient = new TcpClient();
|
||||||
|
await tcpClient.ConnectAsync(server.Hostname, server.Port);
|
||||||
|
using var stream = tcpClient.GetStream();
|
||||||
|
await stream.WriteAsync(data, 0, data.Length);
|
||||||
|
await stream.FlushAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends large messages in chunks over UDP.
|
||||||
|
/// </summary>
|
||||||
|
private static async Task SendUdpInChunksAsync(SyslogServer server, byte[] data, int chunkSize)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < data.Length; i += chunkSize)
|
||||||
|
{
|
||||||
|
var chunk = data.Skip(i).Take(chunkSize).ToArray();
|
||||||
|
await server.Udp.SendAsync(chunk, chunk.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static string GetStartupMessage()
|
||||||
|
{
|
||||||
|
return $"{DllInfo.ApplicationName} started.";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetStopMessage()
|
||||||
|
{
|
||||||
|
return $"{DllInfo.ApplicationName} stopped.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,324 +1,344 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.IO;
|
||||||
using System.IO;
|
using System.Threading;
|
||||||
using System.Threading;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
using EonaCat.Logger.EonaCatCoreLogger;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger;
|
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
|
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
using EonaCat.Logger.Extensions;
|
||||||
using EonaCat.Logger.Extensions;
|
using EonaCat.Logger.Syslog;
|
||||||
using EonaCat.Logger.Syslog;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
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.
|
|
||||||
|
public class LogManager : ILogManager, IDisposable
|
||||||
public class LogManager : ILogManager, IDisposable
|
{
|
||||||
{
|
private static readonly Lazy<LogManager> _instance = new(() => new LogManager(CreateDefaultSettings()));
|
||||||
private static readonly Lazy<LogManager> _instance = new(() => new LogManager(CreateDefaultSettings()));
|
private readonly CancellationTokenSource _tokenSource = new();
|
||||||
private readonly CancellationTokenSource _tokenSource = new();
|
private DateTime _logDate;
|
||||||
private DateTime _logDate;
|
private bool _isDisposing;
|
||||||
private bool _isDisposing;
|
private string _category;
|
||||||
private string _category;
|
|
||||||
|
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
||||||
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
{
|
||||||
{
|
if (string.IsNullOrEmpty(serverIp))
|
||||||
if (string.IsNullOrEmpty(serverIp))
|
{
|
||||||
{
|
throw new ArgumentNullException(nameof(serverIp));
|
||||||
throw new ArgumentNullException(nameof(serverIp));
|
}
|
||||||
}
|
|
||||||
|
if (serverPort < 0)
|
||||||
if (serverPort < 0)
|
{
|
||||||
{
|
throw new ArgumentException("Server port must be zero or greater.");
|
||||||
throw new ArgumentException("Server port must be zero or greater.");
|
}
|
||||||
}
|
|
||||||
|
settings.SysLogServers = new List<SyslogServer>
|
||||||
settings.SysLogServers = new List<SyslogServer>
|
{
|
||||||
{
|
new(serverIp, serverPort)
|
||||||
new(serverIp, serverPort)
|
};
|
||||||
};
|
|
||||||
|
Settings = settings;
|
||||||
Settings = settings;
|
SetupLogManager();
|
||||||
SetupLogManager();
|
}
|
||||||
}
|
|
||||||
|
public LogManager(LoggerSettings settings, string category = null)
|
||||||
public LogManager(LoggerSettings settings, string category = null)
|
{
|
||||||
{
|
_category = category;
|
||||||
_category = category;
|
if (string.IsNullOrWhiteSpace(category))
|
||||||
if (string.IsNullOrWhiteSpace(category))
|
{
|
||||||
{
|
_category = "General";
|
||||||
_category = "General";
|
}
|
||||||
}
|
Settings = settings;
|
||||||
Settings = settings;
|
SetupFileLogger(settings);
|
||||||
SetupFileLogger(settings);
|
SetupLogManager();
|
||||||
SetupLogManager();
|
LogHelper.OnException += LogHelper_OnException;
|
||||||
LogHelper.OnException += LogHelper_OnException;
|
LogHelper.OnLogLevelDisabled += LogHelper_OnLogLevelDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime CurrentDateTime => Settings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
private void LogHelper_OnLogLevelDisabled(object sender, ErrorMessage e)
|
||||||
public ILoggerProvider LoggerProvider { get; private set; }
|
{
|
||||||
public ILoggerFactory LoggerFactory { get; private set; }
|
OnLogLevelDisabled?.Invoke(sender, e);
|
||||||
public ILogger Logger { get; private set; }
|
}
|
||||||
|
|
||||||
public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider
|
private DateTime CurrentDateTime => Settings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
||||||
? fileLoggerProvider.LogFile
|
public ILoggerProvider LoggerProvider { get; private set; }
|
||||||
: string.Empty;
|
public ILoggerFactory LoggerFactory { get; private set; }
|
||||||
|
public ILogger Logger { get; private set; }
|
||||||
public bool IsRunning { get; private set; }
|
|
||||||
|
public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider
|
||||||
public static LogManager Instance => _instance.Value;
|
? fileLoggerProvider.LogFile
|
||||||
|
: string.Empty;
|
||||||
public LoggerSettings Settings { get; set; } = CreateDefaultSettings();
|
|
||||||
|
public bool IsRunning { get; private set; }
|
||||||
public void Dispose()
|
|
||||||
{
|
public static LogManager Instance => _instance.Value;
|
||||||
DisposeAsync(true).GetAwaiter().GetResult();
|
|
||||||
GC.SuppressFinalize(this);
|
public LoggerSettings Settings { get; set; } = CreateDefaultSettings();
|
||||||
}
|
|
||||||
|
public void Dispose()
|
||||||
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
{
|
||||||
bool criticalException = false,
|
DisposeAsync(true).GetAwaiter().GetResult();
|
||||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
GC.SuppressFinalize(this);
|
||||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
}
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
|
||||||
{
|
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
||||||
if (exception == null)
|
bool criticalException = false,
|
||||||
{
|
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||||
return;
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
}
|
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||||
|
{
|
||||||
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
if (exception == null)
|
||||||
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
{
|
||||||
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
return;
|
||||||
grayLogVersion);
|
}
|
||||||
}
|
|
||||||
|
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
||||||
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
||||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
||||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
grayLogVersion);
|
||||||
string grayLogVersion = "1.1")
|
}
|
||||||
{
|
|
||||||
if (logType == ELogType.NONE)
|
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||||
{
|
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||||
return;
|
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||||
}
|
string grayLogVersion = "1.1")
|
||||||
|
{
|
||||||
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
if (logType == ELogType.NONE)
|
||||||
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
|
{
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
public event EventHandler<ErrorMessage> OnException;
|
|
||||||
|
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
||||||
private static LoggerSettings CreateDefaultSettings()
|
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
|
||||||
{
|
}
|
||||||
var settings = new LoggerSettings
|
|
||||||
{
|
/// <summary>
|
||||||
Id = "EonaCatLogger",
|
/// Gets fired when an exception occurs during logging
|
||||||
MaxLogType = ELogType.INFO
|
/// </summary>
|
||||||
};
|
public event EventHandler<ErrorMessage> OnException;
|
||||||
return settings;
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Gets fired when the log level is disabled and the user tries to log a message
|
||||||
protected virtual async Task DisposeAsync(bool disposing)
|
/// </summary>
|
||||||
{
|
public event EventHandler<ErrorMessage> OnLogLevelDisabled;
|
||||||
if (disposing)
|
|
||||||
{
|
private static LoggerSettings CreateDefaultSettings()
|
||||||
_isDisposing = true;
|
{
|
||||||
await StopLoggingAsync();
|
var settings = new LoggerSettings
|
||||||
await Task.Delay(100);
|
{
|
||||||
}
|
Id = "EonaCatLogger",
|
||||||
}
|
MaxLogType = ELogType.INFO
|
||||||
|
};
|
||||||
public async Task StartNewLogAsync()
|
return settings;
|
||||||
{
|
}
|
||||||
if (_tokenSource.IsCancellationRequested)
|
|
||||||
{
|
protected virtual async Task DisposeAsync(bool disposing)
|
||||||
return;
|
{
|
||||||
}
|
if (disposing)
|
||||||
|
{
|
||||||
if (IsRunning && CurrentDateTime.Date > _logDate.Date)
|
_isDisposing = true;
|
||||||
{
|
await StopLoggingAsync();
|
||||||
await StopLoggingAsync();
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
IsRunning = true;
|
|
||||||
|
public async Task StartNewLogAsync()
|
||||||
CreateLogger();
|
{
|
||||||
|
if (_tokenSource.IsCancellationRequested)
|
||||||
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
{
|
||||||
|
return;
|
||||||
_logDate = CurrentDateTime;
|
}
|
||||||
}
|
|
||||||
|
if (IsRunning && CurrentDateTime.Date > _logDate.Date)
|
||||||
private void CreateLogger()
|
{
|
||||||
{
|
await StopLoggingAsync();
|
||||||
// Dispose of previous ServiceProvider if it exists
|
}
|
||||||
LoggerProvider?.Dispose();
|
|
||||||
LoggerFactory?.Dispose();
|
IsRunning = true;
|
||||||
|
|
||||||
IServiceCollection serviceCollection = new ServiceCollection();
|
CreateLogger();
|
||||||
serviceCollection.AddLogging(builder => builder.SetMinimumLevel(Settings.MaxLogType.ToLogLevel())
|
|
||||||
.AddEonaCatFileLogger(configuration =>
|
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
||||||
{
|
|
||||||
var fileLoggerOptions = Settings.FileLoggerOptions;
|
_logDate = CurrentDateTime;
|
||||||
configuration.MaxWriteTries = fileLoggerOptions.MaxWriteTries;
|
}
|
||||||
configuration.RetainedFileCountLimit = fileLoggerOptions.RetainedFileCountLimit;
|
|
||||||
configuration.FlushPeriod = fileLoggerOptions.FlushPeriod;
|
private void CreateLogger()
|
||||||
configuration.IsEnabled = fileLoggerOptions.IsEnabled;
|
{
|
||||||
configuration.BatchSize = fileLoggerOptions.BatchSize;
|
// Dispose of previous ServiceProvider if it exists
|
||||||
configuration.FileSizeLimit = fileLoggerOptions.FileSizeLimit;
|
LoggerProvider?.Dispose();
|
||||||
configuration.LogDirectory = fileLoggerOptions.LogDirectory;
|
LoggerFactory?.Dispose();
|
||||||
configuration.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
|
||||||
configuration.MaxRolloverFiles = fileLoggerOptions.MaxRolloverFiles;
|
IServiceCollection serviceCollection = new ServiceCollection();
|
||||||
configuration.UseLocalTime = Settings.UseLocalTime;
|
serviceCollection.AddLogging(builder => builder.SetMinimumLevel(Settings.MaxLogType.ToLogLevel())
|
||||||
configuration.UseMask = Settings.UseMask;
|
.AddEonaCatFileLogger(configuration =>
|
||||||
configuration.Mask = fileLoggerOptions.Mask;
|
{
|
||||||
configuration.UseDefaultMasking = Settings.UseDefaultMasking;
|
var fileLoggerOptions = Settings.FileLoggerOptions;
|
||||||
configuration.MaskedKeywords = fileLoggerOptions.MaskedKeywords;
|
configuration.MaxWriteTries = fileLoggerOptions.MaxWriteTries;
|
||||||
}));
|
configuration.RetainedFileCountLimit = fileLoggerOptions.RetainedFileCountLimit;
|
||||||
|
configuration.FlushPeriod = fileLoggerOptions.FlushPeriod;
|
||||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
configuration.IsEnabled = fileLoggerOptions.IsEnabled;
|
||||||
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
configuration.BatchSize = fileLoggerOptions.BatchSize;
|
||||||
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
configuration.FileSizeLimit = fileLoggerOptions.FileSizeLimit;
|
||||||
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
configuration.LogDirectory = fileLoggerOptions.LogDirectory;
|
||||||
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
|
configuration.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
||||||
}
|
configuration.MaxRolloverFiles = fileLoggerOptions.MaxRolloverFiles;
|
||||||
|
configuration.UseLocalTime = Settings.UseLocalTime;
|
||||||
private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO,
|
configuration.UseMask = Settings.UseMask;
|
||||||
bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null,
|
configuration.Mask = fileLoggerOptions.Mask;
|
||||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
configuration.UseDefaultMasking = Settings.UseDefaultMasking;
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
configuration.MaskedKeywords = fileLoggerOptions.MaskedKeywords;
|
||||||
{
|
}));
|
||||||
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE ||
|
|
||||||
(int)logType > (int)Settings.MaxLogType)
|
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||||
{
|
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
||||||
return;
|
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||||
}
|
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
||||||
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
|
||||||
if (_isDisposing)
|
}
|
||||||
{
|
|
||||||
return;
|
private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO,
|
||||||
}
|
bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null,
|
||||||
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
if (!IsRunning)
|
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||||
{
|
{
|
||||||
await StartNewLogAsync();
|
if (string.IsNullOrWhiteSpace(message) || logType == ELogType.NONE || !IsLogLevelEnabled(logType) || _isDisposing)
|
||||||
}
|
{
|
||||||
|
return;
|
||||||
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
|
}
|
||||||
var writeToConsoleValue = writeToConsole ?? Settings.EnableConsole;
|
|
||||||
var sendToSyslogServersValue = sendToSyslogServers ?? Settings.SendToSyslogServers;
|
if (!IsRunning)
|
||||||
var sendToSplunkServersValue = sendToSplunkServers ?? Settings.SendToSplunkServers;
|
{
|
||||||
var sendToGrayLogServersValue = sendToGrayLogServers ?? Settings.SendToGrayLogServers;
|
await StartNewLogAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
LogHelper.SendToFile(Logger, Settings, logType, message);
|
|
||||||
|
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
|
||||||
if (writeToConsoleValue)
|
var writeToConsoleValue = writeToConsole.GetValueOrDefault(Settings.EnableConsole);
|
||||||
{
|
var sendToSyslogServersValue = sendToSyslogServers.GetValueOrDefault(Settings.SendToSyslogServers);
|
||||||
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
|
var sendToSplunkServersValue = sendToSplunkServers.GetValueOrDefault(Settings.SendToSplunkServers);
|
||||||
}
|
var sendToGrayLogServersValue = sendToGrayLogServers.GetValueOrDefault(Settings.SendToGrayLogServers);
|
||||||
|
|
||||||
var tasks = new List<Task>();
|
LogHelper.SendToFile(Logger, Settings, logType, message);
|
||||||
if (sendToSyslogServersValue || sendToSplunkServersValue || sendToGrayLogServersValue)
|
|
||||||
{
|
if (writeToConsoleValue)
|
||||||
if (sendToSyslogServersValue)
|
{
|
||||||
{
|
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
|
||||||
tasks.Add(LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true));
|
}
|
||||||
}
|
|
||||||
|
var tasks = new List<Task>(3);
|
||||||
if (sendToSplunkServersValue)
|
if (sendToSyslogServersValue)
|
||||||
{
|
{
|
||||||
tasks.Add(LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(),
|
tasks.Add(LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true));
|
||||||
messageWithHeader, true));
|
}
|
||||||
}
|
if (sendToSplunkServersValue)
|
||||||
|
{
|
||||||
if (sendToGrayLogServersValue)
|
tasks.Add(LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(),
|
||||||
{
|
messageWithHeader, true));
|
||||||
tasks.Add(LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
|
}
|
||||||
grayLogSource, true, grayLogVersion));
|
if (sendToGrayLogServersValue)
|
||||||
}
|
{
|
||||||
|
tasks.Add(LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
|
||||||
await Task.WhenAll(tasks);
|
grayLogSource, true, grayLogVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
var logMessage = new EonaCatLogMessage
|
if (tasks.Count > 0)
|
||||||
{
|
{
|
||||||
DateTime = dateTime,
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
Message = message,
|
}
|
||||||
LogType = logType,
|
|
||||||
Origin = string.IsNullOrWhiteSpace(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin
|
var logMessage = new EonaCatLogMessage
|
||||||
};
|
{
|
||||||
|
DateTime = dateTime,
|
||||||
Settings.OnLogEvent(logMessage);
|
Message = message,
|
||||||
}
|
LogType = logType,
|
||||||
|
Origin = string.IsNullOrEmpty(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin
|
||||||
public void Reset()
|
};
|
||||||
{
|
Settings.OnLogEvent(logMessage);
|
||||||
Settings.ResetLogEvent();
|
}
|
||||||
}
|
|
||||||
|
private bool IsLogLevelEnabled(ELogType logType)
|
||||||
private void LogHelper_OnException(object sender, ErrorMessage e)
|
{
|
||||||
{
|
if (Settings == null)
|
||||||
OnException?.Invoke(sender, e);
|
{
|
||||||
}
|
OnLogLevelDisabled?.Invoke(this, new ErrorMessage { Message = "Settings is null." });
|
||||||
|
return false;
|
||||||
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
|
}
|
||||||
{
|
|
||||||
if (settings == null)
|
var isEnabled = Settings.MaxLogType != ELogType.NONE && logType <= Settings.MaxLogType;
|
||||||
{
|
if (!isEnabled)
|
||||||
settings = Settings;
|
{
|
||||||
}
|
OnLogLevelDisabled?.Invoke(this, new ErrorMessage { Message = $"Logtype '{logType}' is not enabled, cannot log message" });
|
||||||
|
}
|
||||||
if (!settings.EnableFileLogging)
|
return isEnabled;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
public void Reset()
|
||||||
|
{
|
||||||
if (logFolder != null)
|
Settings.ResetLogEvent();
|
||||||
{
|
}
|
||||||
settings.FileLoggerOptions.LogDirectory = logFolder;
|
|
||||||
}
|
private void LogHelper_OnException(object sender, ErrorMessage e)
|
||||||
|
{
|
||||||
if (string.IsNullOrWhiteSpace(settings.FileLoggerOptions.FileNamePrefix))
|
OnException?.Invoke(sender, e);
|
||||||
{
|
}
|
||||||
settings.FileLoggerOptions.FileNamePrefix = defaultPrefix ? "EonaCat" : string.Empty;
|
|
||||||
}
|
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
|
||||||
}
|
{
|
||||||
|
if (settings == null)
|
||||||
private void SetupLogManager()
|
{
|
||||||
{
|
settings = Settings;
|
||||||
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
}
|
||||||
_logDate = CurrentDateTime;
|
|
||||||
}
|
if (!settings.EnableFileLogging)
|
||||||
|
{
|
||||||
private void ProcessExit(object sender, EventArgs e)
|
return;
|
||||||
{
|
}
|
||||||
Dispose();
|
|
||||||
}
|
if (logFolder != null)
|
||||||
|
{
|
||||||
private Task StopLoggingAsync()
|
settings.FileLoggerOptions.LogDirectory = logFolder;
|
||||||
{
|
}
|
||||||
WriteStopMessage();
|
|
||||||
IsRunning = false;
|
if (string.IsNullOrWhiteSpace(settings.FileLoggerOptions.FileNamePrefix))
|
||||||
return Task.CompletedTask;
|
{
|
||||||
}
|
settings.FileLoggerOptions.FileNamePrefix = defaultPrefix ? "EonaCat" : string.Empty;
|
||||||
|
}
|
||||||
private void WriteStopMessage()
|
}
|
||||||
{
|
|
||||||
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
private void SetupLogManager()
|
||||||
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, stopMessage);
|
{
|
||||||
}
|
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
||||||
|
_logDate = CurrentDateTime;
|
||||||
public void DeleteCurrentLogFile()
|
}
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(CurrentLogFile))
|
private void ProcessExit(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
File.Delete(CurrentLogFile);
|
Dispose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
private Task StopLoggingAsync()
|
||||||
|
{
|
||||||
|
WriteStopMessage();
|
||||||
|
IsRunning = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteStopMessage()
|
||||||
|
{
|
||||||
|
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
||||||
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, stopMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteCurrentLogFile()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(CurrentLogFile))
|
||||||
|
{
|
||||||
|
File.Delete(CurrentLogFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -75,8 +75,10 @@ public class SyslogServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// IP:port of the server.
|
/// IP:port of the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string IpPort => _Hostname + ":" + _Port;
|
public string IpPort => _Hostname + ":" + _Port;
|
||||||
|
|
||||||
|
public bool SupportsTcp { get; set; }
|
||||||
|
|
||||||
private void SetUdp()
|
private void SetUdp()
|
||||||
{
|
{
|
||||||
Udp = null;
|
Udp = null;
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -95,6 +95,7 @@ namespace EonaCat.Logger.Advanced
|
|||||||
// Create and configure a LogManager for logging.
|
// Create and configure a LogManager for logging.
|
||||||
_logManager = new LogManager(new LoggerSettings { RemoveMessagePrefix = true });
|
_logManager = new LogManager(new LoggerSettings { RemoveMessagePrefix = true });
|
||||||
_logManager.OnException += _logManager_OnException;
|
_logManager.OnException += _logManager_OnException;
|
||||||
|
_logManager.OnLogLevelDisabled += _logManager_OnLogLevelDisabled;
|
||||||
_logManager.Settings.FileLoggerOptions.FileNamePrefix = "advanced";
|
_logManager.Settings.FileLoggerOptions.FileNamePrefix = "advanced";
|
||||||
_logManager.Settings.UseLocalTime = true;
|
_logManager.Settings.UseLocalTime = true;
|
||||||
_logManager.Settings.FileLoggerOptions.UseLocalTime = true;
|
_logManager.Settings.FileLoggerOptions.UseLocalTime = true;
|
||||||
@@ -106,6 +107,16 @@ namespace EonaCat.Logger.Advanced
|
|||||||
|
|
||||||
// Event handler for LogManager exceptions, writes messages to the console.
|
// Event handler for LogManager exceptions, writes messages to the console.
|
||||||
private static void _logManager_OnException(object? sender, ErrorMessage e)
|
private static void _logManager_OnException(object? sender, ErrorMessage e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
if (e.Exception != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event handler for LogManager loglevel disabled notifications, writes messages to the console.
|
||||||
|
private static void _logManager_OnLogLevelDisabled(object? sender, ErrorMessage e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e.Message);
|
Console.WriteLine(e.Message);
|
||||||
if (e.Exception != null)
|
if (e.Exception != null)
|
||||||
|
|||||||
Reference in New Issue
Block a user