Compare commits

..

No commits in common. "a3be0d96480892a6b2e13ebae30a636389373bbb" and "448d85d6f69716939917f73ab539fca0589f7134" have entirely different histories.

8 changed files with 39 additions and 80 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,41 +0,0 @@
{
"$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

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

View File

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