Updated
This commit is contained in:
@@ -73,34 +73,59 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
protected override async Task WriteMessagesAsync(IEnumerable<LogMessage> messages,
|
protected override async Task WriteMessagesAsync(IEnumerable<LogMessage> messages,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(_path);
|
if (IsWriting)
|
||||||
|
|
||||||
foreach (var group in messages.GroupBy(GetGrouping))
|
|
||||||
{
|
{
|
||||||
LogFile = GetFullName(group.Key);
|
return;
|
||||||
var fileInfo = new FileInfo(LogFile);
|
}
|
||||||
var currentMessages = string.Join(string.Empty, group.Select(item => item.Message));
|
|
||||||
if (!_buffer.TryAdd(LogFile, currentMessages))
|
|
||||||
{
|
|
||||||
_buffer[LogFile] += currentMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
await MoveRolloverLogFilesAsync(fileInfo, cancellationToken).ConfigureAwait(false);
|
IsWriting = true;
|
||||||
|
|
||||||
if (await TryWriteToFileAsync(cancellationToken))
|
try
|
||||||
{
|
{
|
||||||
// Clear buffer on success
|
Directory.CreateDirectory(_path);
|
||||||
_buffer.Clear();
|
|
||||||
}
|
|
||||||
else if (await WriteToTempFileAsync(cancellationToken))
|
|
||||||
{
|
|
||||||
// Fallback to temp file
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteOldLogFiles();
|
foreach (var group in messages.GroupBy(GetGrouping))
|
||||||
|
{
|
||||||
|
LogFile = GetFullName(group.Key);
|
||||||
|
var currentMessages = string.Join(string.Empty, group.Select(item => item.Message));
|
||||||
|
if (!_buffer.TryAdd(LogFile, currentMessages))
|
||||||
|
{
|
||||||
|
_buffer[LogFile] += currentMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check file size
|
||||||
|
FileInfo fileInfo = new FileInfo(LogFile);
|
||||||
|
if (fileInfo.Exists && fileInfo.Length >= _maxFileSize)
|
||||||
|
{
|
||||||
|
// Roll over the log file
|
||||||
|
await RollOverLogFile().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await TryWriteToFileAsync(cancellationToken))
|
||||||
|
{
|
||||||
|
// Clear buffer on success
|
||||||
|
_buffer.Clear();
|
||||||
|
}
|
||||||
|
else if (await WriteToTempFileAsync(cancellationToken))
|
||||||
|
{
|
||||||
|
// Fallback to temp file
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteOldLogFiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
OnError?.Invoke(this, new ErrorMessage { Exception = exception, Message = "Cannot write to file"});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsWriting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsWriting { get; set; }
|
||||||
|
|
||||||
private async Task<bool> TryWriteToFileAsync(CancellationToken cancellationToken)
|
private async Task<bool> TryWriteToFileAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!_buffer.ContainsKey(LogFile)) return true;
|
if (!_buffer.ContainsKey(LogFile)) return true;
|
||||||
@@ -116,10 +141,9 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
{
|
{
|
||||||
await file.WriteAsync(_buffer[LogFile]).ConfigureAwait(false);
|
await file.WriteAsync(_buffer[LogFile]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
completed = true;
|
completed = true;
|
||||||
_buffer.TryRemove(LogFile, out _);
|
_buffer.TryRemove(LogFile, out _);
|
||||||
return true; // Success
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -128,7 +152,7 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
if (tries >= _maxTries)
|
if (tries >= _maxTries)
|
||||||
{
|
{
|
||||||
OnError?.Invoke(this, new ErrorMessage { Message = "Cannot write to log folder"});
|
OnError?.Invoke(this, new ErrorMessage { Message = "Cannot write to log folder"});
|
||||||
return false; // Failure after retries
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,104 +202,82 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
return (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day);
|
return (message.Timestamp.Year, message.Timestamp.Month, message.Timestamp.Day);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MoveFile(string copyFromPath, string copyToPath)
|
private readonly object lockObj = new object();
|
||||||
{
|
|
||||||
var origin = new FileInfo(copyFromPath);
|
|
||||||
origin.MoveTo(copyToPath);
|
|
||||||
|
|
||||||
var destination = new FileInfo(copyToPath);
|
private async Task RollOverLogFile()
|
||||||
destination.CreationTime = origin.CreationTime;
|
{
|
||||||
destination.LastWriteTime = origin.LastWriteTime;
|
lock (lockObj)
|
||||||
destination.LastAccessTime = origin.LastAccessTime;
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string directoryPath = Path.GetDirectoryName(LogFile);
|
||||||
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(LogFile);
|
||||||
|
string fileExtension = Path.GetExtension(LogFile);
|
||||||
|
|
||||||
|
// Rename existing files
|
||||||
|
for (int i = _maxRolloverFiles - 1; i >= 1; i--)
|
||||||
|
{
|
||||||
|
string currentFilePath = Path.Combine(directoryPath, $"{fileNameWithoutExtension}.{i}{fileExtension}");
|
||||||
|
string newFilePath = Path.Combine(directoryPath, $"{fileNameWithoutExtension}.{(i + 1)}{fileExtension}");
|
||||||
|
|
||||||
|
if (File.Exists(currentFilePath))
|
||||||
|
{
|
||||||
|
if (File.Exists(newFilePath))
|
||||||
|
{
|
||||||
|
File.Delete(newFilePath);
|
||||||
|
}
|
||||||
|
File.Move(currentFilePath, newFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != 1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFilePath = Path.Combine(directoryPath, $"{fileNameWithoutExtension}{fileExtension}");
|
||||||
|
newFilePath = Path.Combine(directoryPath, $"{fileNameWithoutExtension}.{i}{fileExtension}");
|
||||||
|
File.Move(currentFilePath, newFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename current log file
|
||||||
|
var rolloverFilePath = Path.Combine(directoryPath, $"{fileNameWithoutExtension}.1{fileExtension}");
|
||||||
|
|
||||||
|
// Write end message and start processing in background
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await WriteEndMessageAsync(rolloverFilePath).ConfigureAwait(false);
|
||||||
|
await ProcessAsync().ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log or handle the exception
|
||||||
|
Console.WriteLine($"Error occurred during log file rollover: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task MoveRolloverLogFilesAsync(FileInfo fileInfo, CancellationToken cancellationToken)
|
private async Task WriteEndMessageAsync(string logFilePath)
|
||||||
|
{
|
||||||
|
var stopMessage = LogHelper.GetStopMessage();
|
||||||
|
stopMessage = LogHelper.FormatMessageWithHeader(LoggerSettings, ELogType.INFO, stopMessage, CurrentDateTme);
|
||||||
|
|
||||||
|
using (var file = new StreamWriter(logFilePath, true))
|
||||||
|
{
|
||||||
|
await file.WriteAsync(stopMessage).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_maxFileSize > 0 && fileInfo.Exists && fileInfo.Length > _maxFileSize)
|
await WriteStartMessage().ConfigureAwait(false);
|
||||||
{
|
|
||||||
if (_maxRolloverFiles > 0 && _rollOverCount >= 0)
|
|
||||||
{
|
|
||||||
if (_rollOverCount < _maxRolloverFiles)
|
|
||||||
{
|
|
||||||
var rollOverFile = LogFile.Replace(".log", $"_{++_rollOverCount}.log");
|
|
||||||
if (File.Exists(rollOverFile))
|
|
||||||
{
|
|
||||||
File.Delete(rollOverFile);
|
|
||||||
}
|
|
||||||
fileInfo.CopyTo(rollOverFile);
|
|
||||||
File.WriteAllText(LogFile, string.Empty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lock (_rollOverLock)
|
|
||||||
{
|
|
||||||
_rollingOver = true;
|
|
||||||
MoveRolloverLogFiles();
|
|
||||||
_rollingOver = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (_rollingOver)
|
|
||||||
{
|
|
||||||
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
OnError?.Invoke(this, new ErrorMessage { Message = "Cannot rollover files" });
|
// Log or handle the exception
|
||||||
}
|
Console.WriteLine($"Error occurred during log file rollover: {ex.Message}");
|
||||||
}
|
|
||||||
|
|
||||||
private object _rollOverLock { get; set; } = new object();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Rollover logFiles
|
|
||||||
/// </summary>
|
|
||||||
private void MoveRolloverLogFiles()
|
|
||||||
{
|
|
||||||
if (_maxRolloverFiles > 0 && _rollOverCount >= 0)
|
|
||||||
{
|
|
||||||
if (_rollOverCount >= _maxRolloverFiles)
|
|
||||||
{
|
|
||||||
var maxRollover = _rollOverCount;
|
|
||||||
bool hasPrefix = !string.IsNullOrWhiteSpace(_fileNamePrefix);
|
|
||||||
IEnumerable<FileInfo> files;
|
|
||||||
if (hasPrefix)
|
|
||||||
{
|
|
||||||
files = new DirectoryInfo(_path).GetFiles(_fileNamePrefix + "*").OrderBy(x => x.CreationTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
files = new DirectoryInfo(_path).GetFiles("*").OrderBy(x => x.CreationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = files.Count() - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var currentFile = files.ElementAt(i);
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
// Temporary move first file
|
|
||||||
var newFilename2 = Path.GetFileName(currentFile.FullName).Replace($".log", $"_{i + 1}.log");
|
|
||||||
MoveFile(currentFile.FullName, $@"{Path.GetDirectoryName(currentFile.FullName)}\{newFilename2}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == files.Count() - 1)
|
|
||||||
{
|
|
||||||
// Delete the last file
|
|
||||||
File.Delete(currentFile.FullName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newFilename = Path.GetFileName(currentFile.FullName).Replace($"_{i}.log", $"_{i + 1}.log");
|
|
||||||
MoveFile(currentFile.FullName, $@"{Path.GetDirectoryName(currentFile.FullName)}\{newFilename}");
|
|
||||||
}
|
|
||||||
_rollOverCount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
|
|
||||||
private ConcurrentQueue<LogMessage> _messageQueue;
|
private ConcurrentQueue<LogMessage> _messageQueue;
|
||||||
private Task _outputTask;
|
private Task _outputTask;
|
||||||
|
private object _writeLock = new object();
|
||||||
|
private bool _isDisposing;
|
||||||
|
|
||||||
protected BatchingLoggerProvider(IOptions<BatchingLoggerOptions> options)
|
protected BatchingLoggerProvider(IOptions<BatchingLoggerOptions> options)
|
||||||
{
|
{
|
||||||
@@ -33,7 +35,7 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
if (options.Value is FileLoggerOptions fileLoggerOptions) UseLocalTime = fileLoggerOptions.UseLocalTime;
|
if (options.Value is FileLoggerOptions fileLoggerOptions) UseLocalTime = fileLoggerOptions.UseLocalTime;
|
||||||
_batchSize = loggerOptions.BatchSize;
|
_batchSize = loggerOptions.BatchSize;
|
||||||
|
|
||||||
Start();
|
StartAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DateTimeOffset CurrentDateTimeOffset => UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;
|
protected DateTimeOffset CurrentDateTimeOffset => UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;
|
||||||
@@ -59,8 +61,12 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
while (!_messageQueue.IsEmpty) Task.Delay(10);
|
while (!_messageQueue.IsEmpty)
|
||||||
|
{
|
||||||
|
Task.Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isDisposing = true;
|
||||||
StopAsync().GetAwaiter().GetResult();
|
StopAsync().GetAwaiter().GetResult();
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
@@ -71,14 +77,8 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Task WriteMessagesAsync(IEnumerable<LogMessage> messages, CancellationToken token);
|
protected abstract Task WriteMessagesAsync(IEnumerable<LogMessage> messages, CancellationToken token);
|
||||||
|
|
||||||
private async Task ProcessLogQueueAsync(object state)
|
private async Task ProcessLogQueueAsync(object state)
|
||||||
{
|
{
|
||||||
var startupMessage = $"{DllInfo.ApplicationName} started.{Environment.NewLine}";
|
|
||||||
startupMessage =
|
|
||||||
LogHelper.FormatMessageWithHeader(LoggerSettings, ELogType.INFO, startupMessage, CurrentDateTme);
|
|
||||||
AddMessage(DateTimeOffset.Now, startupMessage);
|
|
||||||
|
|
||||||
while (!_cancellationTokenSource.IsCancellationRequested)
|
while (!_cancellationTokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var limit = _batchSize <= 0 ? int.MaxValue : _batchSize;
|
var limit = _batchSize <= 0 ? int.MaxValue : _batchSize;
|
||||||
@@ -89,44 +89,57 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_currentBatch.Count > 0)
|
if (_currentBatch.Count > 0)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await WriteMessagesAsync(_currentBatch, _cancellationTokenSource.Token).ConfigureAwait(false);
|
if (_isDisposing)
|
||||||
_currentBatch.Clear();
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_writeLock)
|
||||||
|
{
|
||||||
|
WriteMessagesAsync(_currentBatch, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
_currentBatch.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Thread.Sleep(10);
|
Thread.Sleep(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task WriteStartMessage()
|
||||||
|
{
|
||||||
|
var message = LogHelper.GetStartupMessage();
|
||||||
|
await WriteMessagesAsync(new List<LogMessage> { new LogMessage() { Message = message, Timestamp = CurrentDateTimeOffset } }, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task WriteStopMessage()
|
||||||
|
{
|
||||||
|
var message = LogHelper.GetStopMessage();
|
||||||
|
await WriteMessagesAsync(new List<LogMessage> { new LogMessage() { Message = message, Timestamp = CurrentDateTimeOffset } }, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
internal void AddMessage(DateTimeOffset timestamp, string message)
|
internal void AddMessage(DateTimeOffset timestamp, string message)
|
||||||
{
|
{
|
||||||
_messageQueue.Enqueue(new LogMessage { Message = message, Timestamp = timestamp });
|
_messageQueue.Enqueue(new LogMessage { Message = message, Timestamp = timestamp });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start()
|
private Task StartAsync()
|
||||||
{
|
{
|
||||||
IsStarted = true;
|
IsStarted = true;
|
||||||
_messageQueue = new ConcurrentQueue<LogMessage>();
|
_messageQueue = new ConcurrentQueue<LogMessage>();
|
||||||
|
|
||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
_outputTask = Task.Factory.StartNew(
|
_outputTask = Task.Factory.StartNew(
|
||||||
ProcessLogQueueAsync,
|
ProcessLogQueueAsync,
|
||||||
null,
|
null,
|
||||||
TaskCreationOptions.LongRunning).ContinueWith(async x =>
|
TaskCreationOptions.LongRunning);
|
||||||
{
|
return Task.CompletedTask;
|
||||||
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
|
||||||
stopMessage = LogHelper.FormatMessageWithHeader(LoggerSettings, ELogType.INFO, stopMessage, CurrentDateTme);
|
|
||||||
await WriteMessagesAsync(
|
|
||||||
new List<LogMessage>(new List<LogMessage>
|
|
||||||
{ new() { Message = stopMessage, Timestamp = CurrentDateTme } }),
|
|
||||||
_cancellationTokenSource.Token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StopAsync()
|
private async Task StopAsync()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace EonaCat.Logger.Managers;
|
namespace EonaCat.Logger.Managers;
|
||||||
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||||
@@ -6,13 +7,13 @@ namespace EonaCat.Logger.Managers;
|
|||||||
|
|
||||||
public interface ILogManager
|
public interface ILogManager
|
||||||
{
|
{
|
||||||
void Write(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null,
|
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||||
string grayLogVersion = "1.1");
|
string grayLogVersion = "1.1");
|
||||||
|
|
||||||
void Write(Exception exception, string module = null, string method = null, bool criticalException = false,
|
Task WriteAsync(Exception exception, string module = null, string method = null, bool criticalException = false,
|
||||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||||
string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1");
|
string grayLogSource = null, string grayLogVersion = "1.1");
|
||||||
}
|
}
|
||||||
@@ -261,4 +261,14 @@ internal static class LogHelper
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string GetStartupMessage()
|
||||||
|
{
|
||||||
|
return $"{DllInfo.ApplicationName} started.";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetStopMessage()
|
||||||
|
{
|
||||||
|
return $"{DllInfo.ApplicationName} stopped.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
|
|
||||||
private readonly CancellationTokenSource _tokenSource = new();
|
private readonly CancellationTokenSource _tokenSource = new();
|
||||||
private DateTime _logDate;
|
private DateTime _logDate;
|
||||||
|
private bool _isDisposing;
|
||||||
|
|
||||||
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
||||||
{
|
{
|
||||||
@@ -68,31 +69,33 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(Exception exception, string module = null, string method = null, bool criticalException = false,
|
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
||||||
|
bool criticalException = false,
|
||||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||||
string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||||
{
|
{
|
||||||
if (exception == null)
|
if (exception == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Write(exception.FormatExceptionToMessage(module, method),
|
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
||||||
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
||||||
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
||||||
grayLogVersion);
|
grayLogVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null,
|
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||||
string grayLogVersion = "1.1")
|
string grayLogVersion = "1.1")
|
||||||
{
|
{
|
||||||
if (logType == ELogType.NONE)
|
if (logType == ELogType.NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!IsRunning) StartNewLogAsync().ConfigureAwait(false);
|
await InternalWriteAsync(CurrentDateTme, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
||||||
InternalWriteAsync(CurrentDateTme, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion).ConfigureAwait(false);
|
||||||
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<ErrorMessage> OnException;
|
public event EventHandler<ErrorMessage> OnException;
|
||||||
@@ -113,14 +116,22 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
|
|
||||||
protected virtual async Task DisposeAsync(bool disposing)
|
protected virtual async Task DisposeAsync(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing) await StopLoggingAsync().ConfigureAwait(false);
|
if (disposing)
|
||||||
|
{
|
||||||
|
_isDisposing = true;
|
||||||
|
await StopLoggingAsync().ConfigureAwait(false);
|
||||||
|
await Task.Delay(100).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartNewLogAsync()
|
public async Task StartNewLogAsync()
|
||||||
{
|
{
|
||||||
if (_tokenSource.IsCancellationRequested) return;
|
if (_tokenSource.IsCancellationRequested) return;
|
||||||
|
|
||||||
if (IsRunning && CurrentDateTme.Date > _logDate.Date) await StopLoggingAsync().ConfigureAwait(false);
|
if (IsRunning && CurrentDateTme.Date > _logDate.Date)
|
||||||
|
{
|
||||||
|
await StopLoggingAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
|
|
||||||
@@ -158,6 +169,7 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
||||||
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||||
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
||||||
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,6 +181,16 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE ||
|
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE ||
|
||||||
(int)logType > (int)Settings.MaxLogType) return;
|
(int)logType > (int)Settings.MaxLogType) return;
|
||||||
|
|
||||||
|
if (_isDisposing)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsRunning)
|
||||||
|
{
|
||||||
|
await StartNewLogAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime);
|
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime);
|
||||||
var writeToConsoleValue = writeToConsole ?? Settings.EnableConsole;
|
var writeToConsoleValue = writeToConsole ?? Settings.EnableConsole;
|
||||||
var sendToSyslogServersValue = sendToSyslogServers ?? Settings.SendToSyslogServers;
|
var sendToSyslogServersValue = sendToSyslogServers ?? Settings.SendToSyslogServers;
|
||||||
@@ -233,15 +255,9 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
private void SetupLogManager()
|
private void SetupLogManager()
|
||||||
{
|
{
|
||||||
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
||||||
Console.CancelKeyPress += Console_CancelKeyPress;
|
|
||||||
_logDate = CurrentDateTme;
|
_logDate = CurrentDateTme;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessExit(object sender, EventArgs e)
|
private void ProcessExit(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
@@ -249,10 +265,17 @@ public class LogManager : ILogManager, IDisposable
|
|||||||
|
|
||||||
private Task StopLoggingAsync()
|
private Task StopLoggingAsync()
|
||||||
{
|
{
|
||||||
|
WriteStopMessage();
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteStopMessage()
|
||||||
|
{
|
||||||
|
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
||||||
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, stopMessage);
|
||||||
|
}
|
||||||
|
|
||||||
public void DeleteCurrentLogFile()
|
public void DeleteCurrentLogFile()
|
||||||
{
|
{
|
||||||
if (CurrentLogFile != null)
|
if (CurrentLogFile != null)
|
||||||
|
|||||||
@@ -85,22 +85,22 @@ public static class Logger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(string message, ELogType logType = ELogType.INFO, bool writeToConsole = true)
|
public static async Task LogAsync(string message, ELogType logType = ELogType.INFO, bool writeToConsole = true)
|
||||||
{
|
{
|
||||||
if (IsDisabled)
|
if (IsDisabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LogManager.Write(message, logType, writeToConsole);
|
await LogManager.WriteAsync(message, logType, writeToConsole).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(Exception exception, string message = "", bool writeToConsole = true)
|
public static async Task LogAsync(Exception exception, string message = "", bool writeToConsole = true)
|
||||||
{
|
{
|
||||||
if (IsDisabled)
|
if (IsDisabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ELogType.ERROR <= MaxLogType)
|
if (ELogType.ERROR <= MaxLogType)
|
||||||
{
|
{
|
||||||
LogManager.Write(exception, message, writeToConsole: writeToConsole);
|
await LogManager.WriteAsync(exception, message, writeToConsole: writeToConsole).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,13 @@ using EonaCat.Web.Tracer.Extensions;
|
|||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
|
Logger.UseLocalTime = true;
|
||||||
|
Logger.MaxLogType = ELogType.TRACE;
|
||||||
|
Logger.Configure();
|
||||||
|
|
||||||
var options = new FileLoggerOptions();
|
var options = new FileLoggerOptions();
|
||||||
options.MaxRolloverFiles = 5;
|
options.MaxRolloverFiles = 5;
|
||||||
options.FileSizeLimit = 1 * 1024 * 1024 / 4;
|
//options.FileSizeLimit = 1 * 1024 * 1024 / 4;
|
||||||
options.UseLocalTime = true;
|
options.UseLocalTime = true;
|
||||||
builder.Logging.AddEonaCatFileLogger(fileLoggerOptions: options, filenamePrefix: "web");
|
builder.Logging.AddEonaCatFileLogger(fileLoggerOptions: options, filenamePrefix: "web");
|
||||||
|
|
||||||
@@ -61,10 +65,6 @@ builder.Services.AddMemoryCache();
|
|||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
Logger.UseLocalTime = true;
|
|
||||||
Logger.MaxLogType = ELogType.TRACE;
|
|
||||||
Logger.Configure();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
@@ -116,7 +116,7 @@ void RunLoggingExceptionTests()
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
logger.Write(exception);
|
logger.WriteAsync(exception).ConfigureAwait(false);
|
||||||
Console.WriteLine($"Normal ExceptionLogged: {i}");
|
Console.WriteLine($"Normal ExceptionLogged: {i}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,11 +124,11 @@ void RunLoggingExceptionTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Task.Run(RunWebLoggerTests);
|
Task.Run(RunWebLoggerTests).ConfigureAwait(false);
|
||||||
//Task.Run(RunWebLoggingTests);
|
Task.Run(RunWebLoggingTests).ConfigureAwait(false);
|
||||||
Task.Run(RunLoggingTests);
|
Task.Run(RunLoggingTests).ConfigureAwait(false);
|
||||||
//Task.Run(RunLoggingExceptionTests);
|
Task.Run(RunLoggingExceptionTests).ConfigureAwait(false);
|
||||||
//Task.Run(RunWebLoggingExceptionTests);
|
Task.Run(RunWebLoggingExceptionTests).ConfigureAwait(false);
|
||||||
|
|
||||||
void RunWebLoggingExceptionTests()
|
void RunWebLoggingExceptionTests()
|
||||||
{
|
{
|
||||||
@@ -153,14 +153,17 @@ void RunWebLoggingExceptionTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunWebLoggingTests()
|
async void RunWebLoggingTests()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(Logger.LogFolder)) Directory.CreateDirectory(Logger.LogFolder);
|
if (!Directory.Exists(Logger.LogFolder)) Directory.CreateDirectory(Logger.LogFolder);
|
||||||
|
|
||||||
for (var i = 0; i < 9000000; i++)
|
for (var i = 0; i < 9000000; i++)
|
||||||
{
|
{
|
||||||
app.Logger.LogInformation($"web-test {i}");
|
app.Logger.LogInformation($"web-test {i}");
|
||||||
File.AppendAllText(Path.Combine(Logger.LogFolder, "test.log"), $"WebLogged: {i}{Environment.NewLine}");
|
using (var file = new StreamWriter(Path.Combine(Logger.LogFolder, "test.log"), true))
|
||||||
|
{
|
||||||
|
await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
|
||||||
|
}
|
||||||
Console.WriteLine($"WebLogged: {i}");
|
Console.WriteLine($"WebLogged: {i}");
|
||||||
Task.Delay(1);
|
Task.Delay(1);
|
||||||
}
|
}
|
||||||
@@ -171,7 +174,7 @@ void RunLoggingTests()
|
|||||||
var loggerSettings = new LoggerSettings();
|
var loggerSettings = new LoggerSettings();
|
||||||
loggerSettings.UseLocalTime = true;
|
loggerSettings.UseLocalTime = true;
|
||||||
loggerSettings.FileLoggerOptions.UseLocalTime = true;
|
loggerSettings.FileLoggerOptions.UseLocalTime = true;
|
||||||
loggerSettings.MaxLogType = ELogType.INFO;
|
loggerSettings.MaxLogType = ELogType.DEBUG;
|
||||||
loggerSettings.FileLoggerOptions.FileSizeLimit = 1024 * 1024 * 1;
|
loggerSettings.FileLoggerOptions.FileSizeLimit = 1024 * 1024 * 1;
|
||||||
loggerSettings.FileLoggerOptions.FileNamePrefix = "AllTypes";
|
loggerSettings.FileLoggerOptions.FileNamePrefix = "AllTypes";
|
||||||
loggerSettings.FileLoggerOptions.MaxRolloverFiles = 5;
|
loggerSettings.FileLoggerOptions.MaxRolloverFiles = 5;
|
||||||
@@ -179,14 +182,14 @@ void RunLoggingTests()
|
|||||||
|
|
||||||
for (var i = 0; i < 9000000; i++)
|
for (var i = 0; i < 9000000; i++)
|
||||||
{
|
{
|
||||||
logger.Write($"test to file {i} INFO");
|
logger.WriteAsync($"test to file {i} INFO").ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} CRITICAL", ELogType.CRITICAL);
|
logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} DEBUG", ELogType.DEBUG);
|
logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} ERROR", ELogType.ERROR);
|
logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} TRACE", ELogType.TRACE);
|
logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} TRAFFIC", ELogType.TRAFFIC);
|
logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} WARNING", ELogType.WARNING);
|
logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
|
||||||
logger.Write($"test to file {i} NONE", ELogType.NONE);
|
logger.WriteAsync($"test to file {i} NONE", ELogType.NONE).ConfigureAwait(false);
|
||||||
Console.WriteLine($"Logged: {i}");
|
Console.WriteLine($"Logged: {i}");
|
||||||
Task.Delay(1);
|
Task.Delay(1);
|
||||||
}
|
}
|
||||||
@@ -194,16 +197,21 @@ void RunLoggingTests()
|
|||||||
|
|
||||||
void RunWebLoggerTests()
|
void RunWebLoggerTests()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 9000000; i++)
|
var i = 0;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
Logger.Log($"test via logger {i} INFO");
|
i++;
|
||||||
Logger.Log($"test via logger {i} CRITICAL", ELogType.CRITICAL);
|
Task.Run(() =>
|
||||||
Logger.Log($"test via logger {i} DEBUG", ELogType.DEBUG);
|
{
|
||||||
Logger.Log($"test via logger {i} ERROR", ELogType.ERROR);
|
Logger.LogAsync($"test via logger {i} INFO");
|
||||||
Logger.Log($"test via logger {i} TRACE", ELogType.TRACE);
|
Logger.LogAsync($"test via logger {i} CRITICAL", ELogType.CRITICAL);
|
||||||
Logger.Log($"test via logger {i} TRAFFIC", ELogType.TRAFFIC);
|
Logger.LogAsync($"test via logger {i} DEBUG", ELogType.DEBUG);
|
||||||
Logger.Log($"test via logger {i} WARNING", ELogType.WARNING);
|
Logger.LogAsync($"test via logger {i} ERROR", ELogType.ERROR);
|
||||||
Logger.Log($"test via logger {i} NONE", ELogType.NONE);
|
Logger.LogAsync($"test via logger {i} TRACE", ELogType.TRACE);
|
||||||
|
Logger.LogAsync($"test via logger {i} TRAFFIC", ELogType.TRAFFIC);
|
||||||
|
Logger.LogAsync($"test via logger {i} WARNING", ELogType.WARNING);
|
||||||
|
Logger.LogAsync($"test via logger {i} NONE", ELogType.NONE);
|
||||||
|
});
|
||||||
Console.WriteLine($"Logger: {i}");
|
Console.WriteLine($"Logger: {i}");
|
||||||
Task.Delay(1);
|
Task.Delay(1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user