Files
EonaCat.Logger/EonaCat.Logger/Servers/Splunk/Splunk.cs
2026-01-12 22:09:07 +01:00

189 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using EonaCat.Json;
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.
namespace EonaCat.Logger.Servers.Splunk
{
/// <summary>
/// Splunk Server.
/// </summary>
public class Splunk : IDisposable
{
private string _splunkHecUrl = "https://127.0.0.1:8088/services/collector/event";
private HttpClient _httpClient;
private HttpClientHandler _httpClientHandler;
private bool _disposed;
public event EventHandler<Exception> OnException;
public string SplunkHecToken { get; set; } = "splunk-hec-token";
public string Nickname { get; set; }
public List<ELogType> TypesToLog { get; set; }
public string SplunkHecUrl
{
get => _splunkHecUrl;
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException(nameof(SplunkHecUrl));
}
_splunkHecUrl = value.StartsWith("http", StringComparison.OrdinalIgnoreCase)
? value
: $"http://{value}";
RecreateHttpClient();
}
}
public bool HasHecToken => !string.IsNullOrWhiteSpace(SplunkHecToken) && SplunkHecToken != "splunk-hec-token";
public bool HasHecUrl => !string.IsNullOrWhiteSpace(_splunkHecUrl);
public bool IsHttpsHecUrl => _splunkHecUrl.StartsWith("https", StringComparison.OrdinalIgnoreCase);
public bool IsLocalHost => _splunkHecUrl.Contains("127.0.0.1") || _splunkHecUrl.Contains("localhost");
public Splunk(string splunkHecUrl, string splunkHecToken, HttpClientHandler handler = null, string nickName = null, List<ELogType> typesToLog = null)
{
SplunkHecToken = splunkHecToken ?? throw new ArgumentNullException(nameof(splunkHecToken));
SplunkHecUrl = splunkHecUrl ?? throw new ArgumentNullException(nameof(splunkHecUrl));
Nickname = nickName ?? $"{splunkHecUrl}_{splunkHecToken}";
TypesToLog = typesToLog;
_httpClientHandler = handler ?? new HttpClientHandler();
CreateHttpClient();
}
private void CreateHttpClient()
{
DisposeHttpClient();
_httpClientHandler ??= new HttpClientHandler();
_httpClient = new HttpClient(_httpClientHandler)
{
BaseAddress = new Uri(SplunkHecUrl)
};
if (!_httpClient.DefaultRequestHeaders.Contains("Authorization"))
{
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Splunk {SplunkHecToken}");
}
}
private void RecreateHttpClient()
{
DisposeHttpClient();
_httpClientHandler = new HttpClientHandler();
CreateHttpClient();
}
public void DisableSSLValidation()
{
DisposeHttpClient();
_httpClientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
CreateHttpClient();
}
public async Task<HttpResponseMessage> SendAsync(SplunkPayload payload, bool disableSplunkSSL = false)
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(Splunk));
}
try
{
if (payload == null || !HasHecToken || !HasHecUrl)
{
return null;
}
if (disableSplunkSSL)
{
DisableSSLValidation();
}
_httpClient ??= new HttpClient(_httpClientHandler ?? new HttpClientHandler())
{
BaseAddress = new Uri(SplunkHecUrl)
};
var eventObject = new
{
@event = payload.EventData,
sourcetype = payload.SourceType,
host = payload.Host
};
var json = JsonHelper.ToJson(eventObject);
using var request = new HttpRequestMessage(HttpMethod.Post, "services/collector/event")
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
};
return await _httpClient.SendAsync(request).ConfigureAwait(false);
}
catch (Exception ex)
{
OnException?.Invoke(this, ex);
return null;
}
}
internal void DisposeHttpClient()
{
try
{
_httpClient?.Dispose();
_httpClientHandler?.Dispose();
}
catch
{
// Silent fail
}
finally
{
_httpClient = null;
_httpClientHandler = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
if (disposing)
{
DisposeHttpClient();
}
}
~Splunk()
{
Dispose(false);
}
}
}