Updated
This commit is contained in:
@@ -69,17 +69,17 @@ public sealed class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
var file = GetFullName(group.Key);
|
var file = GetFullName(group.Key);
|
||||||
InitializeFile(file);
|
InitializeFile(file);
|
||||||
|
|
||||||
var sb = _buffers.GetOrAdd(file, _ => new StringBuilder(4096));
|
var stringBuilder = _buffers.GetOrAdd(file, _ => new StringBuilder(4096));
|
||||||
|
|
||||||
lock (sb)
|
lock (stringBuilder)
|
||||||
{
|
{
|
||||||
foreach (var message in group)
|
foreach (var message in group)
|
||||||
{
|
{
|
||||||
AppendMessage(sb, message);
|
AppendMessage(stringBuilder, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await FlushAsync(file, sb, token).ConfigureAwait(false);
|
await FlushAsync(file, stringBuilder, token).ConfigureAwait(false);
|
||||||
DeleteOldLogFiles();
|
DeleteOldLogFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,9 +127,9 @@ public sealed class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
_currentFileSize = File.Exists(_logFile) ? new FileInfo(_logFile).Length : 0;
|
_currentFileSize = File.Exists(_logFile) ? new FileInfo(_logFile).Length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FlushAsync(string file, StringBuilder sb, CancellationToken token)
|
private async Task FlushAsync(string file, StringBuilder stringBuilder, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (sb.Length == 0)
|
if (stringBuilder.Length == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -137,22 +137,25 @@ public sealed class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
await _writeLock.WaitAsync(token).ConfigureAwait(false);
|
await _writeLock.WaitAsync(token).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var fs = new FileStream(
|
var text = stringBuilder.ToString();
|
||||||
|
byte[] bytesToWrite = Encoding.UTF8.GetBytes(text);
|
||||||
|
|
||||||
|
using (var fileStream = new FileStream(
|
||||||
file,
|
file,
|
||||||
FileMode.Append,
|
FileMode.Append,
|
||||||
FileAccess.Write,
|
FileAccess.Write,
|
||||||
FileShare.Read,
|
FileShare.Read,
|
||||||
64 * 1024,
|
64 * 1024,
|
||||||
useAsync: true);
|
useAsync: true))
|
||||||
|
{
|
||||||
|
await fileStream.WriteAsync(bytesToWrite, 0, bytesToWrite.Length, token);
|
||||||
|
}
|
||||||
|
|
||||||
using var writer = new StreamWriter(fs, Encoding.UTF8);
|
// Update current file size correctly
|
||||||
var text = sb.ToString();
|
_fileSizes.AddOrUpdate(file, bytesToWrite.Length, (_, old) => old + bytesToWrite.Length);
|
||||||
await writer.WriteAsync(text).ConfigureAwait(false);
|
|
||||||
|
|
||||||
_fileSizes.AddOrUpdate(file, Encoding.UTF8.GetByteCount(text), (_, old) => old + Encoding.UTF8.GetByteCount(text));
|
|
||||||
_currentFileSize = _fileSizes[file];
|
_currentFileSize = _fileSizes[file];
|
||||||
|
|
||||||
sb.Clear();
|
stringBuilder.Clear();
|
||||||
|
|
||||||
if (_fileSizes[file] >= _maxFileSize)
|
if (_fileSizes[file] >= _maxFileSize)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ using EonaCat.Logger.Extensions;
|
|||||||
using EonaCat.Logger.Managers;
|
using EonaCat.Logger.Managers;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
||||||
{
|
{
|
||||||
@@ -25,13 +22,8 @@ namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
|||||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTimeOffset Now
|
private DateTimeOffset Now =>
|
||||||
{
|
_settings.UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;
|
||||||
get
|
|
||||||
{
|
|
||||||
return _settings.UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
|
public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
|
||||||
|
|
||||||
@@ -49,64 +41,41 @@ namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string rawMessage;
|
string rawMessage = exception != null
|
||||||
if (exception != null)
|
? exception.FormatExceptionToMessage()
|
||||||
{
|
: formatter?.Invoke(state, null);
|
||||||
rawMessage = exception.FormatExceptionToMessage();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rawMessage = formatter != null ? formatter(state, null) : string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(rawMessage))
|
if (string.IsNullOrEmpty(rawMessage))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var timestamp = Now;
|
|
||||||
LogInternalAsync(timestamp, logLevel, rawMessage, exception).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LogInternalAsync(
|
|
||||||
DateTimeOffset timestamp,
|
|
||||||
LogLevel logLevel,
|
|
||||||
string message,
|
|
||||||
Exception exception)
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var timestamp = Now;
|
||||||
|
|
||||||
string formatted = LogHelper.FormatMessageWithHeader(
|
string formatted = LogHelper.FormatMessageWithHeader(
|
||||||
_settings,
|
_settings,
|
||||||
logLevel.FromLogLevel(),
|
logLevel.FromLogLevel(),
|
||||||
message,
|
rawMessage,
|
||||||
timestamp.DateTime,
|
timestamp.DateTime,
|
||||||
_category);
|
_category);
|
||||||
|
|
||||||
var writtenMessage = _provider.AddMessage(timestamp, formatted, _category);
|
var writtenMessage = _provider.AddMessage(timestamp, formatted, _category);
|
||||||
var onLogEvent = _settings.OnLogEvent;
|
|
||||||
|
|
||||||
if (onLogEvent != null)
|
_settings.RaiseOnLog(new EonaCatLogMessage
|
||||||
{
|
|
||||||
onLogEvent(new EonaCatLogMessage
|
|
||||||
{
|
{
|
||||||
DateTime = timestamp.DateTime,
|
DateTime = timestamp.DateTime,
|
||||||
Message = writtenMessage,
|
Message = writtenMessage,
|
||||||
LogType = logLevel.FromLogLevel(),
|
LogType = logLevel.FromLogLevel(),
|
||||||
Category = _category,
|
Category = _category,
|
||||||
Exception = exception,
|
Exception = exception,
|
||||||
Origin = string.IsNullOrWhiteSpace(_settings.LogOrigin) ? "BatchingLogger" : _settings.LogOrigin
|
Origin = string.IsNullOrWhiteSpace(_settings.LogOrigin)
|
||||||
|
? "BatchingLogger"
|
||||||
|
: _settings.LogOrigin
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
await _provider.WriteMessagesAsync(new List<LogMessage>
|
|
||||||
{
|
|
||||||
new LogMessage
|
|
||||||
{
|
|
||||||
Timestamp = timestamp,
|
|
||||||
Message = formatted
|
|
||||||
}
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -116,7 +85,7 @@ namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
|||||||
|
|
||||||
private sealed class NullScope : IDisposable
|
private sealed class NullScope : IDisposable
|
||||||
{
|
{
|
||||||
public static readonly NullScope Instance = new NullScope();
|
public static readonly NullScope Instance = new();
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_batchSize = currentOptions.BatchSize > 0 ? currentOptions.BatchSize : 100;
|
_batchSize = currentOptions.BatchSize > 0 ? currentOptions.BatchSize : 100;
|
||||||
_queue = new BlockingCollection<LogMessage>(new ConcurrentQueue<LogMessage>());
|
_queue = new BlockingCollection<LogMessage>(Math.Max(1, _batchSize * 2));
|
||||||
|
|
||||||
if (currentOptions is FileLoggerOptions file)
|
if (currentOptions is FileLoggerOptions file)
|
||||||
{
|
{
|
||||||
@@ -102,23 +102,24 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
private async Task ProcessLoop()
|
private async Task ProcessLoop()
|
||||||
{
|
{
|
||||||
var batch = new List<LogMessage>(_batchSize);
|
var batch = new List<LogMessage>(_batchSize);
|
||||||
|
var flushInterval = LoggerSettings.FileLoggerOptions.FlushPeriod;
|
||||||
|
var timeoutMs = (int)Math.Min(flushInterval.TotalMilliseconds, int.MaxValue);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var item in _queue.GetConsumingEnumerable(_cts.Token))
|
while (!_cts.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (_queue.TryTake(out var item, timeoutMs, _cts.Token))
|
||||||
{
|
{
|
||||||
batch.Add(item);
|
batch.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
if (batch.Count >= _batchSize)
|
if (batch.Count >= _batchSize ||
|
||||||
|
(batch.Count > 0 && !_queue.TryTake(out _, 0)))
|
||||||
{
|
{
|
||||||
await FlushBatchAsync(batch);
|
await FlushBatchAsync(batch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batch.Count > 0)
|
|
||||||
{
|
|
||||||
await FlushBatchAsync(batch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
@@ -127,10 +128,6 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
await FlushBatchAsync(batch);
|
await FlushBatchAsync(batch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FlushBatchAsync(List<LogMessage> batch)
|
private async Task FlushBatchAsync(List<LogMessage> batch)
|
||||||
|
|||||||
@@ -118,32 +118,29 @@ namespace EonaCat.Logger.Managers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsRunning)
|
|
||||||
{
|
|
||||||
await StartNewLogAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole,
|
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole,
|
||||||
customSplunkSourceType, grayLogFacility, grayLogSource, grayLogVersion, disableSplunkSSL)
|
customSplunkSourceType, grayLogFacility, grayLogSource, grayLogVersion, disableSplunkSSL)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private readonly SemaphoreSlim _startLock = new(1, 1);
|
||||||
public async Task StartNewLogAsync()
|
public async Task StartNewLogAsync()
|
||||||
{
|
{
|
||||||
if (_isDisposing || _tokenSource.IsCancellationRequested)
|
if (_isDisposing || _tokenSource.IsCancellationRequested)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
|
await _startLock.WaitAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
if (IsRunning && CurrentDateTime.Date > _logDate.Date)
|
if (IsRunning && CurrentDateTime.Date > _logDate.Date)
|
||||||
{
|
{
|
||||||
await StopLoggingAsync().ConfigureAwait(false);
|
await StopLoggingAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IsRunning)
|
||||||
|
{
|
||||||
CreateLogger();
|
CreateLogger();
|
||||||
|
|
||||||
// Ensure log file exists
|
|
||||||
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
||||||
if (LoggerProvider is FileLoggerProvider fileProvider)
|
if (LoggerProvider is FileLoggerProvider fileProvider)
|
||||||
{
|
{
|
||||||
@@ -153,7 +150,12 @@ namespace EonaCat.Logger.Managers
|
|||||||
_logDate = CurrentDateTime;
|
_logDate = CurrentDateTime;
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_startLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task StopLoggingAsync()
|
private async Task StopLoggingAsync()
|
||||||
{
|
{
|
||||||
@@ -175,6 +177,12 @@ namespace EonaCat.Logger.Managers
|
|||||||
|
|
||||||
private void CreateLogger()
|
private void CreateLogger()
|
||||||
{
|
{
|
||||||
|
if (Logger != null)
|
||||||
|
{
|
||||||
|
// already created
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_isDisposing)
|
if (_isDisposing)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -355,4 +355,9 @@ public class LoggerSettings
|
|||||||
TypesToLog.Add(ELogType.DEBUG);
|
TypesToLog.Add(ELogType.DEBUG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void RaiseOnLog(EonaCatLogMessage eonaCatLogMessage)
|
||||||
|
{
|
||||||
|
OnLogEvent(eonaCatLogMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user