Compare commits

..

4 Commits

Author SHA1 Message Date
max
a3be0d9648 Add test settings 2024-11-30 21:44:33 +01:00
max
7ec3257eac Optimalization log processor 2024-11-30 21:34:06 +01:00
max
91476907f0 [CHANGE] Update test WebApi 2024-11-30 18:56:24 +01:00
max
e1cba8d68c [CHANGE] Get parameters from framework logger. 2024-11-30 18:55:09 +01:00
8 changed files with 80 additions and 39 deletions

View File

@ -4,6 +4,7 @@ namespace DotBased.Logging.MEL;
public class BasedLogger : Microsoft.Extensions.Logging.ILogger
{
private const string _messageTemplateKey = "{OriginalFormat}";
public BasedLogger(ILogger logger)
{
basedLogger = logger;
@ -22,24 +23,26 @@ public class BasedLogger : Microsoft.Extensions.Logging.ILogger
private LogCapsule ConstructCapsule<TState>(LogSeverity severity, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
//TODO: Extract parameters & format
var msgTemplate = string.Empty;
List<object?> templateParams = [];
if (state is IEnumerable<KeyValuePair<string, object>> stateEnum)
{
foreach (var prop in stateEnum)
{
if (prop is { Key: "{OriginalFormat}", Value: string propValueString })
if (prop is { Key: _messageTemplateKey, Value: string propValueString })
{
msgTemplate = propValueString;
continue;
}
templateParams.Add(prop.Value);
}
}
return new LogCapsule()
{
Exception = exception,
Message = formatter.Invoke(state, exception),
Parameters = [],
Message = msgTemplate,
Parameters = templateParams.ToArray(),
Severity = severity,
TimeStamp = DateTime.Now,
Logger = basedLogger as LoggerBase ?? throw new NullReferenceException(nameof(basedLogger))

View File

@ -4,11 +4,10 @@ namespace DotBased.Logging.MEL;
public static class LoggerBuilderExtensions
{
public static ILoggingBuilder AddDotBased(this ILoggingBuilder builder, LogOptions options)
public static void AddDotBasedLoggerProvider(this ILoggingBuilder builder, LogOptions options)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
builder.AddProvider(new BasedLoggerProvider(options));
return builder;
}
}

View File

@ -7,7 +7,7 @@ public static class BasedSerilog
/// <summary>
/// Default output template with the extra properties that can be used for serilog sinks.
/// </summary>
public const string OutputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3} - {LoggerName}]{NewLine} {Message:lj}{NewLine}{Exception}";
public const string OutputTemplate = "[{Timestamp:HH:mm:ss} {Level} - {LoggerName}] {Message:lj}{NewLine}{Exception}";
public static LoggerConfiguration UseBasedExtension(this LoggerConfiguration loggerConfiguration)
{

View File

@ -1,3 +1,5 @@
using System.Collections.Concurrent;
namespace DotBased.Logging;
/// <summary>
@ -7,21 +9,16 @@ public class LogProcessor : IDisposable
{
public LogProcessor()
{
_processorQueue = new Queue<LogCapsule>();
_canLog = true;
_capsuleCollection = new BlockingCollection<LogCapsule>();
IncomingLogHandlerEvent = IncomingLogHandler;
_processorThread = new Thread(ProcessLog)
{
IsBackground = true,
Name = "Log processor thread (DotBased)"
};
_processorThread.Start();
_processTask = Task.Factory.StartNew(ProcessLog);
}
public readonly Action<LogCapsule> IncomingLogHandlerEvent;
public event EventHandler<LogCapsule>? LogProcessed;
private readonly Queue<LogCapsule> _processorQueue;
private readonly Thread _processorThread;
private readonly ManualResetEvent _threadSuspendEvent = new ManualResetEvent(false);
private readonly ManualResetEvent _threadShutdownEvent = new ManualResetEvent(false);
private bool _canLog;
private readonly BlockingCollection<LogCapsule> _capsuleCollection;
private readonly Task _processTask;
/// <summary>
/// Stop the LogProcessor
@ -31,9 +28,9 @@ public class LogProcessor : IDisposable
/// </remarks>
public void Stop()
{
_threadShutdownEvent.Set();
_threadSuspendEvent.Set();
_processorThread.Join();
_canLog = false;
_capsuleCollection.CompleteAdding();
_processTask.Wait();
}
public void Dispose()
@ -43,35 +40,31 @@ public class LogProcessor : IDisposable
private void IncomingLogHandler(LogCapsule e)
{
_processorQueue.Enqueue(e);
// Check if the thread is running, if not wake up the thread.
if (!_threadSuspendEvent.WaitOne(0))
_threadSuspendEvent.Set();
if (!_canLog)
return;
if (!_capsuleCollection.TryAdd(e))
{
_canLog = false;
}
}
private void ProcessLog()
{
try
{
while (true)
while (!_capsuleCollection.IsCompleted)
{
_threadSuspendEvent.WaitOne(Timeout.Infinite);
if (_threadShutdownEvent.WaitOne(0))
break;
if (_processorQueue.Count != 0)
if (_capsuleCollection.TryTake(out var capsule, Timeout.Infinite))
{
var capsule = _processorQueue.Dequeue();
if (!LogService.CanLog(LogService.Options.Severity, capsule.Severity))
continue;
if (LogService.FilterSeverityLog(capsule))
LogProcessed?.Invoke(this, capsule);
}
else
_threadSuspendEvent.Reset();
}
}
catch (InvalidOperationException)
{ }
catch (Exception e)
{
// Write exception to the output
@ -81,7 +74,8 @@ public class LogProcessor : IDisposable
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write($"[{DateTime.Now}] ");
Console.ForegroundColor = oldColor;
Console.WriteLine($"[{nameof(LogProcessor)} (DotBased)] Log processor thread failed! No logs are being processed!");
Console.WriteLine(
$"[{nameof(LogProcessor)} (DotBased)] Log processor thread failed! No logs are being processed!");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
Console.ForegroundColor = ConsoleColor.Yellow;

View File

@ -16,7 +16,7 @@ var serilogLogger = SetupSerilog();
LogService.AddLogAdapter(new BasedSerilogAdapter(serilogLogger));
builder.Logging.ClearProviders();
builder.Logging.AddDotBased(LogService.Options);
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
@ -25,8 +25,6 @@ builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:35507",
"sslPort": 44353
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5044",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7234;http://localhost:5044",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,3 @@
{
}

View File

@ -0,0 +1,3 @@
{
"AllowedHosts": "*"
}