Updated
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<TargetFrameworks>.netstandard2.1; net6.0; net7.0; net8.0; net4.8;</TargetFrameworks>
|
<TargetFrameworks>.netstandard2.1; net6.0; net7.0; net8.0; net4.8;</TargetFrameworks>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<FileVersion>1.2.9</FileVersion>
|
<FileVersion>1.3.0</FileVersion>
|
||||||
<Authors>EonaCat (Jeroen Saey)</Authors>
|
<Authors>EonaCat (Jeroen Saey)</Authors>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Company>EonaCat (Jeroen Saey)</Company>
|
<Company>EonaCat (Jeroen Saey)</Company>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<EVRevisionFormat>1.2.9+{chash:10}.{c:ymd}</EVRevisionFormat>
|
<EVRevisionFormat>1.3.0+{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>
|
||||||
|
|||||||
@@ -26,9 +26,16 @@ public static class FileLoggerFactoryExtensions
|
|||||||
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder, string filenamePrefix = null,
|
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder, string filenamePrefix = null,
|
||||||
FileLoggerOptions fileLoggerOptions = null)
|
FileLoggerOptions fileLoggerOptions = null)
|
||||||
{
|
{
|
||||||
if (fileLoggerOptions == null) fileLoggerOptions = new FileLoggerOptions();
|
if (fileLoggerOptions == null)
|
||||||
|
{
|
||||||
|
fileLoggerOptions = new FileLoggerOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(filenamePrefix))
|
||||||
|
{
|
||||||
|
fileLoggerOptions.FileNamePrefix = filenamePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(filenamePrefix)) fileLoggerOptions.FileNamePrefix = filenamePrefix;
|
|
||||||
builder.AddEonaCatFileLogger(options =>
|
builder.AddEonaCatFileLogger(options =>
|
||||||
{
|
{
|
||||||
options.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
options.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
||||||
@@ -55,7 +62,11 @@ public static class FileLoggerFactoryExtensions
|
|||||||
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder,
|
public static ILoggingBuilder AddEonaCatFileLogger(this ILoggingBuilder builder,
|
||||||
Action<FileLoggerOptions> configure)
|
Action<FileLoggerOptions> configure)
|
||||||
{
|
{
|
||||||
if (configure == null) throw new ArgumentNullException(nameof(configure));
|
if (configure == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configure));
|
||||||
|
}
|
||||||
|
|
||||||
builder.AddEonaCatFileLogger();
|
builder.AddEonaCatFileLogger();
|
||||||
builder.Services.Configure(configure);
|
builder.Services.Configure(configure);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ public class FileLoggerOptions : BatchingLoggerOptions
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(FileSizeLimit)} must be positive.");
|
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(FileSizeLimit)} must be positive.");
|
||||||
|
}
|
||||||
|
|
||||||
_fileSizeLimit = value;
|
_fileSizeLimit = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,8 +49,11 @@ public class FileLoggerOptions : BatchingLoggerOptions
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(value),
|
throw new ArgumentOutOfRangeException(nameof(value),
|
||||||
$"{nameof(RetainedFileCountLimit)} must be positive.");
|
$"{nameof(RetainedFileCountLimit)} must be positive.");
|
||||||
|
}
|
||||||
|
|
||||||
_retainedFileCountLimit = value;
|
_retainedFileCountLimit = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +80,10 @@ public class FileLoggerOptions : BatchingLoggerOptions
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(MaxRolloverFiles)} must be positive.");
|
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(MaxRolloverFiles)} must be positive.");
|
||||||
|
}
|
||||||
|
|
||||||
_maxRolloverFiles = value;
|
_maxRolloverFiles = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,12 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(_logFile);
|
var dir = Path.GetDirectoryName(_logFile);
|
||||||
if (!string.IsNullOrEmpty(dir))
|
if (!string.IsNullOrEmpty(dir))
|
||||||
|
{
|
||||||
if (!Directory.Exists(dir))
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
Directory.CreateDirectory(dir);
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +132,10 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
var completed = false;
|
var completed = false;
|
||||||
@@ -193,7 +200,10 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
{
|
{
|
||||||
var hasPrefix = !string.IsNullOrWhiteSpace(_fileNamePrefix);
|
var hasPrefix = !string.IsNullOrWhiteSpace(_fileNamePrefix);
|
||||||
if (hasPrefix)
|
if (hasPrefix)
|
||||||
|
{
|
||||||
return Path.Combine(_path, $"{_fileNamePrefix}_{group.Year:0000}{group.Month:00}{group.Day:00}.log");
|
return Path.Combine(_path, $"{_fileNamePrefix}_{group.Year:0000}{group.Month:00}{group.Day:00}.log");
|
||||||
|
}
|
||||||
|
|
||||||
return Path.Combine(_path, $"{group.Year:0000}{group.Month:00}{group.Day:00}.log");
|
return Path.Combine(_path, $"{group.Year:0000}{group.Month:00}{group.Day:00}.log");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +270,7 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
private async Task WriteEndMessageAsync(string logFilePath)
|
private async Task WriteEndMessageAsync(string logFilePath)
|
||||||
{
|
{
|
||||||
var stopMessage = LogHelper.GetStopMessage();
|
var stopMessage = LogHelper.GetStopMessage();
|
||||||
stopMessage = LogHelper.FormatMessageWithHeader(LoggerSettings, ELogType.INFO, stopMessage, CurrentDateTme);
|
stopMessage = LogHelper.FormatMessageWithHeader(LoggerSettings, ELogType.INFO, stopMessage, CurrentDateTme, Category);
|
||||||
|
|
||||||
using (var file = new StreamWriter(logFilePath, true))
|
using (var file = new StreamWriter(logFilePath, true))
|
||||||
{
|
{
|
||||||
@@ -292,13 +302,20 @@ public class FileLoggerProvider : BatchingLoggerProvider
|
|||||||
IEnumerable<FileInfo> files = null;
|
IEnumerable<FileInfo> files = null;
|
||||||
|
|
||||||
if (hasPrefix)
|
if (hasPrefix)
|
||||||
|
{
|
||||||
files = new DirectoryInfo(_path).GetFiles(_fileNamePrefix + "*");
|
files = new DirectoryInfo(_path).GetFiles(_fileNamePrefix + "*");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
files = new DirectoryInfo(_path).GetFiles("*");
|
files = new DirectoryInfo(_path).GetFiles("*");
|
||||||
|
}
|
||||||
|
|
||||||
files = files.OrderByDescending(file => file.Name).Skip(_maxRetainedFiles);
|
files = files.OrderByDescending(file => file.Name).Skip(_maxRetainedFiles);
|
||||||
|
|
||||||
foreach (var item in files) item.Delete();
|
foreach (var item in files)
|
||||||
|
{
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,67 +4,70 @@ using EonaCat.Logger.Extensions;
|
|||||||
using EonaCat.Logger.Managers;
|
using EonaCat.Logger.Managers;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace EonaCat.Logger.EonaCatCoreLogger.Internal;
|
namespace EonaCat.Logger.EonaCatCoreLogger.Internal
|
||||||
// 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.
|
|
||||||
|
|
||||||
public class BatchingLogger : ILogger
|
|
||||||
{
|
{
|
||||||
private readonly string _category;
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
||||||
private readonly BatchingLoggerProvider _provider;
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
||||||
private LoggerSettings _loggerSettings;
|
|
||||||
|
|
||||||
public BatchingLogger(BatchingLoggerProvider loggerProvider, string categoryName, LoggerSettings loggerSettings)
|
public class BatchingLogger : ILogger
|
||||||
{
|
{
|
||||||
_loggerSettings = loggerSettings;
|
private readonly string _category;
|
||||||
_provider = loggerProvider;
|
private readonly BatchingLoggerProvider _provider;
|
||||||
_category = categoryName;
|
private readonly LoggerSettings _loggerSettings;
|
||||||
}
|
|
||||||
|
|
||||||
private DateTimeOffset CurrentDateTimeOffset =>
|
public BatchingLogger(BatchingLoggerProvider loggerProvider, string categoryName, LoggerSettings loggerSettings)
|
||||||
_loggerSettings.UseLocalTime ? DateTimeOffset.Now : DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
private DateTime CurrentDateTme => _loggerSettings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
|
||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEnabled(LogLevel logLevel)
|
|
||||||
{
|
|
||||||
return logLevel != LogLevel.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
|
|
||||||
Func<TState, Exception, string> formatter)
|
|
||||||
{
|
|
||||||
Log(CurrentDateTimeOffset, logLevel, eventId, state, exception, formatter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log<TState>(DateTimeOffset timestamp, LogLevel logLevel, EventId eventId, TState state,
|
|
||||||
Exception exception, Func<TState, Exception, string> formatter)
|
|
||||||
{
|
|
||||||
if (!IsEnabled(logLevel)) return;
|
|
||||||
|
|
||||||
if (_loggerSettings == null) _loggerSettings = new LoggerSettings();
|
|
||||||
|
|
||||||
var message = LogHelper.FormatMessageWithHeader(_loggerSettings, logLevel.FromLogLevel(),
|
|
||||||
formatter(state, exception), timestamp.DateTime) + Environment.NewLine;
|
|
||||||
if (exception != null) message = exception.FormatExceptionToMessage() + Environment.NewLine;
|
|
||||||
|
|
||||||
_provider.AddMessage(timestamp, message);
|
|
||||||
|
|
||||||
var currentMessage = new EonaCatLogMessage
|
|
||||||
{
|
{
|
||||||
DateTime = timestamp.DateTime,
|
_provider = loggerProvider ?? throw new ArgumentNullException(nameof(loggerProvider));
|
||||||
Message = message,
|
_category = categoryName ?? throw new ArgumentNullException(nameof(categoryName));
|
||||||
LogType = logLevel.FromLogLevel()
|
_loggerSettings = loggerSettings ?? throw new ArgumentNullException(nameof(loggerSettings));
|
||||||
};
|
}
|
||||||
|
|
||||||
currentMessage.Origin = string.IsNullOrWhiteSpace(_loggerSettings.LogOrigin)
|
private DateTimeOffset CurrentDateTimeOffset => CurrentDateTime;
|
||||||
? "BatchingLogger"
|
|
||||||
: _loggerSettings.LogOrigin;
|
private DateTime CurrentDateTime => _loggerSettings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
||||||
_loggerSettings?.OnLogEvent(currentMessage);
|
|
||||||
|
public IDisposable BeginScope<TState>(TState state) => null;
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
|
||||||
|
|
||||||
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
|
||||||
|
Func<TState, Exception, string> formatter)
|
||||||
|
{
|
||||||
|
if (!IsEnabled(logLevel))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = CurrentDateTimeOffset;
|
||||||
|
Log(timestamp, logLevel, eventId, state, exception, formatter, _category);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log<TState>(DateTimeOffset timestamp, LogLevel logLevel, EventId eventId, TState state,
|
||||||
|
Exception exception, Func<TState, Exception, string> formatter, string category)
|
||||||
|
{
|
||||||
|
if (!IsEnabled(logLevel))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string message = exception != null
|
||||||
|
? exception.FormatExceptionToMessage() + Environment.NewLine
|
||||||
|
: formatter(state, exception);
|
||||||
|
|
||||||
|
message = LogHelper.FormatMessageWithHeader(_loggerSettings, logLevel.FromLogLevel(), message, timestamp.DateTime, category)
|
||||||
|
+ Environment.NewLine;
|
||||||
|
|
||||||
|
_provider.AddMessage(timestamp, message);
|
||||||
|
|
||||||
|
var currentMessage = new EonaCatLogMessage
|
||||||
|
{
|
||||||
|
DateTime = timestamp.DateTime,
|
||||||
|
Message = message,
|
||||||
|
LogType = logLevel.FromLogLevel(),
|
||||||
|
Origin = string.IsNullOrWhiteSpace(_loggerSettings.LogOrigin) ? "BatchingLogger" : _loggerSettings.LogOrigin
|
||||||
|
};
|
||||||
|
|
||||||
|
_loggerSettings.OnLogEvent(currentMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,10 @@ public class BatchingLoggerOptions
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value <= TimeSpan.Zero)
|
if (value <= TimeSpan.Zero)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(FlushPeriod)} must be positive.");
|
throw new ArgumentOutOfRangeException(nameof(value), $"{nameof(FlushPeriod)} must be positive.");
|
||||||
|
}
|
||||||
|
|
||||||
_flushPeriod = value;
|
_flushPeriod = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,16 +23,23 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
private Task _outputTask;
|
private Task _outputTask;
|
||||||
private object _writeLock = new object();
|
private object _writeLock = new object();
|
||||||
private bool _isDisposing;
|
private bool _isDisposing;
|
||||||
|
protected string Category;
|
||||||
|
|
||||||
protected BatchingLoggerProvider(IOptions<BatchingLoggerOptions> options)
|
protected BatchingLoggerProvider(IOptions<BatchingLoggerOptions> options)
|
||||||
{
|
{
|
||||||
var loggerOptions = options.Value;
|
var loggerOptions = options.Value;
|
||||||
|
|
||||||
if (loggerOptions.FlushPeriod <= TimeSpan.Zero)
|
if (loggerOptions.FlushPeriod <= TimeSpan.Zero)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(loggerOptions.FlushPeriod),
|
throw new ArgumentOutOfRangeException(nameof(loggerOptions.FlushPeriod),
|
||||||
$"{nameof(loggerOptions.FlushPeriod)} must be longer than zero.");
|
$"{nameof(loggerOptions.FlushPeriod)} must be longer than zero.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.Value is FileLoggerOptions fileLoggerOptions)
|
||||||
|
{
|
||||||
|
UseLocalTime = fileLoggerOptions.UseLocalTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.Value is FileLoggerOptions fileLoggerOptions) UseLocalTime = fileLoggerOptions.UseLocalTime;
|
|
||||||
_batchSize = loggerOptions.BatchSize;
|
_batchSize = loggerOptions.BatchSize;
|
||||||
|
|
||||||
StartAsync().ConfigureAwait(false);
|
StartAsync().ConfigureAwait(false);
|
||||||
@@ -47,7 +54,10 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_loggerSettings != null) return _loggerSettings;
|
if (_loggerSettings != null)
|
||||||
|
{
|
||||||
|
return _loggerSettings;
|
||||||
|
}
|
||||||
|
|
||||||
_loggerSettings = new LoggerSettings();
|
_loggerSettings = new LoggerSettings();
|
||||||
_loggerSettings.UseLocalTime = UseLocalTime;
|
_loggerSettings.UseLocalTime = UseLocalTime;
|
||||||
@@ -73,6 +83,7 @@ public abstract class BatchingLoggerProvider : ILoggerProvider, IDisposable
|
|||||||
|
|
||||||
public ILogger CreateLogger(string categoryName)
|
public ILogger CreateLogger(string categoryName)
|
||||||
{
|
{
|
||||||
|
Category = categoryName;
|
||||||
return new BatchingLogger(this, categoryName, LoggerSettings);
|
return new BatchingLogger(this, categoryName, LoggerSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ public static class ExceptionExtensions
|
|||||||
public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
|
public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
|
||||||
{
|
{
|
||||||
if (exception == null)
|
if (exception == null)
|
||||||
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
var st = new StackTrace(exception, true);
|
var st = new StackTrace(exception, true);
|
||||||
var frame = st.GetFrame(0);
|
var frame = st.GetFrame(0);
|
||||||
@@ -28,9 +30,15 @@ public static class ExceptionExtensions
|
|||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
sb.AppendLine("--- Exception details provided by EonaCatLogger ---");
|
sb.AppendLine("--- Exception details provided by EonaCatLogger ---");
|
||||||
if (!string.IsNullOrEmpty(module))
|
if (!string.IsNullOrEmpty(module))
|
||||||
|
{
|
||||||
sb.AppendLine(" Module : " + module);
|
sb.AppendLine(" Module : " + module);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(method))
|
if (!string.IsNullOrEmpty(method))
|
||||||
|
{
|
||||||
sb.AppendLine(" Method : " + method);
|
sb.AppendLine(" Method : " + method);
|
||||||
|
}
|
||||||
|
|
||||||
sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
|
sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
|
||||||
sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
|
sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
|
||||||
? FormatExceptionData(exception.Data)
|
? FormatExceptionData(exception.Data)
|
||||||
@@ -54,10 +62,12 @@ public static class ExceptionExtensions
|
|||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
foreach (DictionaryEntry entry in data)
|
foreach (DictionaryEntry entry in data)
|
||||||
|
{
|
||||||
sb.Append(" | ")
|
sb.Append(" | ")
|
||||||
.Append(entry.Key)
|
.Append(entry.Key)
|
||||||
.Append(": ")
|
.Append(": ")
|
||||||
.AppendLine(entry.Value.ToString());
|
.AppendLine(entry.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,26 @@ public class OffsetStream : Stream
|
|||||||
{
|
{
|
||||||
if (stream.CanSeek)
|
if (stream.CanSeek)
|
||||||
{
|
{
|
||||||
if (offset > stream.Length) throw new EndOfStreamException();
|
if (offset > stream.Length)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
|
||||||
BaseStreamOffset = offset;
|
BaseStreamOffset = offset;
|
||||||
|
|
||||||
if (length > stream.Length - offset) throw new EndOfStreamException();
|
if (length > stream.Length - offset)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
|
{
|
||||||
Length1 = stream.Length - offset;
|
Length1 = stream.Length - offset;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Length1 = length;
|
Length1 = length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -49,9 +59,15 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value > Length1) throw new EndOfStreamException();
|
if (value > Length1)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
|
||||||
if (!BaseStream.CanSeek) throw new NotSupportedException("Cannot seek stream.");
|
if (!BaseStream.CanSeek)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Cannot seek stream.");
|
||||||
|
}
|
||||||
|
|
||||||
Position1 = value;
|
Position1 = value;
|
||||||
}
|
}
|
||||||
@@ -71,11 +87,18 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (Disposed) return;
|
if (Disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
{
|
||||||
if (OwnStream & (BaseStream != null))
|
if (OwnStream & (BaseStream != null))
|
||||||
|
{
|
||||||
BaseStream.Dispose();
|
BaseStream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
@@ -84,20 +107,35 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
public override void Flush()
|
public override void Flush()
|
||||||
{
|
{
|
||||||
if (ReadOnly) throw new IOException("OffsetStream is read only.");
|
if (ReadOnly)
|
||||||
|
{
|
||||||
|
throw new IOException("OffsetStream is read only.");
|
||||||
|
}
|
||||||
|
|
||||||
BaseStream.Flush();
|
BaseStream.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (count < 1) throw new ArgumentOutOfRangeException("Count cannot be less than 1.");
|
if (count < 1)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Count cannot be less than 1.");
|
||||||
|
}
|
||||||
|
|
||||||
if (Position1 >= Length1) return 0;
|
if (Position1 >= Length1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (count > Length1 - Position1) count = Convert.ToInt32(Length1 - Position1);
|
if (count > Length1 - Position1)
|
||||||
|
{
|
||||||
|
count = Convert.ToInt32(Length1 - Position1);
|
||||||
|
}
|
||||||
|
|
||||||
if (BaseStream.CanSeek) BaseStream.Position = BaseStreamOffset + Position1;
|
if (BaseStream.CanSeek)
|
||||||
|
{
|
||||||
|
BaseStream.Position = BaseStreamOffset + Position1;
|
||||||
|
}
|
||||||
|
|
||||||
var bytesRead = BaseStream.Read(buffer, offset, count);
|
var bytesRead = BaseStream.Read(buffer, offset, count);
|
||||||
Position1 += bytesRead;
|
Position1 += bytesRead;
|
||||||
@@ -107,7 +145,10 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
if (!BaseStream.CanSeek) throw new IOException("Stream is not seekable.");
|
if (!BaseStream.CanSeek)
|
||||||
|
{
|
||||||
|
throw new IOException("Stream is not seekable.");
|
||||||
|
}
|
||||||
|
|
||||||
long pos;
|
long pos;
|
||||||
|
|
||||||
@@ -130,7 +171,10 @@ public class OffsetStream : Stream
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos < 0 || pos >= Length1) throw new EndOfStreamException("OffsetStream reached begining/end of stream.");
|
if (pos < 0 || pos >= Length1)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException("OffsetStream reached begining/end of stream.");
|
||||||
|
}
|
||||||
|
|
||||||
Position1 = pos;
|
Position1 = pos;
|
||||||
|
|
||||||
@@ -139,7 +183,10 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
public override void SetLength(long value)
|
public override void SetLength(long value)
|
||||||
{
|
{
|
||||||
if (ReadOnly) throw new IOException("OffsetStream is read only.");
|
if (ReadOnly)
|
||||||
|
{
|
||||||
|
throw new IOException("OffsetStream is read only.");
|
||||||
|
}
|
||||||
|
|
||||||
BaseStream.SetLength(BaseStreamOffset + value);
|
BaseStream.SetLength(BaseStreamOffset + value);
|
||||||
Length1 = value;
|
Length1 = value;
|
||||||
@@ -147,15 +194,27 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (ReadOnly) throw new IOException("OffsetStream is read only.");
|
if (ReadOnly)
|
||||||
|
{
|
||||||
|
throw new IOException("OffsetStream is read only.");
|
||||||
|
}
|
||||||
|
|
||||||
if (count < 1) return;
|
if (count < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var pos = Position1 + count;
|
var pos = Position1 + count;
|
||||||
|
|
||||||
if (pos > Length1) throw new EndOfStreamException("OffsetStream reached end of stream.");
|
if (pos > Length1)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException("OffsetStream reached end of stream.");
|
||||||
|
}
|
||||||
|
|
||||||
if (BaseStream.CanSeek) BaseStream.Position = BaseStreamOffset + Position1;
|
if (BaseStream.CanSeek)
|
||||||
|
{
|
||||||
|
BaseStream.Position = BaseStreamOffset + Position1;
|
||||||
|
}
|
||||||
|
|
||||||
BaseStream.Write(buffer, offset, count);
|
BaseStream.Write(buffer, offset, count);
|
||||||
Position1 = pos;
|
Position1 = pos;
|
||||||
@@ -175,9 +234,15 @@ public class OffsetStream : Stream
|
|||||||
|
|
||||||
public void WriteTo(Stream stream, int bufferSize)
|
public void WriteTo(Stream stream, int bufferSize)
|
||||||
{
|
{
|
||||||
if (!BaseStream.CanSeek) throw new IOException("Stream is not seekable.");
|
if (!BaseStream.CanSeek)
|
||||||
|
{
|
||||||
|
throw new IOException("Stream is not seekable.");
|
||||||
|
}
|
||||||
|
|
||||||
if (Length1 < bufferSize) bufferSize = Convert.ToInt32(Length1);
|
if (Length1 < bufferSize)
|
||||||
|
{
|
||||||
|
bufferSize = Convert.ToInt32(Length1);
|
||||||
|
}
|
||||||
|
|
||||||
var previousPosition = Position1;
|
var previousPosition = Position1;
|
||||||
Position1 = 0;
|
Position1 = 0;
|
||||||
|
|||||||
@@ -42,7 +42,11 @@ public class GrayLogServer
|
|||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(Hostname));
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(Hostname));
|
||||||
|
}
|
||||||
|
|
||||||
_Hostname = value;
|
_Hostname = value;
|
||||||
|
|
||||||
SetUdp();
|
SetUdp();
|
||||||
@@ -57,7 +61,11 @@ public class GrayLogServer
|
|||||||
get => _Port;
|
get => _Port;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value < 0) throw new ArgumentException("Port must be zero or greater.");
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Port must be zero or greater.");
|
||||||
|
}
|
||||||
|
|
||||||
_Port = value;
|
_Port = value;
|
||||||
|
|
||||||
SetUdp();
|
SetUdp();
|
||||||
|
|||||||
@@ -80,10 +80,15 @@ public static class ColorHelper
|
|||||||
|
|
||||||
public static int HexColorToArgb(string htmlColor, bool requireHexSpecified = false, int defaultAlpha = 0xFF)
|
public static int HexColorToArgb(string htmlColor, bool requireHexSpecified = false, int defaultAlpha = 0xFF)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(htmlColor)) throw new ArgumentNullException(nameof(htmlColor));
|
if (string.IsNullOrEmpty(htmlColor))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(htmlColor));
|
||||||
|
}
|
||||||
|
|
||||||
if (!htmlColor.StartsWith("#") && requireHexSpecified)
|
if (!htmlColor.StartsWith("#") && requireHexSpecified)
|
||||||
|
{
|
||||||
throw new ArgumentException($"Provided parameter '{htmlColor}' is not valid");
|
throw new ArgumentException($"Provided parameter '{htmlColor}' is not valid");
|
||||||
|
}
|
||||||
|
|
||||||
htmlColor = htmlColor.TrimStart('#');
|
htmlColor = htmlColor.TrimStart('#');
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,17 @@ internal static class LogHelper
|
|||||||
internal static event EventHandler<ErrorMessage> OnException;
|
internal static event EventHandler<ErrorMessage> OnException;
|
||||||
|
|
||||||
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
|
internal static string FormatMessageWithHeader(LoggerSettings settings, ELogType logType, string currentMessage,
|
||||||
DateTime dateTime)
|
DateTime dateTime, string category = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(currentMessage))
|
if (string.IsNullOrWhiteSpace(currentMessage))
|
||||||
|
{
|
||||||
return currentMessage;
|
return currentMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(category))
|
||||||
|
{
|
||||||
|
category = "General";
|
||||||
|
}
|
||||||
|
|
||||||
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
|
var sb = new StringBuilder(settings?.HeaderFormat ?? "[EonaCatLogger]");
|
||||||
|
|
||||||
@@ -37,11 +44,14 @@ internal static class LogHelper
|
|||||||
dateTime.ToString(settings?.TimestampFormat ?? "yyyy-MM-dd HH:mm:ss") + " " +
|
dateTime.ToString(settings?.TimestampFormat ?? "yyyy-MM-dd HH:mm:ss") + " " +
|
||||||
(settings?.UseLocalTime ?? false ? "[LOCAL]" : "[UTC]"))
|
(settings?.UseLocalTime ?? false ? "[LOCAL]" : "[UTC]"))
|
||||||
.Replace("{host}", $"[Host:{Dns.GetHostName()}]")
|
.Replace("{host}", $"[Host:{Dns.GetHostName()}]")
|
||||||
|
.Replace("{category}", $"[Category:{category}]")
|
||||||
.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId}]")
|
.Replace("{thread}", $"[ThreadId:{Environment.CurrentManagedThreadId}]")
|
||||||
.Replace("{sev}", $"[{logType}]");
|
.Replace("{sev}", $"[{logType}]");
|
||||||
|
|
||||||
if (!settings?.RemoveMessagePrefix ?? (false && !currentMessage.Contains("[EonaCatLogger]")))
|
if (!settings?.RemoveMessagePrefix ?? (false && !currentMessage.Contains("[EonaCatLogger]")))
|
||||||
|
{
|
||||||
sb.Insert(0, "[EonaCatLogger] ");
|
sb.Insert(0, "[EonaCatLogger] ");
|
||||||
|
}
|
||||||
|
|
||||||
sb.Append(" ").Append(currentMessage);
|
sb.Append(" ").Append(currentMessage);
|
||||||
|
|
||||||
@@ -51,7 +61,9 @@ internal static class LogHelper
|
|||||||
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole)
|
internal static void SendToConsole(LoggerSettings settings, ELogType logType, string message, bool writeToConsole)
|
||||||
{
|
{
|
||||||
if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message))
|
if (settings == null || !writeToConsole || string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (settings.EnableColors && settings.Colors != null)
|
if (settings.EnableColors && settings.Colors != null)
|
||||||
{
|
{
|
||||||
@@ -109,7 +121,10 @@ internal static class LogHelper
|
|||||||
internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message)
|
internal static void SendToFile(ILogger logger, LoggerSettings settings, ELogType logType, string message)
|
||||||
{
|
{
|
||||||
if (logger == null || settings == null || !settings.EnableFileLogging ||
|
if (logger == null || settings == null || !settings.EnableFileLogging ||
|
||||||
string.IsNullOrWhiteSpace(message)) return;
|
string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var logLevel = logType.ToLogLevel();
|
var logLevel = logType.ToLogLevel();
|
||||||
if (IsLogLevelEnabled(settings, logType))
|
if (IsLogLevelEnabled(settings, logType))
|
||||||
@@ -132,9 +147,14 @@ internal static class LogHelper
|
|||||||
bool sendToSplunkServer)
|
bool sendToSplunkServer)
|
||||||
{
|
{
|
||||||
if (settings == null || !sendToSplunkServer || splunkPayload == null)
|
if (settings == null || !sendToSplunkServer || splunkPayload == null)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (settings.SplunkServers == null) settings.SplunkServers = new List<SplunkServer.SplunkServer>();
|
if (settings.SplunkServers == null)
|
||||||
|
{
|
||||||
|
settings.SplunkServers = new List<SplunkServer.SplunkServer>();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var splunkServer in settings.SplunkServers)
|
foreach (var splunkServer in settings.SplunkServers)
|
||||||
{
|
{
|
||||||
@@ -154,12 +174,14 @@ internal static class LogHelper
|
|||||||
var response = await splunkServer.SendAsync(splunkPayload);
|
var response = await splunkServer.SendAsync(splunkPayload);
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
OnException?.Invoke(null,
|
OnException?.Invoke(null,
|
||||||
new ErrorMessage
|
new ErrorMessage
|
||||||
{
|
{
|
||||||
Message =
|
Message =
|
||||||
$"Failed to send log to Splunk '{splunkServer.SplunkHecUrl}'. Status code: {response.StatusCode}"
|
$"Failed to send log to Splunk '{splunkServer.SplunkHecUrl}'. Status code: {response.StatusCode}"
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@@ -178,7 +200,9 @@ internal static class LogHelper
|
|||||||
bool sendToSplunkServer)
|
bool sendToSplunkServer)
|
||||||
{
|
{
|
||||||
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
|
if (settings == null || !sendToSplunkServer || string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var splunkPayload = new SplunkPayload
|
var splunkPayload = new SplunkPayload
|
||||||
{
|
{
|
||||||
@@ -194,9 +218,12 @@ internal static class LogHelper
|
|||||||
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
|
string facility, string source, bool sendToGrayLogServer, string version = "1.1")
|
||||||
{
|
{
|
||||||
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
|
if (settings == null || !sendToGrayLogServer || string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var grayLogServer in settings.GrayLogServers ?? new List<GrayLogServer> { new("127.0.0.1") })
|
foreach (var grayLogServer in settings.GrayLogServers ?? new List<GrayLogServer> { new("127.0.0.1") })
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var gelfMessage = new
|
var gelfMessage = new
|
||||||
@@ -223,15 +250,19 @@ internal static class LogHelper
|
|||||||
$"Error while logging to GrayLog Server '{grayLogServer.Hostname}': {exception.Message}"
|
$"Error while logging to GrayLog Server '{grayLogServer.Hostname}': {exception.Message}"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message,
|
internal static async Task SendToSysLogServersAsync(LoggerSettings settings, string message,
|
||||||
bool sendToSyslogServers)
|
bool sendToSyslogServers)
|
||||||
{
|
{
|
||||||
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
|
if (settings == null || !sendToSyslogServers || string.IsNullOrWhiteSpace(message))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var server in settings.SysLogServers ?? new List<SyslogServer> { new("127.0.0.1") })
|
foreach (var server in settings.SysLogServers ?? new List<SyslogServer> { new("127.0.0.1") })
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(server.Hostname))
|
if (string.IsNullOrWhiteSpace(server.Hostname))
|
||||||
@@ -260,6 +291,7 @@ internal static class LogHelper
|
|||||||
Message = $"Error while logging to SysLog Server '{server.Hostname}': {exception.Message}"
|
Message = $"Error while logging to SysLog Server '{server.Hostname}': {exception.Message}"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetStartupMessage()
|
internal static string GetStartupMessage()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -11,274 +12,309 @@ using EonaCat.Logger.Syslog;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace EonaCat.Logger.Managers;
|
namespace EonaCat.Logger.Managers
|
||||||
// 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.
|
|
||||||
|
|
||||||
public class LogManager : ILogManager, IDisposable
|
|
||||||
{
|
{
|
||||||
private static LogManager _instance;
|
// 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.
|
||||||
|
|
||||||
private readonly CancellationTokenSource _tokenSource = new();
|
public class LogManager : ILogManager, IDisposable
|
||||||
private DateTime _logDate;
|
|
||||||
private bool _isDisposing;
|
|
||||||
|
|
||||||
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(serverIp))
|
private static readonly Lazy<LogManager> _instance = new(() => new LogManager(CreateDefaultSettings()));
|
||||||
throw new ArgumentNullException(nameof(serverIp));
|
private readonly CancellationTokenSource _tokenSource = new();
|
||||||
|
private DateTime _logDate;
|
||||||
|
private bool _isDisposing;
|
||||||
|
private string _category;
|
||||||
|
|
||||||
if (serverPort < 0)
|
public LogManager(LoggerSettings settings, string serverIp, int serverPort)
|
||||||
throw new ArgumentException("Server port must be zero or greater.");
|
|
||||||
|
|
||||||
settings.SysLogServers = new List<SyslogServer>
|
|
||||||
{
|
{
|
||||||
new(serverIp, serverPort)
|
if (string.IsNullOrEmpty(serverIp))
|
||||||
};
|
|
||||||
|
|
||||||
Settings = settings;
|
|
||||||
SetupLogManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogManager(LoggerSettings settings)
|
|
||||||
{
|
|
||||||
Settings = settings;
|
|
||||||
SetupFileLogger(settings);
|
|
||||||
SetupLogManager();
|
|
||||||
LogHelper.OnException += LogHelper_OnException;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DateTime CurrentDateTme => Settings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
|
||||||
public ILoggerProvider LoggerProvider { get; private set; }
|
|
||||||
public ILoggerFactory LoggerFactory { get; private set; }
|
|
||||||
public ILogger Logger { get; private set; }
|
|
||||||
|
|
||||||
public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider
|
|
||||||
? fileLoggerProvider.LogFile
|
|
||||||
: string.Empty;
|
|
||||||
|
|
||||||
public bool IsRunning { get; private set; }
|
|
||||||
|
|
||||||
public static LogManager Instance => InstanceInit();
|
|
||||||
|
|
||||||
public LoggerSettings Settings { get; set; } = CreateDefaultSettings();
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
DisposeAsync(true).GetAwaiter().GetResult();
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
|
||||||
bool criticalException = false,
|
|
||||||
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
|
||||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
|
||||||
{
|
|
||||||
if (exception == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
|
||||||
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
|
||||||
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
|
||||||
grayLogVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
|
||||||
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
|
||||||
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
|
||||||
string grayLogVersion = "1.1")
|
|
||||||
{
|
|
||||||
if (logType == ELogType.NONE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await InternalWriteAsync(CurrentDateTme, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
|
||||||
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler<ErrorMessage> OnException;
|
|
||||||
|
|
||||||
private static LogManager InstanceInit()
|
|
||||||
{
|
|
||||||
if (_instance == null) _instance = new LogManager(CreateDefaultSettings());
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LoggerSettings CreateDefaultSettings()
|
|
||||||
{
|
|
||||||
var settings = new LoggerSettings();
|
|
||||||
settings.Id = "EonaCatLogger";
|
|
||||||
settings.MaxLogType = ELogType.INFO;
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual async Task DisposeAsync(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
_isDisposing = true;
|
|
||||||
await StopLoggingAsync().ConfigureAwait(false);
|
|
||||||
await Task.Delay(100).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StartNewLogAsync()
|
|
||||||
{
|
|
||||||
if (_tokenSource.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
if (IsRunning && CurrentDateTme.Date > _logDate.Date)
|
|
||||||
{
|
|
||||||
await StopLoggingAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
IsRunning = true;
|
|
||||||
|
|
||||||
CreateLogger();
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
|
||||||
|
|
||||||
_logDate = CurrentDateTme;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateLogger()
|
|
||||||
{
|
|
||||||
// Dispose of previous ServiceProvider if it exists
|
|
||||||
LoggerProvider?.Dispose();
|
|
||||||
LoggerFactory?.Dispose();
|
|
||||||
|
|
||||||
IServiceCollection serviceCollection = new ServiceCollection();
|
|
||||||
serviceCollection.AddLogging(builder => builder.SetMinimumLevel(Settings.MaxLogType.ToLogLevel())
|
|
||||||
.AddEonaCatFileLogger(configuration =>
|
|
||||||
{
|
{
|
||||||
var fileLoggerOptions = Settings.FileLoggerOptions;
|
throw new ArgumentNullException(nameof(serverIp));
|
||||||
configuration.MaxWriteTries = fileLoggerOptions.MaxWriteTries;
|
}
|
||||||
configuration.RetainedFileCountLimit = fileLoggerOptions.RetainedFileCountLimit;
|
|
||||||
configuration.FlushPeriod = fileLoggerOptions.FlushPeriod;
|
|
||||||
configuration.IsEnabled = fileLoggerOptions.IsEnabled;
|
|
||||||
configuration.BatchSize = fileLoggerOptions.BatchSize;
|
|
||||||
configuration.FileSizeLimit = fileLoggerOptions.FileSizeLimit;
|
|
||||||
configuration.LogDirectory = fileLoggerOptions.LogDirectory;
|
|
||||||
configuration.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
|
||||||
configuration.MaxRolloverFiles = fileLoggerOptions.MaxRolloverFiles;
|
|
||||||
configuration.UseLocalTime = Settings.UseLocalTime;
|
|
||||||
}));
|
|
||||||
|
|
||||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
if (serverPort < 0)
|
||||||
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
{
|
||||||
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
throw new ArgumentException("Server port must be zero or greater.");
|
||||||
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
}
|
||||||
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
settings.SysLogServers = new List<SyslogServer>
|
||||||
|
{
|
||||||
|
new(serverIp, serverPort)
|
||||||
|
};
|
||||||
|
|
||||||
private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO,
|
Settings = settings;
|
||||||
bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null,
|
SetupLogManager();
|
||||||
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
|
||||||
string grayLogSource = null, string grayLogVersion = "1.1")
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE ||
|
|
||||||
(int)logType > (int)Settings.MaxLogType) return;
|
|
||||||
|
|
||||||
if (_isDisposing)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsRunning)
|
public LogManager(LoggerSettings settings, string category = null)
|
||||||
{
|
{
|
||||||
await StartNewLogAsync().ConfigureAwait(false);
|
_category = category;
|
||||||
|
if (string.IsNullOrWhiteSpace(category))
|
||||||
|
{
|
||||||
|
_category = "General";
|
||||||
|
}
|
||||||
|
Settings = settings;
|
||||||
|
SetupFileLogger(settings);
|
||||||
|
SetupLogManager();
|
||||||
|
LogHelper.OnException += LogHelper_OnException;
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime);
|
private DateTime CurrentDateTime => Settings.UseLocalTime ? DateTime.Now : DateTime.UtcNow;
|
||||||
var writeToConsoleValue = writeToConsole ?? Settings.EnableConsole;
|
public ILoggerProvider LoggerProvider { get; private set; }
|
||||||
var sendToSyslogServersValue = sendToSyslogServers ?? Settings.SendToSyslogServers;
|
public ILoggerFactory LoggerFactory { get; private set; }
|
||||||
var sendToSplunkServersValue = sendToSplunkServers ?? Settings.SendToSplunkServers;
|
public ILogger Logger { get; private set; }
|
||||||
var sendToGrayLogServersValue = sendToGrayLogServers ?? Settings.SendToGrayLogServers;
|
|
||||||
|
|
||||||
LogHelper.SendToFile(Logger, Settings, logType, message);
|
public string CurrentLogFile => LoggerProvider is FileLoggerProvider fileLoggerProvider
|
||||||
|
? fileLoggerProvider.LogFile
|
||||||
|
: string.Empty;
|
||||||
|
|
||||||
if (writeToConsoleValue) LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
if (sendToSyslogServersValue || sendToSplunkServersValue || sendToGrayLogServersValue)
|
public static LogManager Instance => _instance.Value;
|
||||||
await Task.Run(async () =>
|
|
||||||
|
public LoggerSettings Settings { get; set; } = CreateDefaultSettings();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DisposeAsync(true).GetAwaiter().GetResult();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsync(Exception exception, string module = null, string method = null,
|
||||||
|
bool criticalException = false,
|
||||||
|
bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null,
|
||||||
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
|
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||||
|
{
|
||||||
|
if (exception == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await WriteAsync(exception.FormatExceptionToMessage(module, method),
|
||||||
|
criticalException ? ELogType.CRITICAL : ELogType.ERROR, writeToConsole, sendToSysLogServers,
|
||||||
|
sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource,
|
||||||
|
grayLogVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task WriteAsync(string message, ELogType logType = ELogType.INFO, bool? writeToConsole = null,
|
||||||
|
bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string customSplunkSourceType = null,
|
||||||
|
bool? sendToGrayLogServers = null, string grayLogFacility = null, string grayLogSource = null,
|
||||||
|
string grayLogVersion = "1.1")
|
||||||
|
{
|
||||||
|
if (logType == ELogType.NONE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await InternalWriteAsync(CurrentDateTime, message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers,
|
||||||
|
customSplunkSourceType, sendToGrayLogServers, grayLogFacility, grayLogSource, grayLogVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<ErrorMessage> OnException;
|
||||||
|
|
||||||
|
private static LoggerSettings CreateDefaultSettings()
|
||||||
|
{
|
||||||
|
var settings = new LoggerSettings
|
||||||
|
{
|
||||||
|
Id = "EonaCatLogger",
|
||||||
|
MaxLogType = ELogType.INFO
|
||||||
|
};
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual async Task DisposeAsync(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_isDisposing = true;
|
||||||
|
await StopLoggingAsync();
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartNewLogAsync()
|
||||||
|
{
|
||||||
|
if (_tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsRunning && CurrentDateTime.Date > _logDate.Date)
|
||||||
|
{
|
||||||
|
await StopLoggingAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
IsRunning = true;
|
||||||
|
|
||||||
|
CreateLogger();
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Settings.FileLoggerOptions.LogDirectory);
|
||||||
|
|
||||||
|
_logDate = CurrentDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLogger()
|
||||||
|
{
|
||||||
|
// Dispose of previous ServiceProvider if it exists
|
||||||
|
LoggerProvider?.Dispose();
|
||||||
|
LoggerFactory?.Dispose();
|
||||||
|
|
||||||
|
IServiceCollection serviceCollection = new ServiceCollection();
|
||||||
|
serviceCollection.AddLogging(builder => builder.SetMinimumLevel(Settings.MaxLogType.ToLogLevel())
|
||||||
|
.AddEonaCatFileLogger(configuration =>
|
||||||
|
{
|
||||||
|
var fileLoggerOptions = Settings.FileLoggerOptions;
|
||||||
|
configuration.MaxWriteTries = fileLoggerOptions.MaxWriteTries;
|
||||||
|
configuration.RetainedFileCountLimit = fileLoggerOptions.RetainedFileCountLimit;
|
||||||
|
configuration.FlushPeriod = fileLoggerOptions.FlushPeriod;
|
||||||
|
configuration.IsEnabled = fileLoggerOptions.IsEnabled;
|
||||||
|
configuration.BatchSize = fileLoggerOptions.BatchSize;
|
||||||
|
configuration.FileSizeLimit = fileLoggerOptions.FileSizeLimit;
|
||||||
|
configuration.LogDirectory = fileLoggerOptions.LogDirectory;
|
||||||
|
configuration.FileNamePrefix = fileLoggerOptions.FileNamePrefix;
|
||||||
|
configuration.MaxRolloverFiles = fileLoggerOptions.MaxRolloverFiles;
|
||||||
|
configuration.UseLocalTime = Settings.UseLocalTime;
|
||||||
|
}));
|
||||||
|
|
||||||
|
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||||
|
LoggerProvider = serviceProvider.GetService<ILoggerProvider>();
|
||||||
|
LoggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||||
|
Logger = LoggerFactory.CreateLogger(Settings.Id);
|
||||||
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, LogHelper.GetStartupMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InternalWriteAsync(DateTime dateTime, string message, ELogType logType = ELogType.INFO,
|
||||||
|
bool? writeToConsole = null, bool? sendToSyslogServers = null, bool? sendToSplunkServers = null,
|
||||||
|
string customSplunkSourceType = null, bool? sendToGrayLogServers = null, string grayLogFacility = null,
|
||||||
|
string grayLogSource = null, string grayLogVersion = "1.1")
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(message) || logType == ELogType.NONE ||
|
||||||
|
(int)logType > (int)Settings.MaxLogType)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isDisposing)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsRunning)
|
||||||
|
{
|
||||||
|
await StartNewLogAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageWithHeader = LogHelper.FormatMessageWithHeader(Settings, logType, message, dateTime, _category);
|
||||||
|
var writeToConsoleValue = writeToConsole ?? Settings.EnableConsole;
|
||||||
|
var sendToSyslogServersValue = sendToSyslogServers ?? Settings.SendToSyslogServers;
|
||||||
|
var sendToSplunkServersValue = sendToSplunkServers ?? Settings.SendToSplunkServers;
|
||||||
|
var sendToGrayLogServersValue = sendToGrayLogServers ?? Settings.SendToGrayLogServers;
|
||||||
|
|
||||||
|
LogHelper.SendToFile(Logger, Settings, logType, message);
|
||||||
|
|
||||||
|
if (writeToConsoleValue)
|
||||||
|
{
|
||||||
|
LogHelper.SendToConsole(Settings, logType, messageWithHeader, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tasks = new List<Task>();
|
||||||
|
if (sendToSyslogServersValue || sendToSplunkServersValue || sendToGrayLogServersValue)
|
||||||
{
|
{
|
||||||
if (sendToSyslogServersValue)
|
if (sendToSyslogServersValue)
|
||||||
await LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true);
|
{
|
||||||
|
tasks.Add(LogHelper.SendToSysLogServersAsync(Settings, messageWithHeader, true));
|
||||||
|
}
|
||||||
|
|
||||||
if (sendToSplunkServersValue)
|
if (sendToSplunkServersValue)
|
||||||
await LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(),
|
{
|
||||||
messageWithHeader, true);
|
tasks.Add(LogHelper.SendToSplunkServersAsync(Settings, customSplunkSourceType ?? logType.ToString(),
|
||||||
|
messageWithHeader, true));
|
||||||
|
}
|
||||||
|
|
||||||
if (sendToGrayLogServersValue)
|
if (sendToGrayLogServersValue)
|
||||||
await LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
|
{
|
||||||
grayLogSource, true, grayLogVersion);
|
tasks.Add(LogHelper.SendToGrayLogServersAsync(Settings, messageWithHeader, logType, grayLogFacility,
|
||||||
});
|
grayLogSource, true, grayLogVersion));
|
||||||
|
}
|
||||||
|
|
||||||
var logMessage = new EonaCatLogMessage
|
await Task.WhenAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
var logMessage = new EonaCatLogMessage
|
||||||
|
{
|
||||||
|
DateTime = dateTime,
|
||||||
|
Message = message,
|
||||||
|
LogType = logType,
|
||||||
|
Origin = string.IsNullOrWhiteSpace(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin
|
||||||
|
};
|
||||||
|
|
||||||
|
Settings.OnLogEvent(logMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
{
|
{
|
||||||
DateTime = dateTime,
|
Settings.ResetLogEvent();
|
||||||
Message = message,
|
}
|
||||||
LogType = logType,
|
|
||||||
Origin = string.IsNullOrWhiteSpace(Settings.LogOrigin) ? "LogManager" : Settings.LogOrigin
|
|
||||||
};
|
|
||||||
|
|
||||||
Settings.OnLogEvent(logMessage);
|
private void LogHelper_OnException(object sender, ErrorMessage e)
|
||||||
}
|
{
|
||||||
|
OnException?.Invoke(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
|
||||||
{
|
{
|
||||||
Settings.ResetLogEvent();
|
if (settings == null)
|
||||||
}
|
{
|
||||||
|
settings = Settings;
|
||||||
|
}
|
||||||
|
|
||||||
private void LogHelper_OnException(object sender, ErrorMessage e)
|
if (!settings.EnableFileLogging)
|
||||||
{
|
{
|
||||||
OnException?.Invoke(sender, e);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupFileLogger(LoggerSettings settings = null, string logFolder = null, bool defaultPrefix = true)
|
if (logFolder != null)
|
||||||
{
|
{
|
||||||
if (settings == null)
|
settings.FileLoggerOptions.LogDirectory = logFolder;
|
||||||
settings = Settings;
|
}
|
||||||
|
|
||||||
if (!settings.EnableFileLogging)
|
if (string.IsNullOrWhiteSpace(settings.FileLoggerOptions.FileNamePrefix))
|
||||||
return;
|
{
|
||||||
|
settings.FileLoggerOptions.FileNamePrefix = defaultPrefix ? "EonaCat" : string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (logFolder != null)
|
private void SetupLogManager()
|
||||||
settings.FileLoggerOptions.LogDirectory = logFolder;
|
{
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
||||||
|
_logDate = CurrentDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(settings.FileLoggerOptions.FileNamePrefix))
|
private void ProcessExit(object sender, EventArgs e)
|
||||||
settings.FileLoggerOptions.FileNamePrefix = defaultPrefix ? "EonaCat" : string.Empty;
|
{
|
||||||
}
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private void SetupLogManager()
|
private Task StopLoggingAsync()
|
||||||
{
|
{
|
||||||
AppDomain.CurrentDomain.ProcessExit += ProcessExit;
|
WriteStopMessage();
|
||||||
_logDate = CurrentDateTme;
|
IsRunning = false;
|
||||||
}
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private void ProcessExit(object sender, EventArgs e)
|
private void WriteStopMessage()
|
||||||
{
|
{
|
||||||
Dispose();
|
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
||||||
}
|
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, stopMessage);
|
||||||
|
}
|
||||||
|
|
||||||
private Task StopLoggingAsync()
|
public void DeleteCurrentLogFile()
|
||||||
{
|
{
|
||||||
WriteStopMessage();
|
if (!string.IsNullOrEmpty(CurrentLogFile))
|
||||||
IsRunning = false;
|
{
|
||||||
return Task.CompletedTask;
|
File.Delete(CurrentLogFile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private void WriteStopMessage()
|
|
||||||
{
|
|
||||||
var stopMessage = $"{DllInfo.ApplicationName} stopped.{Environment.NewLine}";
|
|
||||||
LogHelper.SendToFile(Logger, Settings, ELogType.INFO, stopMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteCurrentLogFile()
|
|
||||||
{
|
|
||||||
if (CurrentLogFile != null)
|
|
||||||
File.Delete(CurrentLogFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public class LoggerSettings
|
|||||||
|
|
||||||
private FileLoggerOptions _fileLoggerOptions;
|
private FileLoggerOptions _fileLoggerOptions;
|
||||||
|
|
||||||
private string _headerFormat = "{ts} {host} {thread} {sev}";
|
private string _headerFormat = "{ts} {host} {category} {thread} {sev}";
|
||||||
private int _maxMessageLength = 1024;
|
private int _maxMessageLength = 1024;
|
||||||
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
|
private string _timestampFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
@@ -43,9 +43,10 @@ public class LoggerSettings
|
|||||||
/// variables including:
|
/// variables including:
|
||||||
/// {ts}: UTC timestamp
|
/// {ts}: UTC timestamp
|
||||||
/// {host}: Hostname
|
/// {host}: Hostname
|
||||||
|
/// {category}: Category
|
||||||
/// {thread}: Thread ID
|
/// {thread}: Thread ID
|
||||||
/// {sev}: Severity
|
/// {sev}: Severity
|
||||||
/// Default: {ts} {host} {thread} {sev}
|
/// Default: {ts} {host} {category} {thread} {sev}
|
||||||
/// A space will be inserted between the header and the message.
|
/// A space will be inserted between the header and the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string HeaderFormat
|
public string HeaderFormat
|
||||||
@@ -53,8 +54,14 @@ public class LoggerSettings
|
|||||||
get => _headerFormat;
|
get => _headerFormat;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value)) _headerFormat = "";
|
if (string.IsNullOrEmpty(value))
|
||||||
else _headerFormat = value;
|
{
|
||||||
|
_headerFormat = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_headerFormat = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +73,11 @@ public class LoggerSettings
|
|||||||
get => _timestampFormat;
|
get => _timestampFormat;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(HeaderFormat));
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(HeaderFormat));
|
||||||
|
}
|
||||||
|
|
||||||
_timestampFormat = value;
|
_timestampFormat = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +92,14 @@ public class LoggerSettings
|
|||||||
get => _enableConsole;
|
get => _enableConsole;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value) _enableConsole = ConsoleExists();
|
if (value)
|
||||||
else _enableConsole = false;
|
{
|
||||||
|
_enableConsole = ConsoleExists();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_enableConsole = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +116,11 @@ public class LoggerSettings
|
|||||||
get => _colors;
|
get => _colors;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == null) throw new ArgumentNullException(nameof(Colors));
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(Colors));
|
||||||
|
}
|
||||||
|
|
||||||
_colors = value;
|
_colors = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +151,11 @@ public class LoggerSettings
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_fileLoggerOptions == null) _fileLoggerOptions = CreateDefaultFileLoggerOptions();
|
if (_fileLoggerOptions == null)
|
||||||
|
{
|
||||||
|
_fileLoggerOptions = CreateDefaultFileLoggerOptions();
|
||||||
|
}
|
||||||
|
|
||||||
return _fileLoggerOptions;
|
return _fileLoggerOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ public class SplunkServer
|
|||||||
SplunkHecUrl = splunkHecUrl;
|
SplunkHecUrl = splunkHecUrl;
|
||||||
SplunkHecToken = splunkHecToken;
|
SplunkHecToken = splunkHecToken;
|
||||||
|
|
||||||
if (httpClientHandler == null) httpClientHandler = new HttpClientHandler();
|
if (httpClientHandler == null)
|
||||||
|
{
|
||||||
|
httpClientHandler = new HttpClientHandler();
|
||||||
|
}
|
||||||
|
|
||||||
SplunkClientHandler = httpClientHandler;
|
SplunkClientHandler = httpClientHandler;
|
||||||
CreateHttpClient();
|
CreateHttpClient();
|
||||||
@@ -45,7 +48,10 @@ public class SplunkServer
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(_splunkHecUrl) && !_splunkHecUrl.ToLower().Contains("http"))
|
if (!string.IsNullOrWhiteSpace(_splunkHecUrl) && !_splunkHecUrl.ToLower().Contains("http"))
|
||||||
|
{
|
||||||
value = $"http://{value}";
|
value = $"http://{value}";
|
||||||
|
}
|
||||||
|
|
||||||
_splunkHecUrl = value;
|
_splunkHecUrl = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +109,10 @@ public class SplunkServer
|
|||||||
|
|
||||||
public async Task<HttpResponseMessage> SendAsync(SplunkPayload splunkPayload)
|
public async Task<HttpResponseMessage> SendAsync(SplunkPayload splunkPayload)
|
||||||
{
|
{
|
||||||
if (splunkPayload == null) return null;
|
if (splunkPayload == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Create an event object with the required fields
|
// Create an event object with the required fields
|
||||||
var eventObject = new
|
var eventObject = new
|
||||||
@@ -116,7 +125,10 @@ public class SplunkServer
|
|||||||
// Serialize the event object to JSON
|
// Serialize the event object to JSON
|
||||||
var eventJson = JsonHelper.ToJson(eventObject);
|
var eventJson = JsonHelper.ToJson(eventObject);
|
||||||
|
|
||||||
if (!HasHecToken) CreateHttpClient();
|
if (!HasHecToken)
|
||||||
|
{
|
||||||
|
CreateHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
// Create an HTTP content with the event data
|
// Create an HTTP content with the event data
|
||||||
var content = new StringContent(eventJson, Encoding.UTF8, "application/json");
|
var content = new StringContent(eventJson, Encoding.UTF8, "application/json");
|
||||||
|
|||||||
@@ -42,7 +42,11 @@ public class SyslogServer
|
|||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(Hostname));
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(Hostname));
|
||||||
|
}
|
||||||
|
|
||||||
_Hostname = value;
|
_Hostname = value;
|
||||||
|
|
||||||
SetUdp();
|
SetUdp();
|
||||||
@@ -57,7 +61,11 @@ public class SyslogServer
|
|||||||
get => _Port;
|
get => _Port;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value < 0) throw new ArgumentException("Port must be zero or greater.");
|
if (value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Port must be zero or greater.");
|
||||||
|
}
|
||||||
|
|
||||||
_Port = value;
|
_Port = value;
|
||||||
|
|
||||||
SetUdp();
|
SetUdp();
|
||||||
|
|||||||
58
README.md
58
README.md
@@ -11,14 +11,14 @@ Microsoft.Extensions.Logging
|
|||||||
|
|
||||||
**Easy way of logging without configuring anything:**
|
**Easy way of logging without configuring anything:**
|
||||||
```csharp
|
```csharp
|
||||||
LogManager.Instance.Write("INFO", ELogType.INFO, true);
|
LogManager.Instance.WriteAsync("INFO", ELogType.INFO, true);
|
||||||
LogManager.Instance.Write("WARNING", ELogType.WARNING, true);
|
LogManager.Instance.WriteAsync("WARNING", ELogType.WARNING, true);
|
||||||
LogManager.Instance.Write("ERROR", ELogType.ERROR, true);
|
LogManager.Instance.WriteAsync("ERROR", ELogType.ERROR, true);
|
||||||
LogManager.Instance.Write("DEBUG", ELogType.DEBUG, true);
|
LogManager.Instance.WriteAsync("DEBUG", ELogType.DEBUG, true);
|
||||||
LogManager.Instance.Write("CRITICAL", ELogType.CRITICAL, true);
|
LogManager.Instance.WriteAsync("CRITICAL", ELogType.CRITICAL, true);
|
||||||
LogManager.Instance.Write("TRACE", ELogType.TRACE, true);
|
LogManager.Instance.WriteAsync("TRACE", ELogType.TRACE, true);
|
||||||
LogManager.Instance.Write("TRAFFIC", ELogType.TRAFFIC, true);
|
LogManager.Instance.WriteAsync("TRAFFIC", ELogType.TRAFFIC, true);
|
||||||
LogManager.Instance.Write("NONE", ELogType.NONE, true);
|
LogManager.Instance.WriteAsync("NONE", ELogType.NONE, true);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Logging in .NET 4.8 or higher: **
|
**Logging in .NET 4.8 or higher: **
|
||||||
@@ -186,28 +186,28 @@ namespace EonaCat.Logger.Advanced
|
|||||||
// Logs an informational message.
|
// Logs an informational message.
|
||||||
public static void Info(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Info(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.INFO, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.INFO, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal method to write logs.
|
// Internal method to write logs.
|
||||||
private static void Write(string message, ELogType logType, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
private static void WriteAsync(string message, ELogType logType, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
if (grayLogSettings != null)
|
if (grayLogSettings != null)
|
||||||
{
|
{
|
||||||
// Log the message with specified settings.
|
// Log the message with specified settings.
|
||||||
_logManager.Write(message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings.Facility, grayLogSettings.Source, grayLogSettings.Version);
|
_logManager.WriteAsync(message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings.Facility, grayLogSettings.Source, grayLogSettings.Version);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Log the message with default settings.
|
// Log the message with default settings.
|
||||||
_logManager.Write(message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers);
|
_logManager.WriteAsync(message, logType, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs a debug message.
|
// Logs a debug message.
|
||||||
public static void Debug(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Debug(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.DEBUG, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.DEBUG, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs an error message along with an exception.
|
// Logs an error message along with an exception.
|
||||||
@@ -216,12 +216,12 @@ namespace EonaCat.Logger.Advanced
|
|||||||
if (grayLogSettings != null)
|
if (grayLogSettings != null)
|
||||||
{
|
{
|
||||||
// Log the exception and message with specified settings.
|
// Log the exception and message with specified settings.
|
||||||
_logManager.Write(exception, message, criticalException: isCriticalException, writeToConsole: writeToConsole, sendToSysLogServers: sendToSysLogServers, sendToSplunkServers: sendToSplunkServers, customSplunkSourceType: customSplunkSourceType, sendToGrayLogServers: sendToGrayLogServers, grayLogFacility: grayLogSettings.Facility, grayLogSource: grayLogSettings.Source, grayLogVersion: grayLogSettings.Version);
|
_logManager.WriteAsync(exception, message, criticalException: isCriticalException, writeToConsole: writeToConsole, sendToSysLogServers: sendToSysLogServers, sendToSplunkServers: sendToSplunkServers, customSplunkSourceType: customSplunkSourceType, sendToGrayLogServers: sendToGrayLogServers, grayLogFacility: grayLogSettings.Facility, grayLogSource: grayLogSettings.Source, grayLogVersion: grayLogSettings.Version);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Log the exception and message with default settings.
|
// Log the exception and message with default settings.
|
||||||
_logManager.Write(exception, message, criticalException: isCriticalException, writeToConsole: writeToConsole, sendToSysLogServers: sendToSysLogServers, sendToSplunkServers: sendToSplunkServers, customSplunkSourceType: customSplunkSourceType, sendToGrayLogServers: sendToGrayLogServers);
|
_logManager.WriteAsync(exception, message, criticalException: isCriticalException, writeToConsole: writeToConsole, sendToSysLogServers: sendToSysLogServers, sendToSplunkServers: sendToSplunkServers, customSplunkSourceType: customSplunkSourceType, sendToGrayLogServers: sendToGrayLogServers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,37 +231,37 @@ namespace EonaCat.Logger.Advanced
|
|||||||
if (isCriticalException)
|
if (isCriticalException)
|
||||||
{
|
{
|
||||||
// Log a critical error message.
|
// Log a critical error message.
|
||||||
_logManager.Write(message, ELogType.CRITICAL, writeToConsole);
|
_logManager.WriteAsync(message, ELogType.CRITICAL, writeToConsole);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Log a regular error message.
|
// Log a regular error message.
|
||||||
_logManager.Write(message, ELogType.ERROR, writeToConsole);
|
_logManager.WriteAsync(message, ELogType.ERROR, writeToConsole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs a warning message.
|
// Logs a warning message.
|
||||||
public static void Warning(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Warning(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.WARNING, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.WARNING, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs a critical message.
|
// Logs a critical message.
|
||||||
public static void Critical(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Critical(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.CRITICAL, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.CRITICAL, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs a traffic message.
|
// Logs a traffic message.
|
||||||
public static void Traffic(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Traffic(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.TRAFFIC, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.TRAFFIC, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs a trace message.
|
// Logs a trace message.
|
||||||
public static void Trace(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
public static void Trace(string message, bool? writeToConsole = null, bool? sendToSysLogServers = null, bool? sendToSplunkServers = null, string? customSplunkSourceType = null, bool? sendToGrayLogServers = null, GrayLogSettings grayLogSettings = null)
|
||||||
{
|
{
|
||||||
Write(message, ELogType.TRACE, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
WriteAsync(message, ELogType.TRACE, writeToConsole, sendToSysLogServers, sendToSplunkServers, customSplunkSourceType, sendToGrayLogServers, grayLogSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,14 +319,14 @@ Task.Run(() =>
|
|||||||
// 10.000.000 lines to go :)
|
// 10.000.000 lines to go :)
|
||||||
for (int i = 0; i < 10000000; i++)
|
for (int i = 0; i < 10000000; i++)
|
||||||
{
|
{
|
||||||
logger.Write($"test to file {i} INFO", ELogType.INFO);
|
logger.WriteAsync($"test to file {i} INFO", ELogType.INFO);
|
||||||
logger.Write($"test to file {i} CRITICAL", ELogType.CRITICAL);
|
logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL);
|
||||||
logger.Write($"test to file {i} DEBUG", ELogType.DEBUG);
|
logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG);
|
||||||
logger.Write($"test to file {i} ERROR", ELogType.ERROR);
|
logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR);
|
||||||
logger.Write($"test to file {i} TRACE", ELogType.TRACE);
|
logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE);
|
||||||
logger.Write($"test to file {i} TRAFFIC", ELogType.TRAFFIC);
|
logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC);
|
||||||
logger.Write($"test to file {i} WARNING", ELogType.WARNING);
|
logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING);
|
||||||
logger.Write($"test to file {i} NONE", ELogType.NONE);
|
logger.WriteAsync($"test to file {i} NONE", ELogType.NONE);
|
||||||
Console.WriteLine($"Logged: {i}");
|
Console.WriteLine($"Logged: {i}");
|
||||||
Task.Delay(1);
|
Task.Delay(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,29 +5,52 @@ using EonaCat.Logger.Managers;
|
|||||||
|
|
||||||
namespace EonaCat.Logger.Test.Web;
|
namespace EonaCat.Logger.Test.Web;
|
||||||
|
|
||||||
public static class Logger
|
public class Logger
|
||||||
{
|
{
|
||||||
private static LogManager LogManager;
|
private LogManager _logManager;
|
||||||
public static ELogType MaxLogType { get; set; }
|
public ELogType MaxLogType { get; set; }
|
||||||
public static bool UseLocalTime { get; set; }
|
public LoggerSettings LoggerSettings { get; }
|
||||||
public static string LogFolder => Path.Combine(FileLoggerOptions.DefaultPath, "logs");
|
public bool UseLocalTime { get; set; }
|
||||||
public static string CurrentLogFile => LogManager.CurrentLogFile;
|
public string LogFolder { get; set; } = Path.Combine(FileLoggerOptions.DefaultPath, "logs");
|
||||||
public static bool IsDisabled { get; set; }
|
public string CurrentLogFile => _logManager.CurrentLogFile;
|
||||||
|
public bool IsDisabled { get; set; }
|
||||||
|
|
||||||
public static void DeleteCurrentLogFile()
|
public Logger(string name = "EonaCatTestLogger", ELogType maxLogType = ELogType.INFO, bool useLocalTime = false, int maxFileSize = 20_000_000)
|
||||||
{
|
{
|
||||||
if (IsDisabled)
|
UseLocalTime = useLocalTime;
|
||||||
return;
|
MaxLogType = maxLogType;
|
||||||
|
|
||||||
LogManager.DeleteCurrentLogFile();
|
LoggerSettings = new LoggerSettings
|
||||||
|
{
|
||||||
|
Id = name,
|
||||||
|
MaxLogType = MaxLogType,
|
||||||
|
UseLocalTime = UseLocalTime,
|
||||||
|
FileLoggerOptions =
|
||||||
|
{
|
||||||
|
LogDirectory = LogFolder,
|
||||||
|
FileSizeLimit = maxFileSize,
|
||||||
|
UseLocalTime = UseLocalTime,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
_logManager = new LogManager(LoggerSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ConvertToAbsolutePath(string path)
|
public void DeleteCurrentLogFile()
|
||||||
|
{
|
||||||
|
if (IsDisabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logManager.DeleteCurrentLogFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ConvertToAbsolutePath(string path)
|
||||||
{
|
{
|
||||||
return Path.IsPathRooted(path) ? path : Path.Combine(LogFolder, path);
|
return Path.IsPathRooted(path) ? path : Path.Combine(LogFolder, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task DownloadLogAsync(HttpContext context, string logName, long limit)
|
public async Task DownloadLogAsync(HttpContext context, string logName, long limit)
|
||||||
{
|
{
|
||||||
var logFileName = logName + ".log";
|
var logFileName = logName + ".log";
|
||||||
|
|
||||||
@@ -39,7 +62,9 @@ public static class Logger
|
|||||||
response.Headers.ContentDisposition = "attachment;filename=" + logFileName;
|
response.Headers.ContentDisposition = "attachment;filename=" + logFileName;
|
||||||
|
|
||||||
if (limit > fS.Length || limit < 1)
|
if (limit > fS.Length || limit < 1)
|
||||||
|
{
|
||||||
limit = fS.Length;
|
limit = fS.Length;
|
||||||
|
}
|
||||||
|
|
||||||
var oFS = new OffsetStream(fS, 0, limit);
|
var oFS = new OffsetStream(fS, 0, limit);
|
||||||
var request = context.Request;
|
var request = context.Request;
|
||||||
@@ -81,43 +106,32 @@ public static class Logger
|
|||||||
await oFS.CopyToAsync(stream).ConfigureAwait(false);
|
await oFS.CopyToAsync(stream).ConfigureAwait(false);
|
||||||
|
|
||||||
if (fS.Length > limit)
|
if (fS.Length > limit)
|
||||||
|
{
|
||||||
await stream.WriteAsync("\r\n####__EONACATLOGGER_TRUNCATED___####"u8.ToArray()).ConfigureAwait(false);
|
await stream.WriteAsync("\r\n####__EONACATLOGGER_TRUNCATED___####"u8.ToArray()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task LogAsync(string message, ELogType logType = ELogType.INFO, bool writeToConsole = true)
|
public async Task LogAsync(string message, ELogType logType = ELogType.INFO, bool writeToConsole = true)
|
||||||
{
|
{
|
||||||
if (IsDisabled)
|
if (IsDisabled)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await LogManager.WriteAsync(message, logType, writeToConsole).ConfigureAwait(false);
|
await _logManager.WriteAsync(message, logType, writeToConsole).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task LogAsync(Exception exception, string message = "", bool writeToConsole = true)
|
public async Task LogAsync(Exception exception, string message = "", bool writeToConsole = true)
|
||||||
{
|
{
|
||||||
if (IsDisabled)
|
if (IsDisabled)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ELogType.ERROR <= MaxLogType)
|
if (ELogType.ERROR <= MaxLogType)
|
||||||
{
|
{
|
||||||
await LogManager.WriteAsync(exception, message, writeToConsole: writeToConsole).ConfigureAwait(false);
|
await _logManager.WriteAsync(exception, message, writeToConsole: writeToConsole).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Configure()
|
|
||||||
{
|
|
||||||
var loggerSettings = new LoggerSettings
|
|
||||||
{
|
|
||||||
Id = "EonaCatTestLogger",
|
|
||||||
MaxLogType = ELogType.INFO,
|
|
||||||
UseLocalTime = UseLocalTime,
|
|
||||||
FileLoggerOptions =
|
|
||||||
{
|
|
||||||
LogDirectory = LogFolder,
|
|
||||||
FileSizeLimit = 20_000_000, // 20 MB,
|
|
||||||
UseLocalTime = UseLocalTime
|
|
||||||
}
|
|
||||||
};
|
|
||||||
LogManager = new LogManager(loggerSettings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using EonaCat.Logger;
|
using EonaCat.Logger;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger;
|
using EonaCat.Logger.EonaCatCoreLogger;
|
||||||
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
|
using EonaCat.Logger.EonaCatCoreLogger.Extensions;
|
||||||
|
using EonaCat.Logger.EonaCatCoreLogger.Models;
|
||||||
using EonaCat.Logger.Managers;
|
using EonaCat.Logger.Managers;
|
||||||
using EonaCat.Logger.Test.Web;
|
using EonaCat.Logger.Test.Web;
|
||||||
using EonaCat.Web.RateLimiter;
|
using EonaCat.Web.RateLimiter;
|
||||||
@@ -8,11 +9,21 @@ using EonaCat.Web.RateLimiter.Endpoints.Extensions;
|
|||||||
using EonaCat.Web.Tracer.Extensions;
|
using EonaCat.Web.Tracer.Extensions;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
int onLogCounter = 0;
|
||||||
|
var defaultColor = Console.ForegroundColor;
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
Logger.UseLocalTime = true;
|
Logger logger = new Logger();
|
||||||
Logger.MaxLogType = ELogType.TRACE;
|
logger.UseLocalTime = true;
|
||||||
Logger.Configure();
|
logger.MaxLogType = ELogType.TRACE;
|
||||||
|
logger.LoggerSettings.OnLog += LoggerSettings_OnLog;
|
||||||
|
|
||||||
|
void LoggerSettings_OnLog(EonaCatLogMessage message)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine($"LogCounter: {++onLogCounter} {message}");
|
||||||
|
Console.ForegroundColor = defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
var options = new FileLoggerOptions();
|
var options = new FileLoggerOptions();
|
||||||
options.MaxRolloverFiles = 5;
|
options.MaxRolloverFiles = 5;
|
||||||
@@ -124,11 +135,11 @@ void RunLoggingExceptionTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Run(RunWebLoggerTests).ConfigureAwait(false);
|
await Task.Run(RunWebLoggerTestsAsync).ConfigureAwait(false);
|
||||||
Task.Run(RunWebLoggingTests).ConfigureAwait(false);
|
await Task.Run(RunWebLoggingTests).ConfigureAwait(false);
|
||||||
Task.Run(RunLoggingTests).ConfigureAwait(false);
|
await Task.Run(RunLoggingTestsAsync).ConfigureAwait(false);
|
||||||
Task.Run(RunLoggingExceptionTests).ConfigureAwait(false);
|
await Task.Run(RunLoggingExceptionTests).ConfigureAwait(false);
|
||||||
Task.Run(RunWebLoggingExceptionTests).ConfigureAwait(false);
|
await Task.Run(RunWebLoggingExceptionTests).ConfigureAwait(false);
|
||||||
|
|
||||||
void RunWebLoggingExceptionTests()
|
void RunWebLoggingExceptionTests()
|
||||||
{
|
{
|
||||||
@@ -155,12 +166,15 @@ void RunWebLoggingExceptionTests()
|
|||||||
|
|
||||||
async 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}");
|
||||||
using (var file = new StreamWriter(Path.Combine(Logger.LogFolder, "test.log"), true))
|
using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "test.log"), true))
|
||||||
{
|
{
|
||||||
await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
|
await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -169,7 +183,7 @@ async void RunWebLoggingTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunLoggingTests()
|
async Task RunLoggingTestsAsync()
|
||||||
{
|
{
|
||||||
var loggerSettings = new LoggerSettings();
|
var loggerSettings = new LoggerSettings();
|
||||||
loggerSettings.UseLocalTime = true;
|
loggerSettings.UseLocalTime = true;
|
||||||
@@ -182,38 +196,37 @@ void RunLoggingTests()
|
|||||||
|
|
||||||
for (var i = 0; i < 9000000; i++)
|
for (var i = 0; i < 9000000; i++)
|
||||||
{
|
{
|
||||||
logger.WriteAsync($"test to file {i} INFO").ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} INFO").ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
|
||||||
logger.WriteAsync($"test to file {i} NONE", ELogType.NONE).ConfigureAwait(false);
|
await logger.WriteAsync($"test to file {i} NONE", ELogType.NONE).ConfigureAwait(false);
|
||||||
Console.WriteLine($"Logged: {i}");
|
Console.WriteLine($"Logged: {i}");
|
||||||
Task.Delay(1);
|
await Task.Delay(1).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunWebLoggerTests()
|
async Task RunWebLoggerTestsAsync()
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
Task.Run(() =>
|
await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
Logger.LogAsync($"test via logger {i} INFO");
|
await logger.LogAsync($"test via logger {i} INFO").ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} CRITICAL", ELogType.CRITICAL);
|
await logger.LogAsync($"test via logger {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} DEBUG", ELogType.DEBUG);
|
await logger.LogAsync($"test via logger {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} ERROR", ELogType.ERROR);
|
await logger.LogAsync($"test via logger {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} TRACE", ELogType.TRACE);
|
await logger.LogAsync($"test via logger {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} TRAFFIC", ELogType.TRAFFIC);
|
await logger.LogAsync($"test via logger {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} WARNING", ELogType.WARNING);
|
await logger.LogAsync($"test via logger {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
|
||||||
Logger.LogAsync($"test via logger {i} NONE", ELogType.NONE);
|
await logger.LogAsync($"test via logger {i} NONE", ELogType.NONE).ConfigureAwait(false);
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
Console.WriteLine($"Logger: {i}");
|
await Task.Delay(1).ConfigureAwait(false);
|
||||||
Task.Delay(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user