This commit is contained in:
2025-02-16 05:25:30 +01:00
parent 580ebae140
commit 56be35fc15
23 changed files with 1027 additions and 414 deletions

View File

@@ -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.5</FileVersion> <FileVersion>1.3.6</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.5+{chash:10}.{c:ymd}</EVRevisionFormat> <EVRevisionFormat>1.3.6+{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>
@@ -52,10 +52,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="EonaCat.Json" Version="1.0.5" /> <PackageReference Include="EonaCat.Json" Version="1.0.5" />
<PackageReference Include="EonaCat.Versioning" Version="1.0.11"> <PackageReference Include="EonaCat.Versioning" Version="1.2.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive; compile</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference> </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.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />

View File

@@ -310,12 +310,6 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
return message; 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) internal string AddMessage(DateTimeOffset timestamp, string message)
{ {
var result = CreateLoggerMessage(message, timestamp); var result = CreateLoggerMessage(message, timestamp);

View File

@@ -8,12 +8,10 @@ namespace EonaCat.Logger.Managers;
public interface ILogManager public interface ILogManager
{ {
Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null, Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null, string customSplunkSourceType = null, string grayLogFacility = null, string grayLogSource = null,
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
string grayLogVersion = "1.1"); string grayLogVersion = "1.1");
Task WriteAsync(Exception exception, string module = null, string method = null, bool criticalException = false, Task WriteAsync(Exception exception, string module = null, string method = null, bool criticalException = false,
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
string grayLogSource = null, string grayLogVersion = "1.1"); string grayLogSource = null, string grayLogVersion = "1.1");
} }

View File

