Files
EonaCat.Logger/EonaCat.Logger/Managers/LogHelper.cs
2024-04-26 06:57:04 +02:00

261 lines
9.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using EonaCat.Json;
using EonaCat.Logger.Extensions;
using EonaCat.Logger.GrayLog;
using EonaCat.Logger.Splunk.Models;
using EonaCat.Logger.Syslog;
using Microsoft.Extensions.Logging;
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
namespace EonaCat.Logger.Managers;
public class ErrorMessage
{
public Exception Exception { get; set; }
public string Message { get; set; }
}
internal static class LogHelper
{
internal static event EventHandler<ErrorMessage> OnException;
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
DateTime dateTime)
{
if (string.IsNullOrWhiteSpace(currentMessage))
return currentMessage;
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
sb.Replace("{ts}",
dateTime.ToString(settings?.TimestampFormat ?? "yyyy-MM-dd HH:mm:ss") + " " +
(settings?.UseLocalTime ?? false ? "[LOCAL]" : "[UTC]"))
.Replace("{host}", $"[Host:{Dns.GetHostName()}]")
.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId}]")
.Replace("{sev}", $"[{logType}]");
if (!settings?.RemoveMessagePrefix ?? (false && !currentMessage.Contains("[EonaCatLogger]")))
sb.Insert(0, "[EonaCatLogger] ");
sb.Append(" ").Append(currentMessage);
return sb.ToString();
}
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole)
{
if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message))
return;
if (settings.EnableColors && settings.Colors != null)
{
var prevForeground = Console.ForegroundColor;
var prevBackground = Console.BackgroundColor;
ConsoleColor foregroundColor;
ConsoleColor backgroundColor;
switch (logType)
{
case ELogType.DEBUG:
foregroundColor = settings.Colors.Debug.Foreground;
backgroundColor = settings.Colors.Debug.Background;
break;
case ELogType.INFO:
foregroundColor = settings.Colors.Info.Foreground;
backgroundColor = settings.Colors.Info.Background;
break;
case ELogType.WARNING:
foregroundColor = settings.Colors.Warning.Foreground;
backgroundColor = settings.Colors.Warning.Background;
break;
case ELogType.ERROR:
foregroundColor = settings.Colors.Error.Foreground;
backgroundColor = settings.Colors.Error.Background;
break;
case ELogType.TRAFFIC:
foregroundColor = settings.Colors.Traffic.Foreground;
backgroundColor = settings.Colors.Traffic.Background;
break;
case ELogType.CRITICAL:
foregroundColor = settings.Colors.Critical.Foreground;
backgroundColor = settings.Colors.Critical.Background;
break;
case ELogType.TRACE:
foregroundColor = settings.Colors.Trace.Foreground;
backgroundColor = settings.Colors.Trace.Background;
break;
default:
return;
}
Console.ForegroundColor = foregroundColor;
Console.BackgroundColor = backgroundColor;
Console.WriteLine(message);
Console.ForegroundColor = prevForeground;
Console.BackgroundColor = prevBackground;
}
else
{
Console.WriteLine(message);
}
}
internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message)
{
if (logger == null || settings == null || !settings.EnableFileLogging ||
string.IsNullOrWhiteSpace(message)) return;
var logLevel = logType.ToLogLevel();
if (IsLogLevelEnabled(settings, logLevel)) Log(logger, logLevel, message);
}
public static bool IsLogLevelEnabled(LoggerSettings settings, LogLevel logLevel)
{
return settings.MinLogType.ToLogLevel() <= logLevel;
}
private static void Log(ILogger logger, LogLevel logLevel, string message)
{
logger.Log(logLevel, message);
}
public static async Task SendToSplunkServersAsync(LoggerSettings settings, SplunkPayload splunkPayload,
bool sendToSplunkServer)
{
if (settings == null || !sendToSplunkServer || splunkPayload == null)
return;
if (settings.SplunkServers == null) settings.SplunkServers = new List<SplunkServer.SplunkServer>();
foreach (var splunkServer in settings.SplunkServers)
{
if (!splunkServer.HasHecUrl || !splunkServer.HasHecToken)
{
OnException?.Invoke(null,
new ErrorMessage
{
Message =
$"Splunk server HecUrl or HecToken not specified, skipping splunkServer '{splunkServer.SplunkHecUrl}'"
});
continue;
}
try
{
var response = await splunkServer.SendAsync(splunkPayload);
if (!response.IsSuccessStatusCode)
OnException?.Invoke(null,
new ErrorMessage
{
Message =
$"Failed to send log to Splunk '{splunkServer.SplunkHecUrl}'. Status code: {response.StatusCode}"
});
}
catch (Exception exception)
{
OnException?.Invoke(null,
new ErrorMessage
{
Exception = exception,
Message =
$"Error while logging to Splunk Server '{splunkServer.SplunkHecUrl}': {exception.Message}"
});
}
}
}
public static async Task SendToSplunkServersAsync(LoggerSettings settings, string logType, string message,
bool sendToSplunkServer)
{
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
return;
var splunkPayload = new SplunkPayload
{
Host = Environment.MachineName,
EventData = message,
SourceType = logType
};
await SendToSplunkServersAsync(settings, splunkPayload, sendToSplunkServer);
}
internal static async Task SendToGrayLogServersAsync(LoggerSettings settings, string message, ELogType logLevel,
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
{
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
return;
foreach (var grayLogServer in settings.GrayLogServers ?? new List<GrayLogServer> { new("127.0.0.1") })
try
{
var gelfMessage = new
{
version,
host = Environment.MachineName,
short_message = message,
level = logLevel.ToGrayLogLevel(),
facility,
source,
timestamp = DateTime.UtcNow.ToUnixTimestamp()
};
var messageBytes = Encoding.UTF8.GetBytes(JsonHelper.ToJson(gelfMessage));
await grayLogServer.Udp.SendAsync(messageBytes, messageBytes.Length);
}
catch (Exception exception)
{
OnException?.Invoke(null,
new ErrorMessage
{
Exception = exception,
Message =
$"Error while logging to GrayLog Server '{grayLogServer.Hostname}': {exception.Message}"
});
}
}
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message,
bool sendToSyslogServers)
{
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
return;
foreach (var server in settings.SysLogServers ?? new List<SyslogServer> { new("127.0.0.1") })
try
{
if (string.IsNullOrWhiteSpace(server.Hostname))
{
OnException?.Invoke(null,
new ErrorMessage { Message = "Server hostname not specified, skipping SysLog Server" });
continue;
}
if (server.Port < 0)
{
OnException?.Invoke(null,
new ErrorMessage { Message = "Server port must be zero or greater, skipping SysLog Server" });
continue;
}
var data = Encoding.UTF8.GetBytes(message);
await server.Udp.SendAsync(data, data.Length);
}
catch (Exception exception)
{
OnException?.Invoke(null,
new ErrorMessage
{
Exception = exception,
Message = $"Error while logging to SysLog Server '{server.Hostname}': {exception.Message}"
});
}
}
}