diff --git a/ModularPipelines/Engine/PipelineExecutor.cs b/ModularPipelines/Engine/PipelineExecutor.cs index 9410c223ed..cd3bb37890 100644 --- a/ModularPipelines/Engine/PipelineExecutor.cs +++ b/ModularPipelines/Engine/PipelineExecutor.cs @@ -14,6 +14,7 @@ internal class PipelineExecutor : IPipelineExecutor private readonly EngineCancellationToken _engineCancellationToken; private readonly IDependencyDetector _dependencyDetector; private readonly IModuleResultPrinter _moduleResultPrinter; + private readonly IModuleLoggerContainer _moduleLoggerContainer; public PipelineExecutor( IPipelineSetupExecutor pipelineSetupExecutor, @@ -23,7 +24,8 @@ public PipelineExecutor( IModuleExecutor moduleExecutor, EngineCancellationToken engineCancellationToken, IDependencyDetector dependencyDetector, - IModuleResultPrinter moduleResultPrinter) + IModuleResultPrinter moduleResultPrinter, + IModuleLoggerContainer moduleLoggerContainer) { _pipelineSetupExecutor = pipelineSetupExecutor; _pipelineConsolePrinter = pipelineConsolePrinter; @@ -33,6 +35,7 @@ public PipelineExecutor( _engineCancellationToken = engineCancellationToken; _dependencyDetector = dependencyDetector; _moduleResultPrinter = moduleResultPrinter; + _moduleLoggerContainer = moduleLoggerContainer; } public async Task> ExecuteAsync() @@ -70,6 +73,8 @@ public async Task> ExecuteAsync() await Task.Delay(200); + _moduleLoggerContainer.PrintAllLoggers(); + _moduleResultPrinter.PrintModuleResults(); } diff --git a/ModularPipelines/Host/PipelineHostBuilder.cs b/ModularPipelines/Host/PipelineHostBuilder.cs index 9ae17089cf..0aa6a3a1e5 100644 --- a/ModularPipelines/Host/PipelineHostBuilder.cs +++ b/ModularPipelines/Host/PipelineHostBuilder.cs @@ -56,6 +56,7 @@ internal PipelineHostBuilder() .AddSingleton() .AddSingleton() .AddSingleton(typeof(ModuleLogger<>)) + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/ModularPipelines/IModuleLoggerContainer.cs b/ModularPipelines/IModuleLoggerContainer.cs new file mode 100644 index 0000000000..115667bc38 --- /dev/null +++ b/ModularPipelines/IModuleLoggerContainer.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Logging; + +namespace ModularPipelines; + +internal interface IModuleLoggerContainer +{ + void PrintAllLoggers(); + void AddLogger(ModuleLogger logger); +} \ No newline at end of file diff --git a/ModularPipelines/ModuleLogger.cs b/ModularPipelines/ModuleLogger.cs index a74d160a6f..a576962bab 100644 --- a/ModularPipelines/ModuleLogger.cs +++ b/ModularPipelines/ModuleLogger.cs @@ -5,7 +5,16 @@ namespace ModularPipelines; -public class ModuleLogger : ILogger, IDisposable +internal abstract class ModuleLogger : ILogger, IDisposable +{ + internal DateTime LastLogWritten { get; set; } = DateTime.MinValue; + public abstract void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter); + public abstract bool IsEnabled(LogLevel logLevel); + public abstract IDisposable BeginScope(TState state); + public abstract void Dispose(); +} + +internal class ModuleLogger : ModuleLogger, ILogger, IDisposable { private readonly IOptions _options; private readonly ILogger _defaultLogger; @@ -15,23 +24,24 @@ public class ModuleLogger : ILogger, IDisposable private bool _isDisposed; // ReSharper disable once ContextualLoggerProblem - public ModuleLogger(IOptions options, ILogger defaultLogger) + public ModuleLogger(IOptions options, ILogger defaultLogger, IModuleLoggerContainer moduleLoggerContainer) { _options = options; _defaultLogger = defaultLogger; + moduleLoggerContainer.AddLogger(this); } - public IDisposable BeginScope(TState state) + public override IDisposable BeginScope(TState state) { return new NoopDisposable(); } - public bool IsEnabled(LogLevel logLevel) + public override bool IsEnabled(LogLevel logLevel) { return logLevel >= _options.Value.LoggerOptions.LogLevel; } - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func? formatter) + public override void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func? formatter) { if (!IsEnabled(logLevel) || _isDisposed) { @@ -43,6 +53,8 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except var valueTuple = (logLevel, eventId, state, exception, mappedFormatter); _logEvents.Add(valueTuple!); + + LastLogWritten = DateTime.UtcNow; } private Func MapFormatter(Func? formatter) @@ -63,8 +75,13 @@ public void Dispose() } [MethodImpl(MethodImplOptions.Synchronized)] - public void Dispose() + public override void Dispose() { + if (_isDisposed) + { + return; + } + _isDisposed = true; var logEvents = Interlocked.Exchange(ref _logEvents!, new List<(LogLevel logLevel, EventId eventId, object state, Exception exception, Func formatter)>()); diff --git a/ModularPipelines/ModuleLoggerContainer.cs b/ModularPipelines/ModuleLoggerContainer.cs new file mode 100644 index 0000000000..6059ce82bc --- /dev/null +++ b/ModularPipelines/ModuleLoggerContainer.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Logging; + +namespace ModularPipelines; + +internal class ModuleLoggerContainer : IModuleLoggerContainer +{ + private readonly List _loggers = new(); + + public void PrintAllLoggers() + { + foreach (var logger in _loggers.OrderBy(x => x.LastLogWritten)) + { + logger.Dispose(); + } + } + + public void AddLogger(ModuleLogger logger) + { + _loggers.Add(logger); + } +} \ No newline at end of file