@@ -2,14 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using EonaCat.Json; using EonaCat.Json;
using EonaCat.Logger.Extensions; using EonaCat.Logger.Extensions;
using EonaCat.Logger.GrayLog; using EonaCat.Logger.Servers.GrayLog;
using EonaCat.Logger.Splunk.Models; using EonaCat.Logger.Servers.Splunk.Models;
using EonaCat.Logger.Syslog;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
// 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.
@@ -35,7 +33,10 @@ internal static class LogHelper
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage, internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
DateTime dateTime, string category = null) DateTime dateTime, string category = null)
{ {
if (string.IsNullOrWhiteSpace(currentMessage)) return currentMessage; if (string.IsNullOrWhiteSpace(currentMessage))
{
return currentMessage;
}
category ??= "General"; category ??= "General";
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]"); var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
@@ -143,9 +144,9 @@ internal static class LogHelper
logger.Log(logLevel, message); 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; return;
} }
@@ -174,9 +175,14 @@ internal static class LogHelper
/// <summary> /// <summary>
/// Overload for sending a simple log message to Splunk. /// Overload for sending a simple log message to Splunk.
/// </summary> /// </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; return;
} }
@@ -188,7 +194,7 @@ internal static class LogHelper
SourceType = logType SourceType = logType
}; };
await SendToSplunkServersAsync(settings, splunkPayload, sendToSplunkServer); await SendToSplunkServersAsync(settings, splunkPayload);
} }
/// <summary> /// <summary>
@@ -201,9 +207,14 @@ internal static class LogHelper
internal static async Task SendToGrayLogServersAsync(LoggerSettings settings, string message, ELogType logLevel, 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; return;
} }
@@ -258,13 +269,12 @@ internal static class LogHelper
await Task.WhenAll(tasks); await Task.WhenAll(tasks);
} }
/// <summary> /// <summary>
/// Sends a message via TCP to a GrayLog server. /// Sends a message via TCP to a GrayLog server.
/// </summary> /// </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); await tcpClient.ConnectAsync(server.Hostname, server.Port);
using var stream = tcpClient.GetStream(); using var stream = tcpClient.GetStream();
await stream.WriteAsync(data, 0, data.Length); await stream.WriteAsync(data, 0, data.Length);
@@ -274,7 +284,7 @@ internal static class LogHelper
/// <summary> /// <summary>
/// Sends large messages in chunks over UDP. /// Sends large messages in chunks over UDP.
/// </summary> /// </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) 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; return;
} }
@@ -329,12 +344,84 @@ internal static class LogHelper
await Task.WhenAll(tasks); 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> /// <summary>
/// Sends a message via TCP to a syslog server. /// Sends a message via TCP to a syslog server.
/// </summary> /// </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); await tcpClient.ConnectAsync(server.Hostname, server.Port);
using var stream = tcpClient.GetStream(); using var stream = tcpClient.GetStream();
await stream.WriteAsync(data, 0, data.Length); await stream.WriteAsync(data, 0, data.Length);
@@ -344,7 +431,7 @@ internal static class LogHelper
/// <summary> /// <summary>
/// Sends large messages in chunks over UDP. /// Sends large messages in chunks over UDP.
/// </summary> /// </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) for (int i = 0; i < data.Length; i += chunkSize)
{ {

View File

@@ -1,13 +1,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Http;
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.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.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -24,23 +30,8 @@ namespace EonaCat.Logger.Managers
private bool _isDisposing; private bool _isDisposing;
private string _category; 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; Settings = settings;
SetupLogManager(); SetupLogManager();
} }
@@ -87,8 +78,7 @@ namespace EonaCat.Logger.Managers
public async Task WriteAsync(Exception exception, string module = null, string method = null, public async Task WriteAsync(Exception exception, string module = null, string method = null,
bool criticalException = false, bool criticalException = false,
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
string grayLogSource = null, string grayLogVersion = "1.1") string grayLogSource = null, string grayLogVersion = "1.1")
{ {
if (exception == null) if (exception == null)
@@ -97,14 +87,14 @@ namespace EonaCat.Logger.Managers
} }
await WriteAsync(exception.FormatExceptionToMessage(module, method), await WriteAsync(exception.FormatExceptionToMessage(module, method),
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers, criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole,
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, customSplunkSourceType, grayLogFacility, grayLogSource,
grayLogVersion); grayLogVersion);
} }
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null, public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null, string customSplunkSourceType = null,
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null, string grayLogFacility = null, string grayLogSource = null,
string grayLogVersion = "1.1") string grayLogVersion = "1.1")
{ {
if (logType == ELogType.NONE) if (logType == ELogType.NONE)
@@ -112,8 +102,8 @@ namespace EonaCat.Logger.Managers
return; return;
} }
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole,
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion); customSplunkSourceType, grayLogFacility, grayLogSource, grayLogVersion);
} }
/// <summary> /// <summary>
@@ -202,8 +192,7 @@ namespace EonaCat.Logger.Managers
} }
private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO, private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO,
bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null, bool? writeToConsole = null, string customSplunkSourceType = null, string grayLogFacility = null,
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
string grayLogSource = null, string grayLogVersion = "1.1") string grayLogSource = null, string grayLogVersion = "1.1")
{ {
if (string.IsNullOrWhiteSpace(message) || logType == ELogType.NONE || !IsLogLevelEnabled(logType) || _isDisposing) 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 messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
var writeToConsoleValue = writeToConsole.GetValueOrDefault(Settings.EnableConsole); 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); LogHelper.SendToFile(Logger, Settings, logType, message);
@@ -229,21 +215,14 @@ namespace EonaCat.Logger.Managers
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true); LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
} }
var tasks = new List<Task>(3); var tasks = new List<Task>(5)
if (sendToSyslogServersValue)
{ {
tasks.Add(LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true)); LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader),
} LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(), messageWithHeader),
if (sendToSplunkServersValue) LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility, grayLogSource, grayLogVersion),
{ LogHelper.SendToTcpLogServersAsync(Settings, messageWithHeader),
tasks.Add(LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(), LogHelper.SendToUdpLogServersAsync(Settings, messageWithHeader),
messageWithHeader, true)); };
}
if (sendToGrayLogServersValue)
{
tasks.Add(LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
grayLogSource, true, grayLogVersion));
}
if (tasks.Count > 0) if (tasks.Count > 0)
{ {
@@ -340,5 +319,326 @@ namespace EonaCat.Logger.Managers
File.Delete(CurrentLogFile); 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;
}
} }
} }

