duh
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user