This commit is contained in:
2026-01-12 22:13:42 +01:00
parent 576a590104
commit 574bbe0632
2 changed files with 36 additions and 32 deletions

View File

@@ -23,7 +23,7 @@
</PropertyGroup>
<PropertyGroup>
<EVRevisionFormat>1.5.3+{chash:10}.{c:ymd}</EVRevisionFormat>
<EVRevisionFormat>1.5.4+{chash:10}.{c:ymd}</EVRevisionFormat>
<EVDefault>true</EVDefault>
<EVInfo>true</EVInfo>
<EVTagMatch>v[0-9]*</EVTagMatch>

View File

@@ -8,9 +8,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
// 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.EonaCatCoreLogger
{
public class DiscordLogger : ILogger, IDisposable
@@ -20,9 +17,9 @@ namespace EonaCat.Logger.EonaCatCoreLogger
private readonly LoggerScopedContext _context = new LoggerScopedContext();
// Static shared resources
private static readonly ConcurrentQueue<string> _messageQueue = new ConcurrentQueue<string>();
private static readonly HttpClient _httpClient = new HttpClient();
private static readonly SemaphoreSlim _flushLock = new SemaphoreSlim(1, 1);
private static readonly ConcurrentQueue<string> _messageQueue = new ConcurrentQueue<string>();
private static bool _flushLoopStarted = false;
private static CancellationTokenSource _cts;
@@ -42,8 +39,7 @@ namespace EonaCat.Logger.EonaCatCoreLogger
{
_flushLoopStarted = true;
_cts = new CancellationTokenSource();
_flushTask = Task.Factory.StartNew(() => FlushLoop(_cts.Token),
_cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
_flushTask = Task.Run(() => FlushLoopAsync(_cts.Token));
}
}
@@ -58,9 +54,7 @@ namespace EonaCat.Logger.EonaCatCoreLogger
Exception exception, Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel) || formatter == null)
{
return;
}
if (IncludeCorrelationId)
{
@@ -69,7 +63,6 @@ namespace EonaCat.Logger.EonaCatCoreLogger
}
var message = formatter(state, exception);
var logParts = new List<string>
{
$"**[{DateTime.UtcNow:u}]**",
@@ -79,31 +72,32 @@ namespace EonaCat.Logger.EonaCatCoreLogger
};
foreach (var kvp in _context.GetAll())
{
logParts.Add($"`{kvp.Key}`: {kvp.Value}");
}
if (exception != null)
{
logParts.Add($"Exception: {exception}");
}
// Limit queue size to prevent memory growth
if (_messageQueue.Count < 1000)
_messageQueue.Enqueue(string.Join("\n", logParts));
else
OnException?.Invoke(this, new Exception("DiscordLogger queue overflow"));
}
private void FlushLoop(CancellationToken token)
private async Task FlushLoopAsync(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
Thread.Sleep(TimeSpan.FromSeconds(_options.FlushIntervalSeconds));
FlushBuffer(token).Wait(token);
await Task.Delay(TimeSpan.FromSeconds(_options.FlushIntervalSeconds), token)
.ConfigureAwait(false);
await FlushBufferAsync(token).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
// Expected when cancelling
// Expected on cancel
}
catch (Exception ex)
{
@@ -111,12 +105,10 @@ namespace EonaCat.Logger.EonaCatCoreLogger
}
}
private async Task FlushBuffer(CancellationToken token)
{
if (!await _flushLock.WaitAsync(0, token))
private async Task FlushBufferAsync(CancellationToken token)
{
if (!await _flushLock.WaitAsync(0, token).ConfigureAwait(false))
return;
}
try
{
@@ -125,16 +117,16 @@ namespace EonaCat.Logger.EonaCatCoreLogger
try
{
var payload = new { content = message };
using (var content = new StringContent(JsonHelper.ToJson(payload), Encoding.UTF8, "application/json"))
{
var response = await _httpClient.PostAsync(_options.WebhookUrl, content, token);
using var content = new StringContent(JsonHelper.ToJson(payload), Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(_options.WebhookUrl, content, token)
.ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var error = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
OnException?.Invoke(this, new Exception($"Discord webhook failed: {response.StatusCode} {error}"));
}
}
}
catch (Exception ex)
{
OnException?.Invoke(this, ex);
@@ -152,7 +144,6 @@ namespace EonaCat.Logger.EonaCatCoreLogger
if (_cts != null && !_cts.IsCancellationRequested)
{
_cts.Cancel();
try
{
_flushTask?.Wait();
@@ -161,12 +152,25 @@ namespace EonaCat.Logger.EonaCatCoreLogger
{
ae.Handle(e => e is OperationCanceledException);
}
_cts.Dispose();
_cts = null;
}
}
// Optional: call this on app shutdown
public static void Shutdown()
{
_cts?.Cancel();
try
{
_flushTask?.Wait();
}
catch (AggregateException ae)
{
ae.Handle(e => e is OperationCanceledException);
}
_flushLock.Dispose();
_httpClient.Dispose();
}
}
}