View File

@@ -1,10 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Sockets;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using EonaCat.Logger.EonaCatCoreLogger; using EonaCat.Logger.EonaCatCoreLogger;
using EonaCat.Logger.EonaCatCoreLogger.Models; using EonaCat.Logger.EonaCatCoreLogger.Models;
using EonaCat.Logger.GrayLog; using EonaCat.Logger.Servers.GrayLog;
using EonaCat.Logger.Syslog;
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.
@@ -127,18 +127,13 @@ public class LoggerSettings
} }
public ELogType MaxLogType { get; set; } = ELogType.INFO; 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 List<Servers.Udp.Udp> UdpServers { get; internal set; }
public bool SendToSplunkServers { get; set; }
public bool SendToGrayLogServers { get; set; }
public List<SplunkServer.SplunkServer> SplunkServers { get; set; }
public List<GrayLogServer> GrayLogServers { get; set; }
/// <summary> /// <summary>
/// Determines if the fileLogging is enabled /// Determines if the fileLogging is enabled

View File

@@ -1,87 +1,84 @@
using System; using System;
using System.Net.Sockets; 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. // This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details. // See the LICENSE file or go to https://EonaCat.com/License for full license details.
/// <summary> /// <summary>
/// Syslog server. /// GrayLog client
/// </summary> /// </summary>
public class GrayLogServer public class Graylog : IDisposable
{ {
internal readonly object SendLock = new(); internal readonly object SendLock = new();
private string _Hostname = "127.0.0.1"; private string _Hostname = "127.0.0.1";
private int _Port = 12201; private int _Port = 12201;
internal UdpClient Udp; internal UdpClient Udp;
/// <summary> public bool SupportsTcp { get; set; }
/// Instantiate the object. public string Nickname { get; set; }
/// </summary> public string IpPort => _Hostname + ":" + _Port;
public GrayLogServer()
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 public string Hostname
{ {
get => _Hostname; get => _Hostname;
set set
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException(nameof(Hostname)); throw new ArgumentNullException(nameof(Hostname));
}
_Hostname = value; _Hostname = value;
SetUdp(); SetUdp();
} }
} }
/// <summary>
/// UDP port.
/// </summary>
public int Port public int Port
{ {
get => _Port; get => _Port;
set set
{ {
if (value < 0) if (value < 0)
{
throw new ArgumentException("Port must be zero or greater."); throw new ArgumentException("Port must be zero or greater.");
}
_Port = value; _Port = value;
SetUdp(); SetUdp();
} }
} }
/// <summary>
/// IP:port of the server.
/// </summary>
public string IpPort => _Hostname + ":" + _Port;
public bool SupportsTcp { get; set; }
private void SetUdp() private void SetUdp()
{ {
Udp = null; DisposeUdp();
Udp = new UdpClient(_Hostname, _Port); Udp = new UdpClient(_Hostname, _Port);
} }
private void DisposeUdp()
{
if (Udp != null)
{
Udp.Dispose();
Udp = null;
}
}
public void Dispose()
{
DisposeUdp();
GC.SuppressFinalize(this);
}
~Graylog()
{
Dispose();
}
} }

View File

@@ -1,4 +1,4 @@
namespace EonaCat.Logger.Splunk.Models; namespace EonaCat.Logger.Servers.Splunk.Models;
public class SplunkPayload public class SplunkPayload
{ {

View 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();
}
}

View File

