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