Updated
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<TargetFrameworks>.netstandard2.1; net6.0; net7.0; net8.0; net4.8;</TargetFrameworks>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<FileVersion>1.3.5</FileVersion>
|
||||
<FileVersion>1.3.6</FileVersion>
|
||||
<Authors>EonaCat (Jeroen Saey)</Authors>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Company>EonaCat (Jeroen Saey)</Company>
|
||||
@@ -24,7 +24,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EVRevisionFormat>1.3.5+{chash:10}.{c:ymd}</EVRevisionFormat>
|
||||
<EVRevisionFormat>1.3.6+{chash:10}.{c:ymd}</EVRevisionFormat>
|
||||
<EVDefault>true</EVDefault>
|
||||
<EVInfo>true</EVInfo>
|
||||
<EVTagMatch>v[0-9]*</EVTagMatch>
|
||||
@@ -52,10 +52,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EonaCat.Json" Version="1.0.5" />
|
||||
<PackageReference Include="EonaCat.Versioning" Version="1.0.11">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive; compile</IncludeAssets>
|
||||
<PackageReference Include="EonaCat.Versioning" Version="1.2.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="EonaCat.Versioning.Helpers" Version="1.0.0" />
|
||||
<PackageReference Include="EonaCat.Versioning.Helpers" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
|
||||
@@ -310,12 +310,6 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
||||
return message;
|
||||
}
|
||||
|
||||
private async Task WriteStopMessage()
|
||||
{
|
||||
var message = LogHelper.GetStopMessage();
|
||||
await WriteMessagesAsync(new List<LogMessage> { CreateLoggerMessage(message, CurrentDateTimeOffset) }, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal string AddMessage(DateTimeOffset timestamp, string message)
|
||||
{
|
||||
var result = CreateLoggerMessage(message, timestamp);
|
||||
|
||||
@@ -8,12 +8,10 @@ namespace EonaCat.Logger.Managers;
|
||||
public interface ILogManager
|
||||
{
|
||||
Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||
string customSplunkSourceType = null, string grayLogFacility = null, string grayLogSource = null,
|
||||
string grayLogVersion = "1.1");
|
||||
|
||||
Task WriteAsync(Exception exception, string module = null, string method = null, bool criticalException = false,
|
||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
|
||||
string grayLogSource = null, string grayLogVersion = "1.1");
|
||||
}
|
||||
@@ -2,14 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
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 EonaCat.Logger.Servers.GrayLog;
|
||||
using EonaCat.Logger.Servers.Splunk.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
@@ -35,7 +33,10 @@ internal static class LogHelper
|
||||
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
|
||||
DateTime dateTime, string category = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(currentMessage)) return currentMessage;
|
||||
if (string.IsNullOrWhiteSpace(currentMessage))
|
||||
{
|
||||
return currentMessage;
|
||||
}
|
||||
|
||||
category ??= "General";
|
||||
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
|
||||
@@ -143,9 +144,9 @@ internal static class LogHelper
|
||||
logger.Log(logLevel, message);
|
||||
}
|
||||
|
||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, SplunkPayload splunkPayload, bool sendToSplunkServer)
|
||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, SplunkPayload splunkPayload)
|
||||
{
|
||||
if (settings == null || !sendToSplunkServer || splunkPayload == null)
|
||||
if (settings == null || splunkPayload == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -174,9 +175,14 @@ internal static class LogHelper
|
||||
/// <summary>
|
||||
/// Overload for sending a simple log message to Splunk.
|
||||
/// </summary>
|
||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, string logType, string message, bool sendToSplunkServer)
|
||||
public static async Task SendToSplunkServersAsync(LoggerSettings settings, string logType, string message)
|
||||
{
|
||||
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
|
||||
if (settings == null || string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.SplunkServers == null || settings.SplunkServers.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -188,7 +194,7 @@ internal static class LogHelper
|
||||
SourceType = logType
|
||||
};
|
||||
|
||||
await SendToSplunkServersAsync(settings, splunkPayload, sendToSplunkServer);
|
||||
await SendToSplunkServersAsync(settings, splunkPayload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -201,9 +207,14 @@ internal static class LogHelper
|
||||
|
||||
|
||||
internal static async Task SendToGrayLogServersAsync(LoggerSettings settings, string message, ELogType logLevel,
|
||||
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
|
||||
string facility, string source, string version = "1.1")
|
||||
{
|
||||
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
|
||||
if (settings == null || string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.GrayLogServers == null || settings.GrayLogServers.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -258,13 +269,12 @@ internal static class LogHelper
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message via TCP to a GrayLog server.
|
||||
/// </summary>
|
||||
private static async Task SendViaTcpAsync(GrayLogServer server, byte[] data)
|
||||
private static async Task SendViaTcpAsync(Graylog server, byte[] data)
|
||||
{
|
||||
using var tcpClient = new TcpClient();
|
||||
using var tcpClient = new System.Net.Sockets.TcpClient();
|
||||
await tcpClient.ConnectAsync(server.Hostname, server.Port);
|
||||
using var stream = tcpClient.GetStream();
|
||||
await stream.WriteAsync(data, 0, data.Length);
|
||||
@@ -274,7 +284,7 @@ internal static class LogHelper
|
||||
/// <summary>
|
||||
/// Sends large messages in chunks over UDP.
|
||||
/// </summary>
|
||||
private static async Task SendUdpInChunksAsync(GrayLogServer server, byte[] data, int chunkSize)
|
||||
private static async Task SendUdpInChunksAsync(Graylog server, byte[] data, int chunkSize)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i += chunkSize)
|
||||
{
|
||||
@@ -283,9 +293,14 @@ internal static class LogHelper
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message, bool sendToSyslogServers)
|
||||
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message)
|
||||
{
|
||||
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
|
||||
if (settings == null || string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.SysLogServers == null || settings.SysLogServers.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -329,12 +344,84 @@ internal static class LogHelper
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
internal static async Task SendToTcpLogServersAsync(LoggerSettings settings, string message)
|
||||
{
|
||||
if (settings == null || string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.TcpServers == null || settings.TcpServers.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tasks = settings.TcpServers?
|
||||
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
|
||||
.Select(async server =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(message);
|
||||
server.DisposeTcp();
|
||||
server.SetTcp();
|
||||
await server.WriteAsync(data).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnException?.Invoke(null, new ErrorMessage
|
||||
{
|
||||
Exception = ex,
|
||||
Message = $"Error logging to Tcp Server '{server.Hostname}': {ex.Message}"
|
||||
});
|
||||
}
|
||||
}) ?? new List<Task>();
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
internal static async Task SendToUdpLogServersAsync(LoggerSettings settings, string message)
|
||||
{
|
||||
if (settings == null || string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.UdpServers == null || settings.UdpServers.Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tasks = settings.UdpServers?
|
||||
.Where(server => !string.IsNullOrWhiteSpace(server.Hostname) && server.Port >= 0)
|
||||
.Select(async server =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(message);
|
||||
server.DisposeUdp();
|
||||
server.SetUdp();
|
||||
await server.WriteAsync(data).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnException?.Invoke(null, new ErrorMessage
|
||||
{
|
||||
Exception = ex,
|
||||
Message = $"Error logging to Udp 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)
|
||||
private static async Task SendViaTcpAsync(Servers.Syslog.Syslog server, byte[] data)
|
||||
{
|
||||
using var tcpClient = new TcpClient();
|
||||
using var tcpClient = new System.Net.Sockets.TcpClient();
|
||||
await tcpClient.ConnectAsync(server.Hostname, server.Port);
|
||||
using var stream = tcpClient.GetStream();
|
||||
await stream.WriteAsync(data, 0, data.Length);
|
||||
@@ -344,7 +431,7 @@ internal static class LogHelper
|
||||
/// <summary>
|
||||
/// Sends large messages in chunks over UDP.
|
||||
/// </summary>
|
||||
private static async Task SendUdpInChunksAsync(SyslogServer server, byte[] data, int chunkSize)
|
||||
private static async Task SendUdpInChunksAsync(Servers.Syslog.Syslog server, byte[] data, int chunkSize)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i += chunkSize)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using EonaCat.Logger.EonaCatCoreLogger;
|
||||
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
|
||||
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
||||
using EonaCat.Logger.Extensions;
|
||||
using EonaCat.Logger.Syslog;
|
||||
using EonaCat.Logger.Servers.GrayLog;
|
||||
using EonaCat.Logger.Servers.Splunk;
|
||||
using EonaCat.Logger.Servers.Syslog;
|
||||
using EonaCat.Logger.Servers.Tcp;
|
||||
using EonaCat.Logger.Servers.Udp;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -24,23 +30,8 @@ namespace EonaCat.Logger.Managers
|
||||
private bool _isDisposing;
|
||||
private string _category;
|
||||
|
||||
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
||||
public LogManager(LoggerSettings settings)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serverIp))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serverIp));
|
||||
}
|
||||
|
||||
if (serverPort < 0)
|
||||
{
|
||||
throw new ArgumentException("Server port must be zero or greater.");
|
||||
}
|
||||
|
||||
settings.SysLogServers = new List<SyslogServer>
|
||||
{
|
||||
new(serverIp, serverPort)
|
||||
};
|
||||
|
||||
Settings = settings;
|
||||
SetupLogManager();
|
||||
}
|
||||
@@ -87,8 +78,7 @@ namespace EonaCat.Logger.Managers
|
||||
|
||||
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
||||
bool criticalException = false,
|
||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
|
||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||
{
|
||||
if (exception == null)
|
||||
@@ -97,14 +87,14 @@ namespace EonaCat.Logger.Managers
|
||||
}
|
||||
|
||||
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
||||
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
||||
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
||||
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole,
|
||||
customSplunkSourceType, grayLogFacility, grayLogSource,
|
||||
grayLogVersion);
|
||||
}
|
||||
|
||||
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||
string customSplunkSourceType = null,
|
||||
string grayLogFacility = null, string grayLogSource = null,
|
||||
string grayLogVersion = "1.1")
|
||||
{
|
||||
if (logType == ELogType.NONE)
|
||||
@@ -112,8 +102,8 @@ namespace EonaCat.Logger.Managers
|
||||
return;
|
||||
}
|
||||
|
||||
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
||||
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
|
||||
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole,
|
||||
customSplunkSourceType, grayLogFacility, grayLogSource, grayLogVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -202,8 +192,7 @@ namespace EonaCat.Logger.Managers
|
||||
}
|
||||
|
||||
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,
|
||||
bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
|
||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message) || logType == ELogType.NONE || !IsLogLevelEnabled(logType) || _isDisposing)
|
||||
@@ -218,9 +207,6 @@ namespace EonaCat.Logger.Managers
|
||||
|
||||
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
|
||||
var writeToConsoleValue = writeToConsole.GetValueOrDefault(Settings.EnableConsole);
|
||||
var sendToSyslogServersValue = sendToSyslogServers.GetValueOrDefault(Settings.SendToSyslogServers);
|
||||
var sendToSplunkServersValue = sendToSplunkServers.GetValueOrDefault(Settings.SendToSplunkServers);
|
||||
var sendToGrayLogServersValue = sendToGrayLogServers.GetValueOrDefault(Settings.SendToGrayLogServers);
|
||||
|
||||
LogHelper.SendToFile(Logger, Settings, logType, message);
|
||||
|
||||
@@ -229,21 +215,14 @@ namespace EonaCat.Logger.Managers
|
||||
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
|
||||
}
|
||||
|
||||
var tasks = new List<Task>(3);
|
||||
if (sendToSyslogServersValue)
|
||||
var tasks = new List<Task>(5)
|
||||
{
|
||||
tasks.Add(LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true));
|
||||
}
|
||||
if (sendToSplunkServersValue)
|
||||
{
|
||||
tasks.Add(LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(),
|
||||
messageWithHeader, true));
|
||||
}
|
||||
if (sendToGrayLogServersValue)
|
||||
{
|
||||
tasks.Add(LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
|
||||
grayLogSource, true, grayLogVersion));
|
||||
}
|
||||
LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader),
|
||||
LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(), messageWithHeader),
|
||||
LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility, grayLogSource, grayLogVersion),
|
||||
LogHelper.SendToTcpLogServersAsync(Settings, messageWithHeader),
|
||||
LogHelper.SendToUdpLogServersAsync(Settings, messageWithHeader),
|
||||
};
|
||||
|
||||
if (tasks.Count > 0)
|
||||
{
|
||||
@@ -340,5 +319,326 @@ namespace EonaCat.Logger.Managers
|
||||
File.Delete(CurrentLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add sysLog server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddSyslogServer(string address, int port, string nickName = null)
|
||||
{
|
||||
if (Settings.SysLogServers == null)
|
||||
{
|
||||
Settings.SysLogServers = new List<Servers.Syslog.Syslog>();
|
||||
}
|
||||
|
||||
if (Settings.SysLogServers.Any(x => (nickName != null && x.Nickname == nickName) || nickName == null && x.Hostname == address && x.Port == port))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings.SysLogServers.Add(new Syslog(address, port));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the sysLog server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveSyslogServer(string address, int port)
|
||||
{
|
||||
if (Settings.SysLogServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.SysLogServers.FirstOrDefault(x => x.Hostname == address && x.Port == port);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.SysLogServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the sysLog server
|
||||
/// </summary>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveSyslogServer(string nickName)
|
||||
{
|
||||
if (Settings.SysLogServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.SysLogServers.FirstOrDefault(x => x.Nickname == nickName);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.SysLogServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Splunk server
|
||||
/// </summary>
|
||||
/// <param name="splunkHecUrl"></param>
|
||||
/// <param name="splunkHecToken"></param>
|
||||
/// <param name="httpClientHandler">(optional)</param>
|
||||
/// <param name="nickName">(optional)</param>
|
||||
/// <returns></returns>
|
||||
public bool AddSplunkServer(string splunkHecUrl, string splunkHecToken, HttpClientHandler httpClientHandler = null, string nickName = null)
|
||||
{
|
||||
if (Settings.SplunkServers == null)
|
||||
{
|
||||
Settings.SplunkServers = new List<Logger.Servers.Splunk.Splunk>();
|
||||
}
|
||||
|
||||
if (Settings.SplunkServers.Any(x => (nickName != null && x.Nickname == nickName) || nickName == null && x.SplunkHecUrl == splunkHecUrl && x.SplunkHecToken == splunkHecToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings.SplunkServers.Add(new Splunk(splunkHecUrl, splunkHecToken, httpClientHandler, nickName));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Splunk server
|
||||
/// </summary>
|
||||
/// <param name="splunkHecUrl"></param>
|
||||
/// <param name="splunkHecToken"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveSplunkServer(string splunkHecUrl, string splunkHecToken)
|
||||
{
|
||||
if (Settings.SplunkServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.SplunkServers.FirstOrDefault(x => x.SplunkHecUrl == splunkHecUrl && x.SplunkHecToken == splunkHecToken);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.SplunkServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Splunk server
|
||||
/// </summary>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveSplunkServer(string nickName)
|
||||
{
|
||||
if (Settings.SplunkServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.SplunkServers.FirstOrDefault(x => x.Nickname == nickName);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.SplunkServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add GrayLog server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddGrayLogServer(string address, int port, string nickName = null)
|
||||
{
|
||||
if (Settings.GrayLogServers == null)
|
||||
{
|
||||
Settings.GrayLogServers = new List<Graylog>();
|
||||
}
|
||||
|
||||
if (Settings.GrayLogServers.Any(x => (nickName != null && x.Nickname == nickName) || nickName == null && x.Hostname == address && x.Port == port))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings.GrayLogServers.Add(new Graylog(address, port));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the GrayLog server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveGrayLogServer(string address, int port)
|
||||
{
|
||||
if (Settings.GrayLogServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.GrayLogServers.FirstOrDefault(x => x.Hostname == address && x.Port == port);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.GrayLogServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the GrayLog server
|
||||
/// </summary>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveGrayLogServer(string nickName)
|
||||
{
|
||||
if (Settings.GrayLogServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.GrayLogServers.FirstOrDefault(x => x.Nickname == nickName);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.GrayLogServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Tcp server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddTcpLogServer(string address, int port, string nickName = null)
|
||||
{
|
||||
if (Settings.TcpServers == null)
|
||||
{
|
||||
Settings.TcpServers = new List<Servers.Tcp.Tcp>();
|
||||
}
|
||||
|
||||
if (Settings.TcpServers.Any(x => (nickName != null && x.Nickname == nickName) || (nickName == null && x.Hostname == address && x.Port == port)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings.TcpServers.Add(new Tcp(address, port));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Tcp server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveTcpLogServer(string address, int port)
|
||||
{
|
||||
if (Settings.TcpServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.TcpServers.FirstOrDefault(x => x.Hostname == address && x.Port == port);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.TcpServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Tcp server
|
||||
/// </summary>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveTcpLogServer(string nickName)
|
||||
{
|
||||
if (Settings.TcpServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.TcpServers.FirstOrDefault(x => x.Nickname == nickName);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.TcpServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Udp server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddUdpLogServer(string address, int port, string nickName = null)
|
||||
{
|
||||
if (Settings.UdpServers == null)
|
||||
{
|
||||
Settings.UdpServers = new List<Servers.Udp.Udp>();
|
||||
}
|
||||
|
||||
if (Settings.UdpServers.Any(x => (nickName != null && x.Nickname == nickName) || nickName == null && x.Hostname == address && x.Port == port))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Settings.UdpServers.Add(new Udp(address, port));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Udp server
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveUdpLogServer(string address, int port)
|
||||
{
|
||||
if (Settings.UdpServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.UdpServers.FirstOrDefault(x => x.Hostname == address && x.Port == port);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.UdpServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the Udp server
|
||||
/// </summary>
|
||||
/// <param name="nickName"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveUdpLogServer(string nickName)
|
||||
{
|
||||
if (Settings.UdpServers == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var delete = Settings.UdpServers.FirstOrDefault(x => x.Nickname == nickName);
|
||||
if (delete != null)
|
||||
{
|
||||
Settings.UdpServers.Remove(delete);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.RegularExpressions;
|
||||
using EonaCat.Logger.EonaCatCoreLogger;
|
||||
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
||||
using EonaCat.Logger.GrayLog;
|
||||
using EonaCat.Logger.Syslog;
|
||||
using EonaCat.Logger.Servers.GrayLog;
|
||||
|
||||
namespace EonaCat.Logger.Managers;
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
@@ -127,18 +127,13 @@ public class LoggerSettings
|
||||
}
|
||||
|
||||
public ELogType MaxLogType { get; set; } = ELogType.INFO;
|
||||
public List<Servers.Syslog.Syslog> SysLogServers { get; internal set; }
|
||||
public List<Logger.Servers.Splunk.Splunk> SplunkServers { get; internal set; }
|
||||
|
||||
public bool SendToSyslogServers { get; set; }
|
||||
public List<Graylog> GrayLogServers { get; internal set; }
|
||||
public List<Servers.Tcp.Tcp> TcpServers { get; internal set; }
|
||||
|
||||
public List<SyslogServer> SysLogServers { get; set; }
|
||||
|
||||
public bool SendToSplunkServers { get; set; }
|
||||
|
||||
public bool SendToGrayLogServers { get; set; }
|
||||
|
||||
public List<SplunkServer.SplunkServer> SplunkServers { get; set; }
|
||||
|
||||
public List<GrayLogServer> GrayLogServers { get; set; }
|
||||
public List<Servers.Udp.Udp> UdpServers { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the fileLogging is enabled
|
||||
|
||||
@@ -1,87 +1,84 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace EonaCat.Logger.GrayLog;
|
||||
namespace EonaCat.Logger.Servers.GrayLog;
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
|
||||
/// <summary>
|
||||
/// Syslog server.
|
||||
/// GrayLog client
|
||||
/// </summary>
|
||||
public class GrayLogServer
|
||||
public class Graylog : IDisposable
|
||||
{
|
||||
internal readonly object SendLock = new();
|
||||
private string _Hostname = "127.0.0.1";
|
||||
private int _Port = 12201;
|
||||
internal UdpClient Udp;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the object.
|
||||
/// </summary>
|
||||
public GrayLogServer()
|
||||
public bool SupportsTcp { get; set; }
|
||||
public string Nickname { get; set; }
|
||||
public string IpPort => _Hostname + ":" + _Port;
|
||||
|
||||
public Graylog() { }
|
||||
|
||||
public Graylog(string hostname = "127.0.0.1", int port = 12201, string nickName = null)
|
||||
{
|
||||
_Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
|
||||
_Port = port >= 0 ? port : throw new ArgumentException("Port must be zero or greater.");
|
||||
|
||||
Nickname = nickName ?? IpPort;
|
||||
SetUdp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the object.
|
||||
/// </summary>
|
||||
/// <param name="hostname">Hostname.</param>
|
||||
/// <param name="port">Port.</param>
|
||||
public GrayLogServer(string hostname = "127.0.0.1", int port = 12201)
|
||||
{
|
||||
Hostname = hostname;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hostname.
|
||||
/// </summary>
|
||||
public string Hostname
|
||||
{
|
||||
get => _Hostname;
|
||||
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Hostname));
|
||||
}
|
||||
|
||||
_Hostname = value;
|
||||
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UDP port.
|
||||
/// </summary>
|
||||
public int Port
|
||||
{
|
||||
get => _Port;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentException("Port must be zero or greater.");
|
||||
}
|
||||
|
||||
_Port = value;
|
||||
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IP:port of the server.
|
||||
/// </summary>
|
||||
public string IpPort => _Hostname + ":" + _Port;
|
||||
|
||||
public bool SupportsTcp { get; set; }
|
||||
|
||||
private void SetUdp()
|
||||
{
|
||||
Udp = null;
|
||||
DisposeUdp();
|
||||
Udp = new UdpClient(_Hostname, _Port);
|
||||
}
|
||||
|
||||
private void DisposeUdp()
|
||||
{
|
||||
if (Udp != null)
|
||||
{
|
||||
Udp.Dispose();
|
||||
Udp = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeUdp();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Graylog()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace EonaCat.Logger.Splunk.Models;
|
||||
namespace EonaCat.Logger.Servers.Splunk.Models;
|
||||
|
||||
public class SplunkPayload
|
||||
{
|
||||
130
EonaCat.Logger/Servers/Splunk/Splunk.cs
Normal file
130
EonaCat.Logger/Servers/Splunk/Splunk.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EonaCat.Json;
|
||||
|
||||
namespace EonaCat.Logger.Servers.Splunk;
|
||||
|
||||
using EonaCat.Logger.Servers.Splunk.Models;
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
|
||||
/// <summary>
|
||||
/// Splunk Server.
|
||||
/// </summary>
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class Splunk : IDisposable
|
||||
{
|
||||
internal readonly object SendLock = new();
|
||||
private string _splunkHecUrl = "https://127.0.0.1:8088/services/collector/event";
|
||||
|
||||
public string SplunkHecToken { get; set; } = "splunk-hec-token";
|
||||
public HttpClientHandler SplunkClientHandler { get; private set; }
|
||||
public HttpClient HttpClient { get; private set; }
|
||||
public string Nickname { get; set; }
|
||||
|
||||
public bool HasHecToken => !string.IsNullOrWhiteSpace(SplunkHecToken) && SplunkHecToken != "splunk-hec-token";
|
||||
public bool HasHecUrl => !string.IsNullOrWhiteSpace(SplunkHecUrl);
|
||||
public bool IsHttpsHecUrl => HasHecUrl && _splunkHecUrl.ToLower().StartsWith("https");
|
||||
public bool IsLocalHost => HasHecUrl && (_splunkHecUrl.ToLower().Contains("127.0.0.1") || _splunkHecUrl.ToLower().Contains("localhost"));
|
||||
|
||||
public Splunk(string splunkHecUrl, string splunkHecToken, HttpClientHandler httpClientHandler = null, string nickName = null)
|
||||
{
|
||||
SplunkHecUrl = splunkHecUrl ?? throw new ArgumentNullException(nameof(splunkHecUrl));
|
||||
SplunkHecToken = splunkHecToken ?? throw new ArgumentNullException(nameof(splunkHecToken));
|
||||
|
||||
Nickname = nickName ?? $"{splunkHecUrl}_{splunkHecToken}";
|
||||
SplunkClientHandler = httpClientHandler ?? new HttpClientHandler();
|
||||
|
||||
CreateHttpClient();
|
||||
}
|
||||
|
||||
public string SplunkHecUrl
|
||||
{
|
||||
get => _splunkHecUrl;
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value) && !value.ToLower().Contains("http"))
|
||||
{
|
||||
value = $"http://{value}";
|
||||
}
|
||||
|
||||
_splunkHecUrl = value;
|
||||
CreateHttpClient();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateHttpClient()
|
||||
{
|
||||
DisposeHttpClient();
|
||||
|
||||
SplunkClientHandler ??= new HttpClientHandler();
|
||||
HttpClient = new HttpClient(SplunkClientHandler)
|
||||
{
|
||||
BaseAddress = new Uri(SplunkHecUrl)
|
||||
};
|
||||
|
||||
HttpClient.DefaultRequestHeaders.Add("Authorization", $"Splunk {SplunkHecToken}");
|
||||
}
|
||||
|
||||
public void DisableSSLValidation()
|
||||
{
|
||||
DisposeHttpClient();
|
||||
|
||||
SplunkClientHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
|
||||
};
|
||||
|
||||
CreateHttpClient();
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> SendAsync(SplunkPayload splunkPayload)
|
||||
{
|
||||
if (splunkPayload == null) return null;
|
||||
|
||||
var eventObject = new
|
||||
{
|
||||
@event = splunkPayload.EventData,
|
||||
sourcetype = splunkPayload.SourceType,
|
||||
host = splunkPayload.Host
|
||||
};
|
||||
|
||||
var eventJson = JsonHelper.ToJson(eventObject);
|
||||
if (!HasHecToken) CreateHttpClient();
|
||||
|
||||
using var content = new StringContent(eventJson, Encoding.UTF8, "application/json");
|
||||
return await HttpClient.PostAsync("/services/collector/event", content);
|
||||
}
|
||||
|
||||
private void DisposeHttpClient()
|
||||
{
|
||||
if (HttpClient != null)
|
||||
{
|
||||
HttpClient.Dispose();
|
||||
HttpClient = null;
|
||||
}
|
||||
|
||||
if (SplunkClientHandler != null)
|
||||
{
|
||||
SplunkClientHandler.Dispose();
|
||||
SplunkClientHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeHttpClient();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Splunk()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,87 +1,82 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace EonaCat.Logger.Syslog;
|
||||
namespace EonaCat.Logger.Servers.Syslog;
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
|
||||
/// <summary>
|
||||
/// Syslog server.
|
||||
/// </summary>
|
||||
public class SyslogServer
|
||||
public class Syslog : IDisposable
|
||||
{
|
||||
private string _Hostname = "127.0.0.1";
|
||||
private int _Port = 514;
|
||||
|
||||
internal UdpClient Udp;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the object.
|
||||
/// </summary>
|
||||
public SyslogServer()
|
||||
{
|
||||
}
|
||||
public Syslog() { }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the object.
|
||||
/// </summary>
|
||||
/// <param name="hostname">Hostname.</param>
|
||||
/// <param name="port">Port.</param>
|
||||
public SyslogServer(string hostname = "127.0.0.1", int port = 514)
|
||||
public Syslog(string hostname = "127.0.0.1", int port = 514, string nickName = null)
|
||||
{
|
||||
Hostname = hostname;
|
||||
Port = port;
|
||||
Nickname = nickName ?? IpPort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hostname.
|
||||
/// </summary>
|
||||
public string Hostname
|
||||
{
|
||||
get => _Hostname;
|
||||
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Hostname));
|
||||
}
|
||||
|
||||
_Hostname = value;
|
||||
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UDP port.
|
||||
/// </summary>
|
||||
public int Port
|
||||
{
|
||||
get => _Port;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentException("Port must be zero or greater.");
|
||||
}
|
||||
|
||||
_Port = value;
|
||||
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IP:port of the server.
|
||||
/// </summary>
|
||||
public string IpPort => _Hostname + ":" + _Port;
|
||||
|
||||
public bool SupportsTcp { get; set; }
|
||||
public string Nickname { get; set; }
|
||||
|
||||
private void SetUdp()
|
||||
{
|
||||
Udp = null;
|
||||
DisposeUdp();
|
||||
Udp = new UdpClient(_Hostname, _Port);
|
||||
}
|
||||
|
||||
private void DisposeUdp()
|
||||
{
|
||||
if (Udp != null)
|
||||
{
|
||||
Udp.Dispose();
|
||||
Udp = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeUdp();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Syslog()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
115
EonaCat.Logger/Servers/Tcp/Tcp.cs
Normal file
115
EonaCat.Logger/Servers/Tcp/Tcp.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace EonaCat.Logger.Servers.Tcp
|
||||
{
|
||||
// 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 class Tcp : IDisposable
|
||||
{
|
||||
private string _Hostname = "127.0.0.1";
|
||||
private int _Port = 514;
|
||||
internal TcpClient _tcp;
|
||||
|
||||
public string Nickname { get; set; }
|
||||
public string IpPort => _Hostname + ":" + _Port;
|
||||
|
||||
public Tcp(string hostname, int port, string nickname = null)
|
||||
{
|
||||
_Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
|
||||
_Port = port >= 0 ? port : throw new ArgumentException("Port must be zero or greater.");
|
||||
|
||||
Nickname = nickname ?? IpPort;
|
||||
SetTcp();
|
||||
}
|
||||
|
||||
public string Hostname
|
||||
{
|
||||
get => _Hostname;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
throw new ArgumentNullException(nameof(Hostname));
|
||||
|
||||
_Hostname = value;
|
||||
SetTcp();
|
||||
}
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get => _Port;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentException("Port must be zero or greater.");
|
||||
|
||||
_Port = value;
|
||||
SetTcp();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetTcp()
|
||||
{
|
||||
DisposeTcp();
|
||||
_tcp = new TcpClient(_Hostname, _Port);
|
||||
}
|
||||
|
||||
internal void DisposeTcp()
|
||||
{
|
||||
if (_tcp != null)
|
||||
{
|
||||
_tcp.Close();
|
||||
_tcp.Dispose();
|
||||
_tcp = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeTcp();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
internal async Task WriteAsync(byte[] data)
|
||||
{
|
||||
if (_tcp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var stream = _tcp.GetStream();
|
||||
await stream.WriteAsync(data, 0, data.Length);
|
||||
await stream.FlushAsync();
|
||||
}
|
||||
|
||||
internal async Task WriteAsync(string data)
|
||||
{
|
||||
if (_tcp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var sendData = Encoding.UTF8.GetBytes(data);
|
||||
using var stream = _tcp.GetStream();
|
||||
await stream.WriteAsync(sendData, 0, sendData.Length);
|
||||
await stream.FlushAsync();
|
||||
}
|
||||
|
||||
~Tcp()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
127
EonaCat.Logger/Servers/Udp/Udp.cs
Normal file
127
EonaCat.Logger/Servers/Udp/Udp.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace EonaCat.Logger.Servers.Udp
|
||||
{
|
||||
// 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 class Udp : IDisposable
|
||||
{
|
||||
const int MaxUdpPacketSize = 4096;
|
||||
private string _Hostname = "127.0.0.1";
|
||||
private int _Port = 514;
|
||||
internal UdpClient _udp;
|
||||
|
||||
public string Nickname { get; set; }
|
||||
public string IpPort => _Hostname + ":" + _Port;
|
||||
|
||||
public Udp(string hostname, int port, string nickname = null)
|
||||
{
|
||||
_Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
|
||||
_Port = port >= 0 ? port : throw new ArgumentException("Port must be zero or greater.");
|
||||
|
||||
Nickname = nickname ?? IpPort;
|
||||
SetUdp();
|
||||
}
|
||||
|
||||
public string Hostname
|
||||
{
|
||||
get => _Hostname;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
throw new ArgumentNullException(nameof(Hostname));
|
||||
|
||||
_Hostname = value;
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get => _Port;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentException("Port must be zero or greater.");
|
||||
|
||||
_Port = value;
|
||||
SetUdp();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetUdp()
|
||||
{
|
||||
DisposeUdp();
|
||||
_udp = new UdpClient(_Hostname, _Port);
|
||||
}
|
||||
|
||||
internal void DisposeUdp()
|
||||
{
|
||||
if (_udp != null)
|
||||
{
|
||||
_udp.Dispose();
|
||||
_udp = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeUdp();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
internal async Task WriteAsync(byte[] data, bool dontFragment = false)
|
||||
{
|
||||
if (_udp == null || data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_udp.DontFragment = dontFragment;
|
||||
|
||||
int maxChunkSize = MaxUdpPacketSize;
|
||||
int offset = 0;
|
||||
|
||||
while (offset < data.Length)
|
||||
{
|
||||
int chunkSize = Math.Min(maxChunkSize, data.Length - offset);
|
||||
byte[] chunk = new byte[chunkSize];
|
||||
Array.Copy(data, offset, chunk, 0, chunkSize);
|
||||
|
||||
await _udp.SendAsync(chunk, chunk.Length);
|
||||
offset += chunkSize;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task WriteAsync(string data, bool dontFragment = false)
|
||||
{
|
||||
if (_udp == null || string.IsNullOrEmpty(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var sendData = Encoding.UTF8.GetBytes(data);
|
||||
_udp.DontFragment = dontFragment;
|
||||
|
||||
int maxChunkSize = MaxUdpPacketSize;
|
||||
int offset = 0;
|
||||
|
||||
while (offset < sendData.Length)
|
||||
{
|
||||
int chunkSize = Math.Min(maxChunkSize, sendData.Length - offset);
|
||||
byte[] chunk = new byte[chunkSize];
|
||||
Array.Copy(sendData, offset, chunk, 0, chunkSize);
|
||||
|
||||
await _udp.SendAsync(chunk, chunk.Length);
|
||||
offset += chunkSize;
|
||||
}
|
||||
}
|
||||
|
||||
~Udp()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace EonaCat.Logger.Zabbix.API;
|
||||
namespace EonaCat.Logger.Servers.Zabbix.API;
|
||||
// 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace EonaCat.Logger.Zabbix.API
|
||||
namespace EonaCat.Logger.Servers.Zabbix.API
|
||||
{
|
||||
// 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.
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Dynamic;
|
||||
|
||||
namespace EonaCat.Logger.Zabbix.API
|
||||
namespace EonaCat.Logger.Servers.Zabbix.API
|
||||
{
|
||||
// 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.
|
||||
22
EonaCat.Logger/Servers/Zabbix/ZabbixData.cs
Normal file
22
EonaCat.Logger/Servers/Zabbix/ZabbixData.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
namespace EonaCat.Logger.Servers.Zabbix
|
||||
{
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
/// <summary>
|
||||
/// Zabbix server.
|
||||
/// </summary>
|
||||
public class ZabbixData
|
||||
{
|
||||
public string Host { get; set; }
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public ZabbixData(string host, string key, string value)
|
||||
{
|
||||
Host = host;
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
EonaCat.Logger/Servers/Zabbix/ZabbixRequest.cs
Normal file
79
EonaCat.Logger/Servers/Zabbix/ZabbixRequest.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using EonaCat.Json;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EonaCat.Logger.Servers.Zabbix
|
||||
{
|
||||
// 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 class ZabbixRequest
|
||||
{
|
||||
private const int BUFFER_SIZE = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// The request to send to the Zabbix server
|
||||
/// </summary>
|
||||
public string Request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data to send to the Zabbix server
|
||||
/// </summary>
|
||||
public ZabbixData[] Data { get; set; }
|
||||
|
||||
public ZabbixRequest(string host, string key, string value)
|
||||
{
|
||||
Request = "sender data";
|
||||
Data = [new ZabbixData(host, key, value)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the request to the Zabbix server
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="TimeoutException"></exception>
|
||||
public async Task<ZabbixResponse> SendAsync(string server, int port = 10051, int timeout = 500)
|
||||
{
|
||||
string json = JsonHelper.ToJson(new ZabbixRequest(Data[0].Host, Data[0].Key, Data[0].Value));
|
||||
using (TcpClient tcpClient = new TcpClient(server, port))
|
||||
using (NetworkStream stream = tcpClient.GetStream())
|
||||
{
|
||||
byte[] header = Encoding.ASCII.GetBytes("ZBXD\x01");
|
||||
byte[] dataLength = BitConverter.GetBytes((long)json.Length);
|
||||
byte[] content = Encoding.ASCII.GetBytes(json);
|
||||
byte[] message = new byte[header.Length + dataLength.Length + content.Length];
|
||||
|
||||
Buffer.BlockCopy(header, 0, message, 0, header.Length);
|
||||
Buffer.BlockCopy(dataLength, 0, message, header.Length, dataLength.Length);
|
||||
Buffer.BlockCopy(content, 0, message, header.Length + dataLength.Length, content.Length);
|
||||
|
||||
stream.Write(message, 0, message.Length);
|
||||
stream.Flush();
|
||||
|
||||
int counter = 0;
|
||||
while (!stream.DataAvailable)
|
||||
{
|
||||
if (counter < timeout / 50)
|
||||
{
|
||||
counter++;
|
||||
await Task.Delay(50).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
byte[] responseBytes = new byte[BUFFER_SIZE];
|
||||
stream.Read(responseBytes, 0, responseBytes.Length);
|
||||
string responseAsString = Encoding.UTF8.GetString(responseBytes);
|
||||
string jsonResult = responseAsString.Substring(responseAsString.IndexOf('{'));
|
||||
return JsonHelper.ToObject<ZabbixResponse>(jsonResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
EonaCat.Logger/Servers/Zabbix/ZabbixResponse.cs
Normal file
11
EonaCat.Logger/Servers/Zabbix/ZabbixResponse.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace EonaCat.Logger.Servers.Zabbix
|
||||
{
|
||||
// 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 class ZabbixResponse
|
||||
{
|
||||
public string Response { get; set; }
|
||||
public string Info { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EonaCat.Json;
|
||||
using EonaCat.Logger.Splunk.Models;
|
||||
|
||||
namespace EonaCat.Logger.SplunkServer;
|
||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||
|
||||
/// <summary>
|
||||
/// Splunk Server.
|
||||
/// </summary>
|
||||
public class SplunkServer
|
||||
{
|
||||
internal readonly object SendLock = new();
|
||||
private string _splunkHecUrl = "https://127.0.0.1:8088/services/collector/event";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate the object.
|
||||
/// </summary>
|
||||
/// <param name="splunkHecUrl">splunkHecUrl.</param>
|
||||
/// <param name="splunkHecToken">splunkHecToken.</param>
|
||||
/// <param name="httpClientHandler">httpClientHandler. (optional)</param>
|
||||
public SplunkServer(string splunkHecUrl, string splunkHecToken, HttpClientHandler httpClientHandler = null)
|
||||
{
|
||||
SplunkHecUrl = splunkHecUrl;
|
||||
SplunkHecToken = splunkHecToken;
|
||||
|
||||
if (httpClientHandler == null)
|
||||
{
|
||||
httpClientHandler = new HttpClientHandler();
|
||||
}
|
||||
|
||||
SplunkClientHandler = httpClientHandler;
|
||||
CreateHttpClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SplunkHecUrl
|
||||
/// </summary>
|
||||
public string SplunkHecUrl
|
||||
{
|
||||
get => _splunkHecUrl;
|
||||
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_splunkHecUrl) && !_splunkHecUrl.ToLower().Contains("http"))
|
||||
{
|
||||
value = $"http://{value}";
|
||||
}
|
||||
|
||||
_splunkHecUrl = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHttpsHecUrl => HasHecUrl && _splunkHecUrl.ToLower().StartsWith("https");
|
||||
|
||||
/// <summary>
|
||||
/// SplunkHecToken
|
||||
/// </summary>
|
||||
public string SplunkHecToken { get; set; } = "splunk-hec-token";
|
||||
|
||||
public HttpClientHandler SplunkClientHandler { get; internal set; }
|
||||
public HttpClient HttpClient { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a HEC token is available
|
||||
/// </summary>
|
||||
public bool HasHecToken => !string.IsNullOrWhiteSpace(SplunkHecToken) && SplunkHecToken != "splunk-hec-token";
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a HEC url is available
|
||||
/// </summary>
|
||||
public bool HasHecUrl => !string.IsNullOrWhiteSpace(SplunkHecUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the splunk URL is local
|
||||
/// </summary>
|
||||
public bool IsLocalHost => HasHecUrl &&
|
||||
(SplunkHecUrl.ToLower().Contains("127.0.0.1") ||
|
||||
SplunkHecUrl.ToLower().Contains("localhost"));
|
||||
|
||||
private void CreateHttpClient()
|
||||
{
|
||||
HttpClient = new HttpClient(SplunkClientHandler);
|
||||
HttpClient.BaseAddress = new Uri(SplunkHecUrl);
|
||||
|
||||
// Add the HEC token to the request headers for authorization
|
||||
HttpClient.DefaultRequestHeaders.Add("Authorization", $"Splunk {SplunkHecToken}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables SSL validation (can be used for insecure https urls)
|
||||
/// <note>This overwrites your own httpClientHandler</note>
|
||||
/// </summary>
|
||||
public void DisableSSLValidation()
|
||||
{
|
||||
var clientHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
|
||||
};
|
||||
|
||||
SplunkClientHandler = clientHandler;
|
||||
CreateHttpClient();
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> SendAsync(SplunkPayload splunkPayload)
|
||||
{
|
||||
if (splunkPayload == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create an event object with the required fields
|
||||
var eventObject = new
|
||||
{
|
||||
@event = splunkPayload.EventData,
|
||||
sourcetype = splunkPayload.SourceType,
|
||||
host = splunkPayload.Host
|
||||
};
|
||||
|
||||
// Serialize the event object to JSON
|
||||
var eventJson = JsonHelper.ToJson(eventObject);
|
||||
|
||||
if (!HasHecToken)
|
||||
{
|
||||
CreateHttpClient();
|
||||
}
|
||||
|
||||
// Create an HTTP content with the event data
|
||||
var content = new StringContent(eventJson, Encoding.UTF8, "application/json");
|
||||
|
||||
// Send the event to Splunk
|
||||
var response = await HttpClient.PostAsync("/services/collector/event", content);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
/// <summary>
|
||||
/// Zabbix server.
|
||||
/// </summary>
|
||||
public class ZabbixData
|
||||
{
|
||||
public string Host { get; set; }
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public ZabbixData(string host, string key, string value)
|
||||
{
|
||||
Host = host;
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using EonaCat.Json;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class ZabbixRequest
|
||||
{
|
||||
private const int BUFFER_SIZE = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// The request to send to the Zabbix server
|
||||
/// </summary>
|
||||
public string Request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data to send to the Zabbix server
|
||||
/// </summary>
|
||||
public ZabbixData[] Data { get; set; }
|
||||
|
||||
public ZabbixRequest(string host, string key, string value)
|
||||
{
|
||||
Request = "sender data";
|
||||
Data = [new ZabbixData(host, key, value)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the request to the Zabbix server
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="TimeoutException"></exception>
|
||||
public async Task<ZabbixResponse> SendAsync(string server, int port = 10051, int timeout = 500)
|
||||
{
|
||||
string json = JsonHelper.ToJson(new ZabbixRequest(Data[0].Host, Data[0].Key, Data[0].Value));
|
||||
using (TcpClient tcpClient = new TcpClient(server, port))
|
||||
using (NetworkStream stream = tcpClient.GetStream())
|
||||
{
|
||||
byte[] header = Encoding.ASCII.GetBytes("ZBXD\x01");
|
||||
byte[] dataLength = BitConverter.GetBytes((long)json.Length);
|
||||
byte[] content = Encoding.ASCII.GetBytes(json);
|
||||
byte[] message = new byte[header.Length + dataLength.Length + content.Length];
|
||||
|
||||
Buffer.BlockCopy(header, 0, message, 0, header.Length);
|
||||
Buffer.BlockCopy(dataLength, 0, message, header.Length, dataLength.Length);
|
||||
Buffer.BlockCopy(content, 0, message, header.Length + dataLength.Length, content.Length);
|
||||
|
||||
stream.Write(message, 0, message.Length);
|
||||
stream.Flush();
|
||||
|
||||
int counter = 0;
|
||||
while (!stream.DataAvailable)
|
||||
{
|
||||
if (counter < timeout / 50)
|
||||
{
|
||||
counter++;
|
||||
await Task.Delay(50).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
byte[] responseBytes = new byte[BUFFER_SIZE];
|
||||
stream.Read(responseBytes, 0, responseBytes.Length);
|
||||
string responseAsString = Encoding.UTF8.GetString(responseBytes);
|
||||
string jsonResult = responseAsString.Substring(responseAsString.IndexOf('{'));
|
||||
return JsonHelper.ToObject<ZabbixResponse>(jsonResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
public class ZabbixResponse
|
||||
{
|
||||
public string Response { get; set; }
|
||||
public string Info { get; set; }
|
||||
|
||||
}
|
||||
@@ -183,7 +183,7 @@ async void RunWebLoggingTests()
|
||||
await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
|
||||
}
|
||||
Console.WriteLine($"WebLogged: {i}");
|
||||
Task.Delay(1);
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,10 +203,10 @@ async void RunMaskTest()
|
||||
|
||||
using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "testmask.log"), true))
|
||||
{
|
||||
file.WriteAsync(message);
|
||||
await file.WriteAsync(message);
|
||||
}
|
||||
Console.WriteLine($"Masked: {i}");
|
||||
Task.Delay(1);
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user