@@ -1,87 +1,82 @@
using System; using System;
using System.Net.Sockets; 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. // This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details. // See the LICENSE file or go to https://EonaCat.com/License for full license details.
/// <summary> /// <summary>
/// Syslog server. /// Syslog server.
/// </summary> /// </summary>
public class SyslogServer public class Syslog : IDisposable
{ {
private string _Hostname = "127.0.0.1"; private string _Hostname = "127.0.0.1";
private int _Port = 514; private int _Port = 514;
internal UdpClient Udp; internal UdpClient Udp;
/// <summary> public Syslog() { }
/// Instantiate the object.
/// </summary>
public SyslogServer()
{
}
/// <summary> public Syslog(string hostname = "127.0.0.1", int port = 514, string nickName = null)
/// 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)
{ {
Hostname = hostname; Hostname = hostname;
Port = port; Port = port;
Nickname = nickName ?? IpPort;
} }
/// <summary>
/// Hostname.
/// </summary>
public string Hostname public string Hostname
{ {
get => _Hostname; get => _Hostname;
set set
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException(nameof(Hostname)); throw new ArgumentNullException(nameof(Hostname));
}
_Hostname = value; _Hostname = value;
SetUdp(); SetUdp();
} }
} }
/// <summary>
/// UDP port.
/// </summary>
public int Port public int Port
{ {
get => _Port; get => _Port;
set set
{ {
if (value < 0) if (value < 0)
{
throw new ArgumentException("Port must be zero or greater."); throw new ArgumentException("Port must be zero or greater.");
}
_Port = value; _Port = value;
SetUdp(); SetUdp();
} }
} }
/// <summary> public string IpPort => _Hostname + ":" + _Port;
/// IP:port of the server. public bool SupportsTcp { get; set; }
/// </summary> public string Nickname { get; set; }
public string IpPort => _Hostname + ":" + _Port;
public bool SupportsTcp { get; set; }
private void SetUdp() private void SetUdp()
{ {
Udp = null; DisposeUdp();
Udp = new UdpClient(_Hostname, _Port); Udp = new UdpClient(_Hostname, _Port);
} }
private void DisposeUdp()
{
if (Udp != null)
{
Udp.Dispose();
Udp = null;
}
}
public void Dispose()
{
DisposeUdp();
GC.SuppressFinalize(this);
}
~Syslog()
{
Dispose();
}
} }

View 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();
}
}
}

View 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();
}
}
}

View File

@@ -5,7 +5,7 @@ using System.IO;
using System.Net; using System.Net;
using System.Text; 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. // 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.
@@ -26,8 +26,8 @@ public class ZabbixApi
} }
public ZabbixApi(string user, string password, string zabbixURL) : this(user, password, zabbixURL, false) public ZabbixApi(string user, string password, string zabbixURL) : this(user, password, zabbixURL, false)
{ {
} }
private readonly string _user; private readonly string _user;
@@ -112,7 +112,7 @@ public class ZabbixApi
private string SendRequest(string jsonParams) private string SendRequest(string jsonParams)
{ {
WebRequest request = WebRequest.Create(_zabbixURL); WebRequest request = WebRequest.Create(_zabbixURL);
if (_basicAuth != null) if (_basicAuth != null)
{ {
request.Headers.Add("Authorization", "Basic " + _basicAuth); request.Headers.Add("Authorization", "Basic " + _basicAuth);

View File

@@ -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. // 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.

View File

@@ -1,6 +1,6 @@
using System.Dynamic; 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. // 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.

View 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;
}
}
}

View 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);
}
}
}
}

View 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; }
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -1,6 +0,0 @@
public class ZabbixResponse
{
public string Response { get; set; }
public string Info { get; set; }
}

View File

@@ -183,7 +183,7 @@ async void RunWebLoggingTests()
await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false); await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
} }
Console.WriteLine($"WebLogged: {i}"); 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)) using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "testmask.log"), true))
{ {
file.WriteAsync(message); await file.WriteAsync(message);
} }
Console.WriteLine($"Masked: {i}"); Console.WriteLine($"Masked: {i}");
Task.Delay(1); await Task.Delay(1);
} }
} }