From c51b78c628994e358ac2217fc195fefeb36f1675 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Fri, 22 Mar 2024 14:56:54 +0300 Subject: [PATCH] File-scoped namespaces --- .../SimpleServiceSample/PrintTimeService.cs | 27 +- samples/SimpleServiceSample/Program.cs | 63 +- samples/WebApplicationSample/Program.cs | 63 +- samples/WebApplicationSample/Startup.cs | 41 +- .../AmbientDiagnosticContextCollector.cs | 43 +- .../Hosting/CachingReloadableLogger.cs | 835 +++++++------ .../Extensions/Hosting/DiagnosticContext.cs | 75 +- .../Hosting/DiagnosticContextCollector.cs | 169 ++- .../Hosting/FixedPropertyEnricher.cs | 23 +- .../Extensions/Hosting/IReloadableLogger.cs | 9 +- .../Hosting/InjectedLoggerSettings.cs | 53 +- .../Extensions/Hosting/NullEnricher.cs | 13 +- .../Extensions/Hosting/ReloadableLogger.cs | 1053 ++++++++--------- .../Hosting/SerilogLoggerFactory.cs | 87 +- .../IDiagnosticContext.cs | 47 +- .../LoggerConfigurationExtensions.cs | 31 +- .../LoggerSettingsConfigurationExtensions.cs | 35 +- .../Serilog.Extensions.Hosting.csproj | 2 +- .../SerilogHostBuilderExtensions.cs | 175 ++- .../SerilogServiceCollectionExtensions.cs | 365 +++--- .../DiagnosticContextTests.cs | 215 ++-- ...gerSettingsConfigurationExtensionsTests.cs | 37 +- .../ReloadableLoggerTests.cs | 163 ++- .../Serilog.Extensions.Hosting.Tests.csproj | 4 +- .../SerilogHostBuilderExtensionsTests.cs | 167 ++- ...SerilogServiceCollectionExtensionsTests.cs | 97 +- .../Support/DisposeTrackingLogger.cs | 691 ++++++----- .../Support/ListSink.cs | 23 +- .../Support/Some.cs | 17 +- 29 files changed, 2298 insertions(+), 2325 deletions(-) diff --git a/samples/SimpleServiceSample/PrintTimeService.cs b/samples/SimpleServiceSample/PrintTimeService.cs index f88e137..5a1434a 100644 --- a/samples/SimpleServiceSample/PrintTimeService.cs +++ b/samples/SimpleServiceSample/PrintTimeService.cs @@ -4,24 +4,23 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace SimpleServiceSample +namespace SimpleServiceSample; + +public class PrintTimeService : BackgroundService { - public class PrintTimeService : BackgroundService - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public PrintTimeService(ILogger logger) - { - _logger = logger; - } + public PrintTimeService(ILogger logger) + { + _logger = logger; + } - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) { - while (!stoppingToken.IsCancellationRequested) - { - _logger.LogInformation("The current time is: {CurrentTime}", DateTimeOffset.UtcNow); - await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); - } + _logger.LogInformation("The current time is: {CurrentTime}", DateTimeOffset.UtcNow); + await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } } diff --git a/samples/SimpleServiceSample/Program.cs b/samples/SimpleServiceSample/Program.cs index ee7319f..c9a5b17 100644 --- a/samples/SimpleServiceSample/Program.cs +++ b/samples/SimpleServiceSample/Program.cs @@ -3,41 +3,40 @@ using Microsoft.Extensions.Hosting; using Serilog; -namespace SimpleServiceSample +namespace SimpleServiceSample; + +public static class Program { - public static class Program + public static int Main(string[] args) { - public static int Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateBootstrapLogger(); + Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateBootstrapLogger(); - try - { - Log.Information("Getting the motors running..."); - CreateHostBuilder(args).Build().Run(); - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "Host terminated unexpectedly"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } + try + { + Log.Information("Getting the motors running..."); + CreateHostBuilder(args).Build().Run(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly"); + return 1; + } + finally + { + Log.CloseAndFlush(); } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureServices(services => services.AddHostedService()) - .UseSerilog((context, services, loggerConfiguration) => loggerConfiguration - .ReadFrom.Configuration(context.Configuration) - .ReadFrom.Services(services) - .Enrich.FromLogContext() - .WriteTo.Console()); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices(services => services.AddHostedService()) + .UseSerilog((context, services, loggerConfiguration) => loggerConfiguration + .ReadFrom.Configuration(context.Configuration) + .ReadFrom.Services(services) + .Enrich.FromLogContext() + .WriteTo.Console()); } diff --git a/samples/WebApplicationSample/Program.cs b/samples/WebApplicationSample/Program.cs index 4cf73b8..7c1c019 100644 --- a/samples/WebApplicationSample/Program.cs +++ b/samples/WebApplicationSample/Program.cs @@ -3,42 +3,41 @@ using Microsoft.Extensions.Hosting; using Serilog; -namespace WebApplicationSample +namespace WebApplicationSample; + +public static class Program { - public static class Program + public static int Main(string[] args) { - public static int Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Console() - .CreateBootstrapLogger(); - - Log.Information("Starting up!"); + Log.Logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateBootstrapLogger(); + + Log.Information("Starting up!"); - try - { - CreateHostBuilder(args).Build().Run(); + try + { + CreateHostBuilder(args).Build().Run(); - Log.Information("Stopped cleanly"); - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "An unhandled exception occured during bootstrapping"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } + Log.Information("Stopped cleanly"); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "An unhandled exception occured during bootstrapping"); + return 1; + } + finally + { + Log.CloseAndFlush(); } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .UseSerilog((context, services, configuration) => configuration - .WriteTo.Console() - .ReadFrom.Configuration(context.Configuration) - .ReadFrom.Services(services)) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseSerilog((context, services, configuration) => configuration + .WriteTo.Console() + .ReadFrom.Configuration(context.Configuration) + .ReadFrom.Services(services)) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } \ No newline at end of file diff --git a/samples/WebApplicationSample/Startup.cs b/samples/WebApplicationSample/Startup.cs index 4fe346d..2ac4443 100644 --- a/samples/WebApplicationSample/Startup.cs +++ b/samples/WebApplicationSample/Startup.cs @@ -9,34 +9,33 @@ using Microsoft.Extensions.Hosting; using Serilog; -namespace WebApplicationSample +namespace WebApplicationSample; + +public class Startup { - public class Startup + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - } + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } + app.UseDeveloperExceptionPage(); + } - app.UseRouting(); + app.UseRouting(); - app.UseEndpoints(endpoints => + app.UseEndpoints(endpoints => + { + endpoints.MapGet("/", async context => { - endpoints.MapGet("/", async context => - { - Log.Information("Saying hello"); - await context.Response.WriteAsync("Hello World!"); - }); + Log.Information("Saying hello"); + await context.Response.WriteAsync("Hello World!"); }); - } + }); } } \ No newline at end of file diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs index 68010ee..02eb1c9 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs @@ -15,32 +15,31 @@ using System; using System.Threading; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +class AmbientDiagnosticContextCollector : IDisposable { - class AmbientDiagnosticContextCollector : IDisposable - { - static readonly AsyncLocal AmbientCollector = - new AsyncLocal(); + static readonly AsyncLocal AmbientCollector = + new AsyncLocal(); - // The indirection here ensures that completing collection cleans up the collector in all - // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-) - DiagnosticContextCollector _collector; + // The indirection here ensures that completing collection cleans up the collector in all + // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-) + DiagnosticContextCollector _collector; - public static DiagnosticContextCollector Current => AmbientCollector.Value?._collector; + public static DiagnosticContextCollector Current => AmbientCollector.Value?._collector; - public static DiagnosticContextCollector Begin() - { - var value = new AmbientDiagnosticContextCollector(); - value._collector = new DiagnosticContextCollector(value); - AmbientCollector.Value = value; - return value._collector; - } + public static DiagnosticContextCollector Begin() + { + var value = new AmbientDiagnosticContextCollector(); + value._collector = new DiagnosticContextCollector(value); + AmbientCollector.Value = value; + return value._collector; + } - public void Dispose() - { - _collector = null; - if (AmbientCollector.Value == this) - AmbientCollector.Value = null; - } + public void Dispose() + { + _collector = null; + if (AmbientCollector.Value == this) + AmbientCollector.Value = null; } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs index 3a8fee6..7f235e5 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs @@ -20,525 +20,524 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +class CachingReloadableLogger : ILogger, IReloadableLogger { - class CachingReloadableLogger : ILogger, IReloadableLogger + readonly ReloadableLogger _reloadableLogger; + readonly Func _configure; + readonly IReloadableLogger _parent; + + ILogger _root, _cached; + bool _frozen; + + public CachingReloadableLogger(ReloadableLogger reloadableLogger, ILogger root, IReloadableLogger parent, Func configure) { - readonly ReloadableLogger _reloadableLogger; - readonly Func _configure; - readonly IReloadableLogger _parent; - - ILogger _root, _cached; - bool _frozen; + _reloadableLogger = reloadableLogger; + _parent = parent; + _configure = configure; + _root = root; + _cached = null; + _frozen = false; + } - public CachingReloadableLogger(ReloadableLogger reloadableLogger, ILogger root, IReloadableLogger parent, Func configure) + public ILogger ReloadLogger() + { + return _configure(_parent.ReloadLogger()); + } + + public ILogger ForContext(ILogEventEnricher enricher) + { + if (enricher == null) return this; + + if (_frozen) + return _cached.ForContext(enricher); + + if (_reloadableLogger.CreateChild( + _root, + this, + _cached, + p => p.ForContext(enricher), + out var child, + out var newRoot, + out var newCached, + out var frozen)) { - _reloadableLogger = reloadableLogger; - _parent = parent; - _configure = configure; - _root = root; - _cached = null; - _frozen = false; + Update(newRoot, newCached, frozen); } - public ILogger ReloadLogger() + return child; + } + + public ILogger ForContext(IEnumerable enrichers) + { + if (enrichers == null) return this; + + if (_frozen) + return _cached.ForContext(enrichers); + + if (_reloadableLogger.CreateChild( + _root, + this, + _cached, + p => p.ForContext(enrichers), + out var child, + out var newRoot, + out var newCached, + out var frozen)) { - return _configure(_parent.ReloadLogger()); + Update(newRoot, newCached, frozen); } - public ILogger ForContext(ILogEventEnricher enricher) - { - if (enricher == null) return this; - - if (_frozen) - return _cached.ForContext(enricher); + return child; + } + + public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + if (propertyName == null) return this; + + if (_frozen) + return _cached.ForContext(propertyName, value, destructureObjects); + ILogger child; + if (value == null || value is string || value.GetType().IsPrimitive || value.GetType().IsEnum) + { + // Safe to extend the lifetime of `value` by closing over it. + // This ensures `SourceContext` is passed through appropriately and triggers minimum level overrides. if (_reloadableLogger.CreateChild( _root, this, - _cached, - p => p.ForContext(enricher), - out var child, + _cached, + p => p.ForContext(propertyName, value, destructureObjects), + out child, out var newRoot, out var newCached, out var frozen)) { Update(newRoot, newCached, frozen); } - - return child; } - - public ILogger ForContext(IEnumerable enrichers) + else { - if (enrichers == null) return this; - - if (_frozen) - return _cached.ForContext(enrichers); + // It's not safe to extend the lifetime of `value` or pass it unexpectedly between threads. + // Changes to destructuring configuration won't be picked up by the cached logger. + var eager = ReloadLogger(); + if (!eager.BindProperty(propertyName, value, destructureObjects, out var property)) + return this; + var enricher = new FixedPropertyEnricher(property); + if (_reloadableLogger.CreateChild( _root, this, - _cached, - p => p.ForContext(enrichers), - out var child, + _cached, + p => p.ForContext(enricher), + out child, out var newRoot, out var newCached, out var frozen)) { Update(newRoot, newCached, frozen); } + } + + return child; + } - return child; + public ILogger ForContext() + { + if (_frozen) + return _cached.ForContext(); + + if (_reloadableLogger.CreateChild( + _root, + this, + _cached, + p => p.ForContext(), + out var child, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } - public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + return child; + } + + public ILogger ForContext(Type source) + { + if (_frozen) + return _cached.ForContext(source); + + if (_reloadableLogger.CreateChild( + _root, + this, + _cached, + p => p.ForContext(source), + out var child, + out var newRoot, + out var newCached, + out var frozen)) { - if (propertyName == null) return this; - - if (_frozen) - return _cached.ForContext(propertyName, value, destructureObjects); + Update(newRoot, newCached, frozen); + } - ILogger child; - if (value == null || value is string || value.GetType().IsPrimitive || value.GetType().IsEnum) - { - // Safe to extend the lifetime of `value` by closing over it. - // This ensures `SourceContext` is passed through appropriately and triggers minimum level overrides. - if (_reloadableLogger.CreateChild( - _root, - this, - _cached, - p => p.ForContext(propertyName, value, destructureObjects), - out child, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } - } - else - { - // It's not safe to extend the lifetime of `value` or pass it unexpectedly between threads. - // Changes to destructuring configuration won't be picked up by the cached logger. - var eager = ReloadLogger(); - if (!eager.BindProperty(propertyName, value, destructureObjects, out var property)) - return this; + return child; + } - var enricher = new FixedPropertyEnricher(property); + void Update(ILogger newRoot, ILogger newCached, bool frozen) + { + _root = newRoot; + _cached = newCached; - if (_reloadableLogger.CreateChild( - _root, - this, - _cached, - p => p.ForContext(enricher), - out child, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } - } + // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431 + // Publish `_cached` and then `_frozen`. This is useful here because it means that once the logger is frozen - which + // we always expect - reads don't require any synchronization/interlocked instructions. + Interlocked.MemoryBarrierProcessWide(); - return child; - } + _frozen = frozen; - public ILogger ForContext() - { - if (_frozen) - return _cached.ForContext(); - - if (_reloadableLogger.CreateChild( - _root, - this, - _cached, - p => p.ForContext(), - out var child, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + Interlocked.MemoryBarrierProcessWide(); + } - return child; + public void Write(LogEvent logEvent) + { + if (_frozen) + { + _cached.Write(logEvent); + return; } - public ILogger ForContext(Type source) + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + logEvent, + out var newRoot, + out var newCached, + out var frozen)) { - if (_frozen) - return _cached.ForContext(source); - - if (_reloadableLogger.CreateChild( - _root, - this, - _cached, - p => p.ForContext(source), - out var child, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } - - return child; + Update(newRoot, newCached, frozen); } + } - void Update(ILogger newRoot, ILogger newCached, bool frozen) + public void Write(LogEventLevel level, string messageTemplate) + { + if (_frozen) { - _root = newRoot; - _cached = newCached; - - // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431 - // Publish `_cached` and then `_frozen`. This is useful here because it means that once the logger is frozen - which - // we always expect - reads don't require any synchronization/interlocked instructions. - Interlocked.MemoryBarrierProcessWide(); - - _frozen = frozen; - - Interlocked.MemoryBarrierProcessWide(); + _cached.Write(level, messageTemplate); + return; } - public void Write(LogEvent logEvent) + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + messageTemplate, + out var newRoot, + out var newCached, + out var frozen)) { - if (_frozen) - { - _cached.Write(logEvent); - return; - } - - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - logEvent, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, string messageTemplate) + public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, messageTemplate); - return; - } - - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - messageTemplate, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + _cached.Write(level, messageTemplate, propertyValue); + return; } - public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + messageTemplate, + propertyValue, + out var newRoot, + out var newCached, + out var frozen)) { - if (_frozen) - { - _cached.Write(level, messageTemplate, propertyValue); - return; - } - - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - messageTemplate, - propertyValue, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, messageTemplate, propertyValue0, propertyValue1); - return; - } + _cached.Write(level, messageTemplate, propertyValue0, propertyValue1); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - messageTemplate, - propertyValue0, - propertyValue1, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + messageTemplate, + propertyValue0, + propertyValue1, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return; - } + _cached.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - messageTemplate, - propertyValue0, - propertyValue1, - propertyValue2, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + messageTemplate, + propertyValue0, + propertyValue1, + propertyValue2, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, messageTemplate, propertyValues); - return; - } + _cached.Write(level, messageTemplate, propertyValues); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - messageTemplate, - propertyValues, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + messageTemplate, + propertyValues, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, Exception exception, string messageTemplate) + public void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, exception, messageTemplate); - return; - } + _cached.Write(level, exception, messageTemplate); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - exception, - messageTemplate, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + exception, + messageTemplate, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, exception, messageTemplate, propertyValue); - return; - } + _cached.Write(level, exception, messageTemplate, propertyValue); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - exception, - messageTemplate, - propertyValue, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + exception, + messageTemplate, + propertyValue, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, - T1 propertyValue1) + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); - return; - } + _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - exception, - messageTemplate, - propertyValue0, - propertyValue1, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + exception, + messageTemplate, + propertyValue0, + propertyValue1, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, - T1 propertyValue1, T2 propertyValue2) + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1, T2 propertyValue2) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return; - } + _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - exception, - messageTemplate, - propertyValue0, - propertyValue1, - propertyValue2, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + exception, + messageTemplate, + propertyValue0, + propertyValue1, + propertyValue2, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + if (_frozen) { - if (_frozen) - { - _cached.Write(level, exception, messageTemplate, propertyValues); - return; - } + _cached.Write(level, exception, messageTemplate, propertyValues); + return; + } - if (_reloadableLogger.InvokeWrite( - _root, - _cached, - this, - level, - exception, - messageTemplate, - propertyValues, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeWrite( + _root, + _cached, + this, + level, + exception, + messageTemplate, + propertyValues, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); } + } - public bool IsEnabled(LogEventLevel level) + public bool IsEnabled(LogEventLevel level) + { + if (_frozen) { - if (_frozen) - { - return _cached.IsEnabled(level); - } + return _cached.IsEnabled(level); + } - if (_reloadableLogger.InvokeIsEnabled( - _root, - _cached, - this, - level, - out var isEnabled, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + if (_reloadableLogger.InvokeIsEnabled( + _root, + _cached, + this, + level, + out var isEnabled, + out var newRoot, + out var newCached, + out var frozen)) + { + Update(newRoot, newCached, frozen); + } - return isEnabled; + return isEnabled; + } + + public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, + out IEnumerable boundProperties) + { + if (_frozen) + { + return _cached.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); } - - public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, - out IEnumerable boundProperties) + + if (_reloadableLogger.InvokeBindMessageTemplate( + _root, + _cached, + this, + messageTemplate, + propertyValues, + out parsedTemplate, + out boundProperties, + out var canBind, + out var newRoot, + out var newCached, + out var frozen)) { - if (_frozen) - { - return _cached.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); - } + Update(newRoot, newCached, frozen); + } - if (_reloadableLogger.InvokeBindMessageTemplate( - _root, - _cached, - this, - messageTemplate, - propertyValues, - out parsedTemplate, - out boundProperties, - out var canBind, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } + return canBind; + } - return canBind; + public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + if (_frozen) + { + return _cached.BindProperty(propertyName, value, destructureObjects, out property); } - public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + if (_reloadableLogger.InvokeBindProperty( + _root, + _cached, + this, + propertyName, + value, + destructureObjects, + out property, + out var canBind, + out var newRoot, + out var newCached, + out var frozen)) { - if (_frozen) - { - return _cached.BindProperty(propertyName, value, destructureObjects, out property); - } - - if (_reloadableLogger.InvokeBindProperty( - _root, - _cached, - this, - propertyName, - value, - destructureObjects, - out property, - out var canBind, - out var newRoot, - out var newCached, - out var frozen)) - { - Update(newRoot, newCached, frozen); - } - - return canBind; + Update(newRoot, newCached, frozen); } + + return canBind; } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs index 44462ac..7f4ee2b 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs @@ -15,53 +15,52 @@ using System; using System.Threading; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +/// +/// Implements an ambient diagnostic context using . +/// +/// Consumers should use to set context properties. +public sealed class DiagnosticContext : IDiagnosticContext { + readonly ILogger _logger; + /// - /// Implements an ambient diagnostic context using . + /// Construct a . /// - /// Consumers should use to set context properties. - public sealed class DiagnosticContext : IDiagnosticContext + /// A logger for binding properties in the context, or null to use . + public DiagnosticContext(ILogger logger) { - readonly ILogger _logger; + _logger = logger; + } - /// - /// Construct a . - /// - /// A logger for binding properties in the context, or null to use . - public DiagnosticContext(ILogger logger) - { - _logger = logger; - } + /// + /// Start collecting properties to associate with the current diagnostic context. This will replace + /// the active collector, if any. + /// + /// A collector that will receive properties added in the current diagnostic context. + public DiagnosticContextCollector BeginCollection() + { + return AmbientDiagnosticContextCollector.Begin(); + } - /// - /// Start collecting properties to associate with the current diagnostic context. This will replace - /// the active collector, if any. - /// - /// A collector that will receive properties added in the current diagnostic context. - public DiagnosticContextCollector BeginCollection() - { - return AmbientDiagnosticContextCollector.Begin(); - } + /// + public void Set(string propertyName, object value, bool destructureObjects = false) + { + if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); - /// - public void Set(string propertyName, object value, bool destructureObjects = false) + var collector = AmbientDiagnosticContextCollector.Current; + if (collector != null && + (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property)) { - if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); - - var collector = AmbientDiagnosticContextCollector.Current; - if (collector != null && - (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property)) - { - collector.AddOrUpdate(property); - } + collector.AddOrUpdate(property); } + } - /// - public void SetException(Exception exception) - { - var collector = AmbientDiagnosticContextCollector.Current; - collector?.SetException(exception); - } + /// + public void SetException(Exception exception) + { + var collector = AmbientDiagnosticContextCollector.Current; + collector?.SetException(exception); } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs index 63c6339..05734f6 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs @@ -2,106 +2,105 @@ using System.Collections.Generic; using Serilog.Events; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +/// +/// A container that receives properties added to a diagnostic context. +/// +public sealed class DiagnosticContextCollector : IDisposable { + readonly IDisposable _chainedDisposable; + readonly object _propertiesLock = new object(); + Exception _exception; + Dictionary _properties = new Dictionary(); + /// - /// A container that receives properties added to a diagnostic context. + /// Construct a . /// - public sealed class DiagnosticContextCollector : IDisposable + /// An object that will be disposed to signal completion/disposal of + /// the collector. + public DiagnosticContextCollector(IDisposable chainedDisposable) { - readonly IDisposable _chainedDisposable; - readonly object _propertiesLock = new object(); - Exception _exception; - Dictionary _properties = new Dictionary(); + _chainedDisposable = chainedDisposable ?? throw new ArgumentNullException(nameof(chainedDisposable)); + } - /// - /// Construct a . - /// - /// An object that will be disposed to signal completion/disposal of - /// the collector. - public DiagnosticContextCollector(IDisposable chainedDisposable) - { - _chainedDisposable = chainedDisposable ?? throw new ArgumentNullException(nameof(chainedDisposable)); - } + /// + /// Add the property to the context. + /// + /// The property to add. + public void AddOrUpdate(LogEventProperty property) + { + if (property == null) throw new ArgumentNullException(nameof(property)); - /// - /// Add the property to the context. - /// - /// The property to add. - public void AddOrUpdate(LogEventProperty property) + lock (_propertiesLock) { - if (property == null) throw new ArgumentNullException(nameof(property)); - - lock (_propertiesLock) - { - if (_properties == null) return; - _properties[property.Name] = property; - } + if (_properties == null) return; + _properties[property.Name] = property; } + } - /// - /// Set the exception associated with the current diagnostic context. - /// - /// - /// Passing an exception to the diagnostic context is useful when unhandled exceptions are handled before reaching Serilog's - /// RequestLoggingMiddleware. One example is using https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails to transform - /// exceptions to ProblemDetails responses. - /// - /// - /// If an unhandled exception reaches Serilog's RequestLoggingMiddleware, then the unhandled exception takes precedence.
- /// If null is given, it clears any previously assigned exception. - ///
- /// The exception to log. - public void SetException(Exception exception) + /// + /// Set the exception associated with the current diagnostic context. + /// + /// + /// Passing an exception to the diagnostic context is useful when unhandled exceptions are handled before reaching Serilog's + /// RequestLoggingMiddleware. One example is using https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails to transform + /// exceptions to ProblemDetails responses. + /// + /// + /// If an unhandled exception reaches Serilog's RequestLoggingMiddleware, then the unhandled exception takes precedence.
+ /// If null is given, it clears any previously assigned exception. + ///
+ /// The exception to log. + public void SetException(Exception exception) + { + lock (_propertiesLock) { - lock (_propertiesLock) - { - if (_properties == null) return; - _exception = exception; - } + if (_properties == null) return; + _exception = exception; } + } - /// - /// Complete the context and retrieve the properties added to it, if any. This will - /// stop collection and remove the collector from the original execution context and - /// any of its children. - /// - /// The collected properties, or null if no collection is active. - /// True if properties could be collected. - /// - [Obsolete("Replaced by TryComplete(out IEnumerable properties, out Exception exception).")] - public bool TryComplete(out IEnumerable properties) - { - return TryComplete(out properties, out _); - } + /// + /// Complete the context and retrieve the properties added to it, if any. This will + /// stop collection and remove the collector from the original execution context and + /// any of its children. + /// + /// The collected properties, or null if no collection is active. + /// True if properties could be collected. + /// + [Obsolete("Replaced by TryComplete(out IEnumerable properties, out Exception exception).")] + public bool TryComplete(out IEnumerable properties) + { + return TryComplete(out properties, out _); + } - /// - /// Complete the context and retrieve the properties and exception added to it, if any. This will - /// stop collection and remove the collector from the original execution context and - /// any of its children. - /// - /// The collected properties, or null if no collection is active. - /// The collected exception, or null if none has been collected or if no collection is active. - /// True if properties could be collected. - /// - /// - public bool TryComplete(out IEnumerable properties, out Exception exception) + /// + /// Complete the context and retrieve the properties and exception added to it, if any. This will + /// stop collection and remove the collector from the original execution context and + /// any of its children. + /// + /// The collected properties, or null if no collection is active. + /// The collected exception, or null if none has been collected or if no collection is active. + /// True if properties could be collected. + /// + /// + public bool TryComplete(out IEnumerable properties, out Exception exception) + { + lock (_propertiesLock) { - lock (_propertiesLock) - { - properties = _properties?.Values; - exception = _exception; - _properties = null; - _exception = null; - Dispose(); - return properties != null; - } + properties = _properties?.Values; + exception = _exception; + _properties = null; + _exception = null; + Dispose(); + return properties != null; } + } - /// - public void Dispose() - { - _chainedDisposable.Dispose(); - } + /// + public void Dispose() + { + _chainedDisposable.Dispose(); } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs index 3543173..d552194 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/FixedPropertyEnricher.cs @@ -15,20 +15,19 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +class FixedPropertyEnricher : ILogEventEnricher { - class FixedPropertyEnricher : ILogEventEnricher - { - readonly LogEventProperty _property; + readonly LogEventProperty _property; - public FixedPropertyEnricher(LogEventProperty property) - { - _property = property; - } + public FixedPropertyEnricher(LogEventProperty property) + { + _property = property; + } - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - { - logEvent.AddPropertyIfAbsent(_property); - } + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + logEvent.AddPropertyIfAbsent(_property); } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs index 07b4cf9..a3c2de4 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/IReloadableLogger.cs @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +interface IReloadableLogger { - interface IReloadableLogger - { - ILogger ReloadLogger(); - } + ILogger ReloadLogger(); } \ No newline at end of file diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs index 97e37ea..d879bf8 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs @@ -3,37 +3,36 @@ using Serilog.Configuration; using Serilog.Core; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +class InjectedLoggerSettings : ILoggerSettings { - class InjectedLoggerSettings : ILoggerSettings - { - readonly IServiceProvider _services; + readonly IServiceProvider _services; - public InjectedLoggerSettings(IServiceProvider services) - { - _services = services ?? throw new ArgumentNullException(nameof(services)); - } + public InjectedLoggerSettings(IServiceProvider services) + { + _services = services ?? throw new ArgumentNullException(nameof(services)); + } - public void Configure(LoggerConfiguration loggerConfiguration) - { - var levelSwitch = _services.GetService(); - if (levelSwitch != null) - loggerConfiguration.MinimumLevel.ControlledBy(levelSwitch); - - foreach (var settings in _services.GetServices()) - loggerConfiguration.ReadFrom.Settings(settings); + public void Configure(LoggerConfiguration loggerConfiguration) + { + var levelSwitch = _services.GetService(); + if (levelSwitch != null) + loggerConfiguration.MinimumLevel.ControlledBy(levelSwitch); + + foreach (var settings in _services.GetServices()) + loggerConfiguration.ReadFrom.Settings(settings); - foreach (var policy in _services.GetServices()) - loggerConfiguration.Destructure.With(policy); + foreach (var policy in _services.GetServices()) + loggerConfiguration.Destructure.With(policy); - foreach (var enricher in _services.GetServices()) - loggerConfiguration.Enrich.With(enricher); - - foreach (var filter in _services.GetServices()) - loggerConfiguration.Filter.With(filter); - - foreach (var sink in _services.GetServices()) - loggerConfiguration.WriteTo.Sink(sink); - } + foreach (var enricher in _services.GetServices()) + loggerConfiguration.Enrich.With(enricher); + + foreach (var filter in _services.GetServices()) + loggerConfiguration.Filter.With(filter); + + foreach (var sink in _services.GetServices()) + loggerConfiguration.WriteTo.Sink(sink); } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs index af13dfc..ea6ace3 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/NullEnricher.cs @@ -15,14 +15,13 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +// Does nothing, but makes it easy to create an `ILogger` from a Serilog `Logger` +// that will not dispose the underlying pipeline when disposed itself. +class NullEnricher : ILogEventEnricher { - // Does nothing, but makes it easy to create an `ILogger` from a Serilog `Logger` - // that will not dispose the underlying pipeline when disposed itself. - class NullEnricher : ILogEventEnricher + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - { - } } } \ No newline at end of file diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs index 6ec1d37..729ae35 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs @@ -23,663 +23,662 @@ // ReSharper disable MemberCanBePrivate.Global -namespace Serilog.Extensions.Hosting +namespace Serilog.Extensions.Hosting; + +/// +/// A Serilog that can be reconfigured without invalidating existing +/// instances derived from it. +/// +public sealed class ReloadableLogger : ILogger, IReloadableLogger, IDisposable { + readonly object _sync = new object(); + Logger _logger; + + // One-way; if the value is `true` it can never again be made `false`, allowing "double-checked" reads. If + // `true`, `_logger` is final and a memory barrier ensures the final value is seen by all threads. + bool _frozen; + + // Unsure whether this should be exposed; currently going for minimal API surface. + internal ReloadableLogger(Logger initial) + { + _logger = initial ?? throw new ArgumentNullException(nameof(initial)); + } + + ILogger IReloadableLogger.ReloadLogger() + { + return _logger; + } + /// - /// A Serilog that can be reconfigured without invalidating existing - /// instances derived from it. + /// Reload the logger using the supplied configuration delegate. /// - public sealed class ReloadableLogger : ILogger, IReloadableLogger, IDisposable + /// A callback in which the logger is reconfigured. + /// is null. + public void Reload(Func configure) { - readonly object _sync = new object(); - Logger _logger; + if (configure == null) throw new ArgumentNullException(nameof(configure)); - // One-way; if the value is `true` it can never again be made `false`, allowing "double-checked" reads. If - // `true`, `_logger` is final and a memory barrier ensures the final value is seen by all threads. - bool _frozen; - - // Unsure whether this should be exposed; currently going for minimal API surface. - internal ReloadableLogger(Logger initial) + lock (_sync) { - _logger = initial ?? throw new ArgumentNullException(nameof(initial)); - } - - ILogger IReloadableLogger.ReloadLogger() - { - return _logger; + _logger.Dispose(); + _logger = configure(new LoggerConfiguration()).CreateLogger(); } + } - /// - /// Reload the logger using the supplied configuration delegate. - /// - /// A callback in which the logger is reconfigured. - /// is null. - public void Reload(Func configure) + /// + /// Freeze the logger, so that no further reconfiguration is possible. Once the logger is frozen, logging through + /// new contextual loggers will have no additional cost, and logging directly through this logger will not require + /// any synchronization. + /// + /// The configured with the final settings. + /// The logger is already frozen. + public Logger Freeze() + { + lock (_sync) { - if (configure == null) throw new ArgumentNullException(nameof(configure)); + if (_frozen) + throw new InvalidOperationException("The logger is already frozen."); + + _frozen = true; + + // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431 + // Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which + // we always expect - reads don't require any synchronization/interlocked instructions. + Interlocked.MemoryBarrierProcessWide(); - lock (_sync) - { - _logger.Dispose(); - _logger = configure(new LoggerConfiguration()).CreateLogger(); - } + return _logger; } + } - /// - /// Freeze the logger, so that no further reconfiguration is possible. Once the logger is frozen, logging through - /// new contextual loggers will have no additional cost, and logging directly through this logger will not require - /// any synchronization. - /// - /// The configured with the final settings. - /// The logger is already frozen. - public Logger Freeze() - { - lock (_sync) - { - if (_frozen) - throw new InvalidOperationException("The logger is already frozen."); + /// + public void Dispose() + { + lock (_sync) + _logger.Dispose(); + } - _frozen = true; + /// + public ILogger ForContext(ILogEventEnricher enricher) + { + if (enricher == null) return this; + + if (_frozen) + return _logger.ForContext(enricher); - // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431 - // Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which - // we always expect - reads don't require any synchronization/interlocked instructions. - Interlocked.MemoryBarrierProcessWide(); - - return _logger; - } - } + lock (_sync) + return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enricher)); + } - /// - public void Dispose() + /// + public ILogger ForContext(IEnumerable enrichers) + { + if (enrichers == null) return this; + + if (_frozen) + return _logger.ForContext(enrichers); + + lock (_sync) + return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enrichers)); + } + + /// + public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + if (propertyName == null) return this; + + if (_frozen) + return _logger.ForContext(propertyName, value, destructureObjects); + + lock (_sync) + return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(propertyName, value, destructureObjects)); + } + + /// + public ILogger ForContext() + { + if (_frozen) + return _logger.ForContext(); + + lock (_sync) + return new CachingReloadableLogger(this, _logger, this, p => p.ForContext()); + } + + /// + public ILogger ForContext(Type source) + { + if (source == null) return this; + + if (_frozen) + return _logger.ForContext(source); + + lock (_sync) + return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(source)); + } + + /// + public void Write(LogEvent logEvent) + { + if (_frozen) { - lock (_sync) - _logger.Dispose(); + _logger.Write(logEvent); + return; } - /// - public ILogger ForContext(ILogEventEnricher enricher) + lock (_sync) { - if (enricher == null) return this; - - if (_frozen) - return _logger.ForContext(enricher); - - lock (_sync) - return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enricher)); + _logger.Write(logEvent); } + } - /// - public ILogger ForContext(IEnumerable enrichers) + /// + public void Write(LogEventLevel level, string messageTemplate) + { + if (_frozen) { - if (enrichers == null) return this; - - if (_frozen) - return _logger.ForContext(enrichers); - - lock (_sync) - return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(enrichers)); + _logger.Write(level, messageTemplate); + return; } - /// - public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + lock (_sync) { - if (propertyName == null) return this; - - if (_frozen) - return _logger.ForContext(propertyName, value, destructureObjects); + _logger.Write(level, messageTemplate); + } + } - lock (_sync) - return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(propertyName, value, destructureObjects)); + /// + public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + if (_frozen) + { + _logger.Write(level, messageTemplate, propertyValue); + return; } - /// - public ILogger ForContext() + lock (_sync) { - if (_frozen) - return _logger.ForContext(); + _logger.Write(level, messageTemplate, propertyValue); + } + } - lock (_sync) - return new CachingReloadableLogger(this, _logger, this, p => p.ForContext()); + /// + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + if (_frozen) + { + _logger.Write(level, messageTemplate, propertyValue0, propertyValue1); + return; } - /// - public ILogger ForContext(Type source) + lock (_sync) { - if (source == null) return this; - - if (_frozen) - return _logger.ForContext(source); + _logger.Write(level, messageTemplate, propertyValue0, propertyValue1); + } + } - lock (_sync) - return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(source)); + /// + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + if (_frozen) + { + _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return; } - /// - public void Write(LogEvent logEvent) + lock (_sync) { - if (_frozen) - { - _logger.Write(logEvent); - return; - } + _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + } - lock (_sync) - { - _logger.Write(logEvent); - } + /// + public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + if (_frozen) + { + _logger.Write(level, messageTemplate, propertyValues); + return; } - /// - public void Write(LogEventLevel level, string messageTemplate) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, messageTemplate); - return; - } + _logger.Write(level, messageTemplate, propertyValues); + } + } - lock (_sync) - { - _logger.Write(level, messageTemplate); - } + /// + public void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + if (_frozen) + { + _logger.Write(level, exception, messageTemplate); + return; } - /// - public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, messageTemplate, propertyValue); - return; - } + _logger.Write(level, exception, messageTemplate); + } + } - lock (_sync) - { - _logger.Write(level, messageTemplate, propertyValue); - } + /// + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + if (_frozen) + { + _logger.Write(level, exception, messageTemplate, propertyValue); + return; } - /// - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, messageTemplate, propertyValue0, propertyValue1); - return; - } + _logger.Write(level, exception, messageTemplate, propertyValue); + } + } - lock (_sync) - { - _logger.Write(level, messageTemplate, propertyValue0, propertyValue1); - } + /// + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + if (_frozen) + { + _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + return; } - /// - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return; - } + _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + } + } - lock (_sync) - { - _logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - } + /// + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + if (_frozen) + { + _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return; } - /// - public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, messageTemplate, propertyValues); - return; - } + _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + } - lock (_sync) - { - _logger.Write(level, messageTemplate, propertyValues); - } + /// + public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + if (_frozen) + { + _logger.Write(level, exception, messageTemplate, propertyValues); + return; } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, exception, messageTemplate); - return; - } + _logger.Write(level, exception, messageTemplate, propertyValues); + } + } - lock (_sync) - { - _logger.Write(level, exception, messageTemplate); - } + /// + public bool IsEnabled(LogEventLevel level) + { + if (_frozen) + { + return _logger.IsEnabled(level); } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, exception, messageTemplate, propertyValue); - return; - } + return _logger.IsEnabled(level); + } + } + + /// + public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, + out IEnumerable boundProperties) + { + if (_frozen) + { + return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + } - lock (_sync) - { - _logger.Write(level, exception, messageTemplate, propertyValue); - } + lock (_sync) + { + return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); } + } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + /// + public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + if (_frozen) { - if (_frozen) - { - _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); - return; - } + return _logger.BindProperty(propertyName, value, destructureObjects, out property); + } - lock (_sync) - { - _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); - } + lock (_sync) + { + return _logger.BindProperty(propertyName, value, destructureObjects, out property); } + } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + (ILogger, bool) UpdateForCaller(ILogger root, ILogger cached, IReloadableLogger caller, out ILogger newRoot, out ILogger newCached, out bool frozen) + { + // Synchronization on `_sync` is not required in this method; it will be called without a lock + // if `_frozen` and under a lock if not. + + if (_frozen) { - if (_frozen) - { - _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return; - } + // If we're frozen, then the caller hasn't observed this yet and should update. We could optimize a little here + // and only signal an update if the cached logger is stale (as per the next condition below). + newRoot = _logger; + newCached = caller.ReloadLogger(); + frozen = true; + return (newCached, true); + } - lock (_sync) - { - _logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - } + if (cached != null && root == _logger) + { + newRoot = default; + newCached = default; + frozen = false; + return (cached, false); + } + + newRoot = _logger; + newCached = caller.ReloadLogger(); + frozen = false; + return (newCached, true); + } + + internal bool InvokeIsEnabled(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, out bool isEnabled, out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + isEnabled = logger.IsEnabled(level); + return update; } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + lock (_sync) { - if (_frozen) - { - _logger.Write(level, exception, messageTemplate, propertyValues); - return; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + isEnabled = logger.IsEnabled(level); + return update; + } + } + + internal bool InvokeBindMessageTemplate(ILogger root, ILogger cached, IReloadableLogger caller, string messageTemplate, + object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties, + out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + return update; + } - lock (_sync) - { - _logger.Write(level, exception, messageTemplate, propertyValues); - } + lock (_sync) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + return update; + } + } + + internal bool InvokeBindProperty(ILogger root, ILogger cached, IReloadableLogger caller, string propertyName, + object propertyValue, bool destructureObjects, out LogEventProperty property, + out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property); + return update; } - /// - public bool IsEnabled(LogEventLevel level) + lock (_sync) { - if (_frozen) - { - return _logger.IsEnabled(level); - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property); + return update; + } + } - lock (_sync) - { - return _logger.IsEnabled(level); - } + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(logEvent); + return update; } - - /// - public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, - out IEnumerable boundProperties) + + lock (_sync) { - if (_frozen) - { - return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(logEvent); + return update; + } + } - lock (_sync) - { - return _logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); - } + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate); + return update; } - /// - public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + lock (_sync) { - if (_frozen) - { - return _logger.BindProperty(propertyName, value, destructureObjects, out property); - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate); + return update; + } + } - lock (_sync) - { - return _logger.BindProperty(propertyName, value, destructureObjects, out property); - } + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + T propertyValue, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue); + return update; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - (ILogger, bool) UpdateForCaller(ILogger root, ILogger cached, IReloadableLogger caller, out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - // Synchronization on `_sync` is not required in this method; it will be called without a lock - // if `_frozen` and under a lock if not. - - if (_frozen) - { - // If we're frozen, then the caller hasn't observed this yet and should update. We could optimize a little here - // and only signal an update if the cached logger is stale (as per the next condition below). - newRoot = _logger; - newCached = caller.ReloadLogger(); - frozen = true; - return (newCached, true); - } - - if (cached != null && root == _logger) - { - newRoot = default; - newCached = default; - frozen = false; - return (cached, false); - } - - newRoot = _logger; - newCached = caller.ReloadLogger(); - frozen = false; - return (newCached, true); + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue); + return update; } - - internal bool InvokeIsEnabled(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, out bool isEnabled, out ILogger newRoot, out ILogger newCached, out bool frozen) + } + + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + T0 propertyValue0, T1 propertyValue1, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - isEnabled = logger.IsEnabled(level); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - isEnabled = logger.IsEnabled(level); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue0, propertyValue1); + return update; } - - internal bool InvokeBindMessageTemplate(ILogger root, ILogger cached, IReloadableLogger caller, string messageTemplate, - object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties, - out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen) + + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - canBind = logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue0, propertyValue1); + return update; } - - internal bool InvokeBindProperty(ILogger root, ILogger cached, IReloadableLogger caller, string propertyName, - object propertyValue, bool destructureObjects, out LogEventProperty property, - out bool canBind, out ILogger newRoot, out ILogger newCached, out bool frozen) + } + + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - canBind = logger.BindProperty(propertyName, propertyValue, destructureObjects, out property); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return update; } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(logEvent); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(logEvent); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return update; } + } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - out ILogger newRoot, out ILogger newCached, out bool frozen) + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + object[] propertyValues, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValues); + return update; } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - T propertyValue, - out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, messageTemplate, propertyValues); + return update; } - - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - T0 propertyValue0, T1 propertyValue1, - out ILogger newRoot, out ILogger newCached, out bool frozen) + } + + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue0, propertyValue1); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue0, propertyValue1); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate); + return update; } - - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, - out ILogger newRoot, out ILogger newCached, out bool frozen) + + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate); + return update; + } + } - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return update; - } + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + T propertyValue, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue); + return update; } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - object[] propertyValues, - out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValues); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, messageTemplate, propertyValues); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue); + return update; } - - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, - out ILogger newRoot, out ILogger newCached, out bool frozen) + } + + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + T0 propertyValue0, T1 propertyValue1, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + return update; } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, - T propertyValue, - out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + return update; } - - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, - T0 propertyValue0, T1 propertyValue1, - out ILogger newRoot, out ILogger newCached, out bool frozen) + } + + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return update; } - - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, - T0 propertyValue0, T1 propertyValue1, T2 propertyValue2, - out ILogger newRoot, out ILogger newCached, out bool frozen) + + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return update; - } + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + return update; + } + } - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); - return update; - } + internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + object[] propertyValues, + out ILogger newRoot, out ILogger newCached, out bool frozen) + { + if (_frozen) + { + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValues); + return update; } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, - object[] propertyValues, - out ILogger newRoot, out ILogger newCached, out bool frozen) + lock (_sync) { - if (_frozen) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValues); - return update; - } - - lock (_sync) - { - var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); - logger.Write(level, exception, messageTemplate, propertyValues); - return update; - } - } - - internal bool CreateChild( - ILogger root, - IReloadableLogger parent, - ILogger cachedParent, - Func configureChild, - out ILogger child, - out ILogger newRoot, - out ILogger newCached, - out bool frozen) + var (logger, update) = UpdateForCaller(root, cached, caller, out newRoot, out newCached, out frozen); + logger.Write(level, exception, messageTemplate, propertyValues); + return update; + } + } + + internal bool CreateChild( + ILogger root, + IReloadableLogger parent, + ILogger cachedParent, + Func configureChild, + out ILogger child, + out ILogger newRoot, + out ILogger newCached, + out bool frozen) + { + if (_frozen) { - if (_frozen) - { - var (logger, _) = UpdateForCaller(root, cachedParent, parent, out newRoot, out newCached, out frozen); - child = configureChild(logger); - return true; // Always an update, since the caller has not observed that the reloadable logger is frozen. - } - - // No synchronization, here - a lot of loggers are created and thrown away again without ever being used, - // so we just return a lazy wrapper. - child = new CachingReloadableLogger(this, root, parent, configureChild); - newRoot = default; - newCached = default; - frozen = default; - return false; + var (logger, _) = UpdateForCaller(root, cachedParent, parent, out newRoot, out newCached, out frozen); + child = configureChild(logger); + return true; // Always an update, since the caller has not observed that the reloadable logger is frozen. } + + // No synchronization, here - a lot of loggers are created and thrown away again without ever being used, + // so we just return a lazy wrapper. + child = new CachingReloadableLogger(this, root, parent, configureChild); + newRoot = default; + newCached = default; + frozen = default; + return false; } } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs index 1b100b9..f60dae3 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs @@ -21,56 +21,55 @@ // To line up with the convention used elsewhere in the *.Extensions libraries, this // should have been Serilog.Extensions.Hosting. // ReSharper disable once CheckNamespace -namespace Serilog.Hosting +namespace Serilog.Hosting; + +/// +/// Implements so that we can inject Serilog Logger. +/// +[Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")] +[EditorBrowsable(EditorBrowsableState.Never)] +public class SerilogLoggerFactory : ILoggerFactory { + readonly SerilogLoggerProvider _provider; + /// - /// Implements so that we can inject Serilog Logger. + /// Initializes a new instance of the class. /// - [Obsolete("Replaced with Serilog.Extensions.Logging.SerilogLoggerFactory")] - [EditorBrowsable(EditorBrowsableState.Never)] - public class SerilogLoggerFactory : ILoggerFactory + /// The Serilog logger; if not supplied, the static will be used. + /// When true, dispose when the framework disposes the provider. If the + /// logger is not specified but is true, the method will be + /// called on the static class instead. + public SerilogLoggerFactory(ILogger logger = null, bool dispose = false) { - readonly SerilogLoggerProvider _provider; - - /// - /// Initializes a new instance of the class. - /// - /// The Serilog logger; if not supplied, the static will be used. - /// When true, dispose when the framework disposes the provider. If the - /// logger is not specified but is true, the method will be - /// called on the static class instead. - public SerilogLoggerFactory(ILogger logger = null, bool dispose = false) - { - _provider = new SerilogLoggerProvider(logger, dispose); - } + _provider = new SerilogLoggerProvider(logger, dispose); + } - /// - /// Disposes the provider. - /// - public void Dispose() - { - _provider.Dispose(); - } + /// + /// Disposes the provider. + /// + public void Dispose() + { + _provider.Dispose(); + } - /// - /// Creates a new instance. - /// - /// The category name for messages produced by the logger. - /// - /// The . - /// - public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) - { - return _provider.CreateLogger(categoryName); - } + /// + /// Creates a new instance. + /// + /// The category name for messages produced by the logger. + /// + /// The . + /// + public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) + { + return _provider.CreateLogger(categoryName); + } - /// - /// Adds an to the logging system. - /// - /// The . - public void AddProvider(ILoggerProvider provider) - { - SelfLog.WriteLine("Ignoring add logger provider {0}", provider); - } + /// + /// Adds an to the logging system. + /// + /// The . + public void AddProvider(ILoggerProvider provider) + { + SelfLog.WriteLine("Ignoring add logger provider {0}", provider); } } diff --git a/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs index 79da237..c867cf7 100644 --- a/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs +++ b/src/Serilog.Extensions.Hosting/IDiagnosticContext.cs @@ -14,32 +14,31 @@ using System; -namespace Serilog +namespace Serilog; + +/// +/// Collects diagnostic information for packaging into wide events. +/// +public interface IDiagnosticContext { /// - /// Collects diagnostic information for packaging into wide events. + /// Set the specified property on the current diagnostic context. The property will be collected + /// and attached to the event emitted at the completion of the context. /// - public interface IDiagnosticContext - { - /// - /// Set the specified property on the current diagnostic context. The property will be collected - /// and attached to the event emitted at the completion of the context. - /// - /// The name of the property. Must be non-empty. - /// The property value. - /// If true, the value will be serialized as structured - /// data if possible; if false, the object will be recorded as a scalar or simple array. - void Set(string propertyName, object value, bool destructureObjects = false); + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as structured + /// data if possible; if false, the object will be recorded as a scalar or simple array. + void Set(string propertyName, object value, bool destructureObjects = false); - /// - /// Set the specified exception on the current diagnostic context. - /// - /// - /// This method is useful when unhandled exceptions do not reach Serilog.AspNetCore.RequestLoggingMiddleware, - /// such as when using Hellang.Middleware.ProblemDetails - /// to transform exceptions to ProblemDetails responses. - /// - /// The exception to log. If null is given, it clears any previously assigned exception. - void SetException(Exception exception); - } + /// + /// Set the specified exception on the current diagnostic context. + /// + /// + /// This method is useful when unhandled exceptions do not reach Serilog.AspNetCore.RequestLoggingMiddleware, + /// such as when using Hellang.Middleware.ProblemDetails + /// to transform exceptions to ProblemDetails responses. + /// + /// The exception to log. If null is given, it clears any previously assigned exception. + void SetException(Exception exception); } diff --git a/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs b/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs index 51a02d1..8511c34 100644 --- a/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs +++ b/src/Serilog.Extensions.Hosting/LoggerConfigurationExtensions.cs @@ -18,26 +18,25 @@ using Serilog.Extensions.Hosting; using System; -namespace Serilog +namespace Serilog; + +/// +/// Extends . +/// +public static class LoggerConfigurationExtensions { /// - /// Extends . + /// Create a for use during host bootstrapping. The + /// + /// configuration overload will detect when is set to a instance, and + /// reconfigure/freeze it so that s created during host bootstrapping continue to work once + /// logger configuration (with access to host services) is completed. /// - public static class LoggerConfigurationExtensions + /// + /// + public static ReloadableLogger CreateBootstrapLogger(this LoggerConfiguration loggerConfiguration) { - /// - /// Create a for use during host bootstrapping. The - /// - /// configuration overload will detect when is set to a instance, and - /// reconfigure/freeze it so that s created during host bootstrapping continue to work once - /// logger configuration (with access to host services) is completed. - /// - /// - /// - public static ReloadableLogger CreateBootstrapLogger(this LoggerConfiguration loggerConfiguration) - { - return new ReloadableLogger(loggerConfiguration.CreateLogger()); - } + return new ReloadableLogger(loggerConfiguration.CreateLogger()); } } diff --git a/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs b/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs index 4e9c62c..46abd8d 100644 --- a/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs +++ b/src/Serilog.Extensions.Hosting/LoggerSettingsConfigurationExtensions.cs @@ -17,27 +17,26 @@ using Serilog.Core; using Serilog.Extensions.Hosting; -namespace Serilog +namespace Serilog; + +/// +/// Extends with methods for consuming host services. +/// +public static class LoggerSettingsConfigurationExtensions { /// - /// Extends with methods for consuming host services. + /// Configure the logger using components from the . If present, the logger will + /// receive implementations/instances of , , + /// , , , and + /// . /// - public static class LoggerSettingsConfigurationExtensions + /// The `ReadFrom` configuration object. + /// A from which services will be requested. + /// A to support method chaining. + public static LoggerConfiguration Services( + this LoggerSettingsConfiguration loggerSettingsConfiguration, + IServiceProvider services) { - /// - /// Configure the logger using components from the . If present, the logger will - /// receive implementations/instances of , , - /// , , , and - /// . - /// - /// The `ReadFrom` configuration object. - /// A from which services will be requested. - /// A to support method chaining. - public static LoggerConfiguration Services( - this LoggerSettingsConfiguration loggerSettingsConfiguration, - IServiceProvider services) - { - return loggerSettingsConfiguration.Settings(new InjectedLoggerSettings(services)); - } + return loggerSettingsConfiguration.Settings(new InjectedLoggerSettings(services)); } } \ No newline at end of file diff --git a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj index edeb7db..bca67be 100644 --- a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj +++ b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj @@ -8,7 +8,7 @@ net462;netstandard2.0;net6.0;net7.0;net8.0 - 8 + latest true true ../../assets/Serilog.snk diff --git a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs index 7f0ab0d..d8b8c4a 100644 --- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs @@ -18,104 +18,103 @@ using Serilog.Extensions.Logging; // ReSharper disable MemberCanBePrivate.Global -namespace Serilog +namespace Serilog; + +/// +/// Extends with Serilog configuration methods. +/// +public static class SerilogHostBuilderExtensions { /// - /// Extends with Serilog configuration methods. + /// Sets Serilog as the logging provider. /// - public static class SerilogHostBuilderExtensions + /// The host builder to configure. + /// The Serilog logger; if not supplied, the static will be used. + /// When true, dispose when the framework disposes the provider. If the + /// logger is not specified but is true, the method will be + /// called on the static class instead. + /// A registered in the Serilog pipeline using the + /// WriteTo.Providers() configuration method, enabling other s to receive events. By + /// default, only Serilog sinks will receive events. + /// The host builder. + public static IHostBuilder UseSerilog( + this IHostBuilder builder, + ILogger logger = null, + bool dispose = false, + LoggerProviderCollection providers = null) { - /// - /// Sets Serilog as the logging provider. - /// - /// The host builder to configure. - /// The Serilog logger; if not supplied, the static will be used. - /// When true, dispose when the framework disposes the provider. If the - /// logger is not specified but is true, the method will be - /// called on the static class instead. - /// A registered in the Serilog pipeline using the - /// WriteTo.Providers() configuration method, enabling other s to receive events. By - /// default, only Serilog sinks will receive events. - /// The host builder. - public static IHostBuilder UseSerilog( - this IHostBuilder builder, - ILogger logger = null, - bool dispose = false, - LoggerProviderCollection providers = null) + if (builder == null) throw new ArgumentNullException(nameof(builder)); + + builder.ConfigureServices((_, collection) => { - if (builder == null) throw new ArgumentNullException(nameof(builder)); + collection.AddSerilog(logger, dispose, providers); + }); - builder.ConfigureServices((_, collection) => - { - collection.AddSerilog(logger, dispose, providers); - }); + return builder; + } - return builder; - } + /// Sets Serilog as the logging provider. + /// + /// A is supplied so that configuration and hosting information can be used. + /// The logger will be shut down when application services are disposed. + /// + /// The host builder to configure. + /// The delegate for configuring the that will be used to construct a . + /// Indicates whether to preserve the value of . + /// By default, Serilog does not write events to s registered through + /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify + /// true to write events to all providers. + /// The host builder. + public static IHostBuilder UseSerilog( + this IHostBuilder builder, + Action configureLogger, + bool preserveStaticLogger = false, + bool writeToProviders = false) + { + if (builder == null) throw new ArgumentNullException(nameof(builder)); + if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); + return UseSerilog( + builder, + (hostBuilderContext, services, loggerConfiguration) => + configureLogger(hostBuilderContext, loggerConfiguration), + preserveStaticLogger: preserveStaticLogger, + writeToProviders: writeToProviders); + } - /// Sets Serilog as the logging provider. - /// - /// A is supplied so that configuration and hosting information can be used. - /// The logger will be shut down when application services are disposed. - /// - /// The host builder to configure. - /// The delegate for configuring the that will be used to construct a . - /// Indicates whether to preserve the value of . - /// By default, Serilog does not write events to s registered through - /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify - /// true to write events to all providers. - /// The host builder. - public static IHostBuilder UseSerilog( - this IHostBuilder builder, - Action configureLogger, - bool preserveStaticLogger = false, - bool writeToProviders = false) + /// Sets Serilog as the logging provider. + /// + /// A is supplied so that configuration and hosting information can be used. + /// The logger will be shut down when application services are disposed. + /// + /// The host builder to configure. + /// The delegate for configuring the that will be used to construct a . + /// Indicates whether to preserve the value of . + /// By default, Serilog does not write events to s registered through + /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify + /// true to write events to all providers. + /// If the static is a bootstrap logger (see + /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is + /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being + /// replaced entirely or ignored. + /// The host builder. + public static IHostBuilder UseSerilog( + this IHostBuilder builder, + Action configureLogger, + bool preserveStaticLogger = false, + bool writeToProviders = false) + { + if (builder == null) throw new ArgumentNullException(nameof(builder)); + if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); + + builder.ConfigureServices((context, collection) => { - if (builder == null) throw new ArgumentNullException(nameof(builder)); - if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); - return UseSerilog( - builder, - (hostBuilderContext, services, loggerConfiguration) => - configureLogger(hostBuilderContext, loggerConfiguration), + collection.AddSerilog( + (services, loggerConfiguration) => + configureLogger(context, services, loggerConfiguration), preserveStaticLogger: preserveStaticLogger, writeToProviders: writeToProviders); - } - - /// Sets Serilog as the logging provider. - /// - /// A is supplied so that configuration and hosting information can be used. - /// The logger will be shut down when application services are disposed. - /// - /// The host builder to configure. - /// The delegate for configuring the that will be used to construct a . - /// Indicates whether to preserve the value of . - /// By default, Serilog does not write events to s registered through - /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify - /// true to write events to all providers. - /// If the static is a bootstrap logger (see - /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is - /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being - /// replaced entirely or ignored. - /// The host builder. - public static IHostBuilder UseSerilog( - this IHostBuilder builder, - Action configureLogger, - bool preserveStaticLogger = false, - bool writeToProviders = false) - { - if (builder == null) throw new ArgumentNullException(nameof(builder)); - if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); - - builder.ConfigureServices((context, collection) => - { - collection.AddSerilog( - (services, loggerConfiguration) => - configureLogger(context, services, loggerConfiguration), - preserveStaticLogger: preserveStaticLogger, - writeToProviders: writeToProviders); - }); - - return builder; - } + }); + + return builder; } } diff --git a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs index e6055c0..d0d21af 100644 --- a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs @@ -20,222 +20,221 @@ using Serilog.Extensions.Logging; // ReSharper disable MemberCanBePrivate.Global -namespace Serilog +namespace Serilog; + +/// +/// Extends with Serilog configuration methods. +/// +public static class SerilogServiceCollectionExtensions { - /// - /// Extends with Serilog configuration methods. - /// - public static class SerilogServiceCollectionExtensions + // Used internally to pass information through the container. We need to do this because if `logger` is the + // root logger, registering it as a singleton may lead to disposal along with the container by MEDI. This isn't + // always desirable, i.e. we may be handed a logger and `dispose: false`, so wrapping it keeps us in control + // of when the logger is disposed. + class RegisteredLogger { - // Used internally to pass information through the container. We need to do this because if `logger` is the - // root logger, registering it as a singleton may lead to disposal along with the container by MEDI. This isn't - // always desirable, i.e. we may be handed a logger and `dispose: false`, so wrapping it keeps us in control - // of when the logger is disposed. - class RegisteredLogger + public RegisteredLogger(ILogger logger) { - public RegisteredLogger(ILogger logger) - { - Logger = logger; - } - - public ILogger Logger { get; } + Logger = logger; } + + public ILogger Logger { get; } + } - /// - /// Sets Serilog as the logging provider. - /// - /// The service collection to use. - /// The Serilog logger; if not supplied, the static will be used. - /// When true, dispose when the framework disposes the provider. If the - /// logger is not specified but is true, the method will be - /// called on the static class instead. - /// A registered in the Serilog pipeline using the - /// WriteTo.Providers() configuration method, enabling other s to receive events. By - /// default, only Serilog sinks will receive events. - /// The service collection. - public static IServiceCollection AddSerilog( - this IServiceCollection collection, - ILogger logger = null, - bool dispose = false, - LoggerProviderCollection providers = null) - { - if (collection == null) throw new ArgumentNullException(nameof(collection)); - - if (providers != null) - { - collection.AddSingleton(services => - { - var factory = new SerilogLoggerFactory(logger, dispose, providers); - - foreach (var provider in services.GetServices()) - factory.AddProvider(provider); - - return factory; - }); - } - else - { - collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)); - } + /// + /// Sets Serilog as the logging provider. + /// + /// The service collection to use. + /// The Serilog logger; if not supplied, the static will be used. + /// When true, dispose when the framework disposes the provider. If the + /// logger is not specified but is true, the method will be + /// called on the static class instead. + /// A registered in the Serilog pipeline using the + /// WriteTo.Providers() configuration method, enabling other s to receive events. By + /// default, only Serilog sinks will receive events. + /// The service collection. + public static IServiceCollection AddSerilog( + this IServiceCollection collection, + ILogger logger = null, + bool dispose = false, + LoggerProviderCollection providers = null) + { + if (collection == null) throw new ArgumentNullException(nameof(collection)); - if (logger != null) + if (providers != null) + { + collection.AddSingleton(services => { - // This won't (and shouldn't) take ownership of the logger. - collection.AddSingleton(logger); + var factory = new SerilogLoggerFactory(logger, dispose, providers); - // Still need to use RegisteredLogger as it is used by ConfigureDiagnosticContext. - collection.AddSingleton(new RegisteredLogger(logger)); - } - bool useRegisteredLogger = logger != null; - ConfigureDiagnosticContext(collection, useRegisteredLogger); + foreach (var provider in services.GetServices()) + factory.AddProvider(provider); - return collection; + return factory; + }); } - - /// Sets Serilog as the logging provider. - /// The service collection to use. - /// The delegate for configuring the that will be used to construct a . - /// Indicates whether to preserve the value of . - /// By default, Serilog does not write events to s registered through - /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify - /// true to write events to all providers. - /// The service collection. - public static IServiceCollection AddSerilog( - this IServiceCollection collection, - Action configureLogger, - bool preserveStaticLogger = false, - bool writeToProviders = false) + else { - if (collection == null) throw new ArgumentNullException(nameof(collection)); - if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); - return AddSerilog( - collection, - (services, loggerConfiguration) => - configureLogger(loggerConfiguration), - preserveStaticLogger: preserveStaticLogger, - writeToProviders: writeToProviders); + collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)); } - /// Sets Serilog as the logging provider. - /// The service collection to use. - /// The delegate for configuring the that will be used to construct a . - /// Indicates whether to preserve the value of . - /// By default, Serilog does not write events to s registered through - /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify - /// true to write events to all providers. - /// If the static is a bootstrap logger (see - /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is - /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being - /// replaced entirely or ignored. - /// The service collection. - public static IServiceCollection AddSerilog( - this IServiceCollection collection, - Action configureLogger, - bool preserveStaticLogger = false, - bool writeToProviders = false) + if (logger != null) { - if (collection == null) throw new ArgumentNullException(nameof(collection)); - if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); - - // This check is eager; replacing the bootstrap logger after calling this method is not supported. + // This won't (and shouldn't) take ownership of the logger. + collection.AddSingleton(logger); + + // Still need to use RegisteredLogger as it is used by ConfigureDiagnosticContext. + collection.AddSingleton(new RegisteredLogger(logger)); + } + bool useRegisteredLogger = logger != null; + ConfigureDiagnosticContext(collection, useRegisteredLogger); + + return collection; + } + + /// Sets Serilog as the logging provider. + /// The service collection to use. + /// The delegate for configuring the that will be used to construct a . + /// Indicates whether to preserve the value of . + /// By default, Serilog does not write events to s registered through + /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify + /// true to write events to all providers. + /// The service collection. + public static IServiceCollection AddSerilog( + this IServiceCollection collection, + Action configureLogger, + bool preserveStaticLogger = false, + bool writeToProviders = false) + { + if (collection == null) throw new ArgumentNullException(nameof(collection)); + if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); + return AddSerilog( + collection, + (services, loggerConfiguration) => + configureLogger(loggerConfiguration), + preserveStaticLogger: preserveStaticLogger, + writeToProviders: writeToProviders); + } + + /// Sets Serilog as the logging provider. + /// The service collection to use. + /// The delegate for configuring the that will be used to construct a . + /// Indicates whether to preserve the value of . + /// By default, Serilog does not write events to s registered through + /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify + /// true to write events to all providers. + /// If the static is a bootstrap logger (see + /// LoggerConfigurationExtensions.CreateBootstrapLogger()), and is + /// not specified, the the bootstrap logger will be reconfigured through the supplied delegate, rather than being + /// replaced entirely or ignored. + /// The service collection. + public static IServiceCollection AddSerilog( + this IServiceCollection collection, + Action configureLogger, + bool preserveStaticLogger = false, + bool writeToProviders = false) + { + if (collection == null) throw new ArgumentNullException(nameof(collection)); + if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); + + // This check is eager; replacing the bootstrap logger after calling this method is not supported. #if !NO_RELOADABLE_LOGGER - var reloadable = Log.Logger as ReloadableLogger; - var useReload = reloadable != null && !preserveStaticLogger; + var reloadable = Log.Logger as ReloadableLogger; + var useReload = reloadable != null && !preserveStaticLogger; #else - const bool useReload = false; + const bool useReload = false; #endif + + LoggerProviderCollection loggerProviders = null; + if (writeToProviders) + { + loggerProviders = new LoggerProviderCollection(); + } - LoggerProviderCollection loggerProviders = null; - if (writeToProviders) - { - loggerProviders = new LoggerProviderCollection(); - } - - collection.AddSingleton(services => - { - ILogger logger; + collection.AddSingleton(services => + { + ILogger logger; #if !NO_RELOADABLE_LOGGER - if (useReload) + if (useReload) + { + reloadable!.Reload(cfg => { - reloadable!.Reload(cfg => - { - if (loggerProviders != null) - cfg.WriteTo.Providers(loggerProviders); - - configureLogger(services, cfg); - return cfg; - }); + if (loggerProviders != null) + cfg.WriteTo.Providers(loggerProviders); - logger = reloadable.Freeze(); - } - else + configureLogger(services, cfg); + return cfg; + }); + + logger = reloadable.Freeze(); + } + else #endif - { - var loggerConfiguration = new LoggerConfiguration(); + { + var loggerConfiguration = new LoggerConfiguration(); - if (loggerProviders != null) - loggerConfiguration.WriteTo.Providers(loggerProviders); + if (loggerProviders != null) + loggerConfiguration.WriteTo.Providers(loggerProviders); - configureLogger(services, loggerConfiguration); - logger = loggerConfiguration.CreateLogger(); - } + configureLogger(services, loggerConfiguration); + logger = loggerConfiguration.CreateLogger(); + } - return new RegisteredLogger(logger); - }); + return new RegisteredLogger(logger); + }); - collection.AddSingleton(services => - { - // How can we register the logger, here, but not have MEDI dispose it? - // Using the `NullEnricher` hack to prevent disposal. - var logger = services.GetRequiredService().Logger; - return logger.ForContext(new NullEnricher()); - }); + collection.AddSingleton(services => + { + // How can we register the logger, here, but not have MEDI dispose it? + // Using the `NullEnricher` hack to prevent disposal. + var logger = services.GetRequiredService().Logger; + return logger.ForContext(new NullEnricher()); + }); + + collection.AddSingleton(services => + { + var logger = services.GetRequiredService().Logger; - collection.AddSingleton(services => + ILogger registeredLogger = null; + if (preserveStaticLogger) { - var logger = services.GetRequiredService().Logger; - - ILogger registeredLogger = null; - if (preserveStaticLogger) - { - registeredLogger = logger; - } - else - { - // Passing a `null` logger to `SerilogLoggerFactory` results in disposal via - // `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op. - Log.Logger = logger; - } + registeredLogger = logger; + } + else + { + // Passing a `null` logger to `SerilogLoggerFactory` results in disposal via + // `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op. + Log.Logger = logger; + } - var factory = new SerilogLoggerFactory(registeredLogger, !useReload, loggerProviders); + var factory = new SerilogLoggerFactory(registeredLogger, !useReload, loggerProviders); - if (writeToProviders) - { - foreach (var provider in services.GetServices()) - factory.AddProvider(provider); - } + if (writeToProviders) + { + foreach (var provider in services.GetServices()) + factory.AddProvider(provider); + } - return factory; - }); + return factory; + }); - ConfigureDiagnosticContext(collection, preserveStaticLogger); - - return collection; - } + ConfigureDiagnosticContext(collection, preserveStaticLogger); + + return collection; + } - static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger) - { - if (collection == null) throw new ArgumentNullException(nameof(collection)); + static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger) + { + if (collection == null) throw new ArgumentNullException(nameof(collection)); - // Registered to provide two services... - // Consumed by e.g. middleware - collection.AddSingleton(services => - { - ILogger logger = useRegisteredLogger ? services.GetRequiredService().Logger : null; - return new DiagnosticContext(logger); - }); - // Consumed by user code - collection.AddSingleton(services => services.GetRequiredService()); - } + // Registered to provide two services... + // Consumed by e.g. middleware + collection.AddSingleton(services => + { + ILogger logger = useRegisteredLogger ? services.GetRequiredService().Logger : null; + return new DiagnosticContext(logger); + }); + // Consumed by user code + collection.AddSingleton(services => services.GetRequiredService()); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs index 3281065..d66114b 100644 --- a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs @@ -7,115 +7,114 @@ // ReSharper disable PossibleNullReferenceException -namespace Serilog.Extensions.Hosting.Tests +namespace Serilog.Extensions.Hosting.Tests; + +public class DiagnosticContextTests { - public class DiagnosticContextTests + [Fact] + public void SetIsSafeWhenNoContextIsActive() + { + var dc = new DiagnosticContext(Some.Logger()); + dc.Set(Some.String("name"), Some.Int32()); + } + + [Fact] + public void SetExceptionIsSafeWhenNoContextIsActive() + { + var dc = new DiagnosticContext(Some.Logger()); + dc.SetException(new Exception("test")); + } + + [Fact] + public async Task PropertiesAreCollectedInAnActiveContext() + { + var dc = new DiagnosticContext(Some.Logger()); + + var collector = dc.BeginCollection(); + dc.Set(Some.String("first"), Some.Int32()); + await Task.Delay(TimeSpan.FromMilliseconds(10)); + dc.Set(Some.String("second"), Some.Int32()); + + Assert.True(collector.TryComplete(out var properties, out var exception)); + Assert.Equal(2, properties.Count()); + Assert.Null(exception); + + Assert.False(collector.TryComplete(out _, out _)); + + collector.Dispose(); + + dc.Set(Some.String("third"), Some.Int32()); + Assert.False(collector.TryComplete(out _, out _)); + } + + [Fact] + public void ExceptionIsCollectedInAnActiveContext() + { + var dc = new DiagnosticContext(Some.Logger()); + var collector = dc.BeginCollection(); + + var setException = new Exception("before collect"); + dc.SetException(setException); + + Assert.True(collector.TryComplete(out _, out var collectedException)); + Assert.Same(setException, collectedException); + } + + [Fact] + public void ExceptionIsNotCollectedAfterTryComplete() + { + var dc = new DiagnosticContext(Some.Logger()); + var collector = dc.BeginCollection(); + collector.TryComplete(out _, out _); + dc.SetException(new Exception(Some.String("after collect"))); + + var tryComplete2 = collector.TryComplete(out _, out var collectedException2); + + Assert.False(tryComplete2); + Assert.Null(collectedException2); + } + + [Fact] + public void ExceptionIsNotCollectedAfterDispose() { - [Fact] - public void SetIsSafeWhenNoContextIsActive() - { - var dc = new DiagnosticContext(Some.Logger()); - dc.Set(Some.String("name"), Some.Int32()); - } - - [Fact] - public void SetExceptionIsSafeWhenNoContextIsActive() - { - var dc = new DiagnosticContext(Some.Logger()); - dc.SetException(new Exception("test")); - } - - [Fact] - public async Task PropertiesAreCollectedInAnActiveContext() - { - var dc = new DiagnosticContext(Some.Logger()); - - var collector = dc.BeginCollection(); - dc.Set(Some.String("first"), Some.Int32()); - await Task.Delay(TimeSpan.FromMilliseconds(10)); - dc.Set(Some.String("second"), Some.Int32()); - - Assert.True(collector.TryComplete(out var properties, out var exception)); - Assert.Equal(2, properties.Count()); - Assert.Null(exception); - - Assert.False(collector.TryComplete(out _, out _)); - - collector.Dispose(); - - dc.Set(Some.String("third"), Some.Int32()); - Assert.False(collector.TryComplete(out _, out _)); - } - - [Fact] - public void ExceptionIsCollectedInAnActiveContext() - { - var dc = new DiagnosticContext(Some.Logger()); - var collector = dc.BeginCollection(); - - var setException = new Exception("before collect"); - dc.SetException(setException); - - Assert.True(collector.TryComplete(out _, out var collectedException)); - Assert.Same(setException, collectedException); - } - - [Fact] - public void ExceptionIsNotCollectedAfterTryComplete() - { - var dc = new DiagnosticContext(Some.Logger()); - var collector = dc.BeginCollection(); - collector.TryComplete(out _, out _); - dc.SetException(new Exception(Some.String("after collect"))); - - var tryComplete2 = collector.TryComplete(out _, out var collectedException2); - - Assert.False(tryComplete2); - Assert.Null(collectedException2); - } - - [Fact] - public void ExceptionIsNotCollectedAfterDispose() - { - var dc = new DiagnosticContext(Some.Logger()); - var collector = dc.BeginCollection(); - collector.Dispose(); - - dc.SetException(new Exception("after dispose")); - - var tryComplete = collector.TryComplete(out _, out var collectedException); - - Assert.True(tryComplete); - Assert.Null(collectedException); - } - - [Fact] - public void ExistingPropertiesCanBeUpdated() - { - var dc = new DiagnosticContext(Some.Logger()); - - var collector = dc.BeginCollection(); - dc.Set("name", 10); - dc.Set("name", 20); - - Assert.True(collector.TryComplete(out var properties, out var exception)); - var prop = Assert.Single(properties); - var scalar = Assert.IsType(prop.Value); - Assert.Equal(20, scalar.Value); - Assert.Null(exception); - } - - [Fact] - public void ExistingExceptionCanBeUpdated() - { - var dc = new DiagnosticContext(Some.Logger()); - var collector = dc.BeginCollection(); - - dc.SetException(new Exception("ex1")); - dc.SetException(new Exception("ex2")); - - Assert.True(collector.TryComplete(out _, out var collectedException)); - Assert.Equal("ex2", collectedException.Message); - } + var dc = new DiagnosticContext(Some.Logger()); + var collector = dc.BeginCollection(); + collector.Dispose(); + + dc.SetException(new Exception("after dispose")); + + var tryComplete = collector.TryComplete(out _, out var collectedException); + + Assert.True(tryComplete); + Assert.Null(collectedException); + } + + [Fact] + public void ExistingPropertiesCanBeUpdated() + { + var dc = new DiagnosticContext(Some.Logger()); + + var collector = dc.BeginCollection(); + dc.Set("name", 10); + dc.Set("name", 20); + + Assert.True(collector.TryComplete(out var properties, out var exception)); + var prop = Assert.Single(properties); + var scalar = Assert.IsType(prop.Value); + Assert.Equal(20, scalar.Value); + Assert.Null(exception); + } + + [Fact] + public void ExistingExceptionCanBeUpdated() + { + var dc = new DiagnosticContext(Some.Logger()); + var collector = dc.BeginCollection(); + + dc.SetException(new Exception("ex1")); + dc.SetException(new Exception("ex2")); + + Assert.True(collector.TryComplete(out _, out var collectedException)); + Assert.Equal("ex2", collectedException.Message); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs index 54a8154..87f5bea 100644 --- a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs @@ -5,27 +5,26 @@ using Serilog.Extensions.Hosting.Tests.Support; using Xunit; -namespace Serilog.Extensions.Hosting.Tests +namespace Serilog.Extensions.Hosting.Tests; + +public class LoggerSettingsConfigurationExtensionsTests { - public class LoggerSettingsConfigurationExtensionsTests + [Fact] + public void SinksAreInjectedFromTheServiceProvider() { - [Fact] - public void SinksAreInjectedFromTheServiceProvider() - { - var emittedEvents = new List(); - - var serviceCollection = new ServiceCollection(); - serviceCollection.AddSingleton(new ListSink(emittedEvents)); - using var services = serviceCollection.BuildServiceProvider(); + var emittedEvents = new List(); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(new ListSink(emittedEvents)); + using var services = serviceCollection.BuildServiceProvider(); - using var logger = new LoggerConfiguration() - .ReadFrom.Services(services) - .CreateLogger(); - - logger.Information("Hello, world!"); - - var evt = Assert.Single(emittedEvents); - Assert.Equal("Hello, world!", evt!.MessageTemplate.Text); - } + using var logger = new LoggerConfiguration() + .ReadFrom.Services(services) + .CreateLogger(); + + logger.Information("Hello, world!"); + + var evt = Assert.Single(emittedEvents); + Assert.Equal("Hello, world!", evt!.MessageTemplate.Text); } } \ No newline at end of file diff --git a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs index 10b807a..80a0239 100644 --- a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs @@ -7,101 +7,100 @@ using Serilog.Extensions.Hosting.Tests.Support; using Xunit; -namespace Serilog.Extensions.Hosting.Tests +namespace Serilog.Extensions.Hosting.Tests; + +public class ReloadableLoggerTests { - public class ReloadableLoggerTests + [Fact] + public void AFrozenLoggerYieldsSerilogLoggers() { - [Fact] - public void AFrozenLoggerYieldsSerilogLoggers() - { - var logger = new ReloadableLogger(new LoggerConfiguration().CreateLogger()); - var contextual = logger.ForContext(); + var logger = new ReloadableLogger(new LoggerConfiguration().CreateLogger()); + var contextual = logger.ForContext(); - var nested = contextual.ForContext("test", "test"); - Assert.IsNotType(nested); + var nested = contextual.ForContext("test", "test"); + Assert.IsNotType(nested); - logger.Freeze(); + logger.Freeze(); - nested = contextual.ForContext("test", "test"); - Assert.IsType(nested); - } - - [Fact] - public void CachingReloadableLoggerRemainsUsableAfterFreezing() - { - var logger = new LoggerConfiguration().CreateBootstrapLogger(); - var contextual = logger.ForContext(); - contextual.Information("First"); - logger.Reload(c => c); - logger.Freeze(); - contextual.Information("Second"); - contextual.Information("Third"); - contextual.Information("Fourth"); // No crash :-) - } + nested = contextual.ForContext("test", "test"); + Assert.IsType(nested); + } + + [Fact] + public void CachingReloadableLoggerRemainsUsableAfterFreezing() + { + var logger = new LoggerConfiguration().CreateBootstrapLogger(); + var contextual = logger.ForContext(); + contextual.Information("First"); + logger.Reload(c => c); + logger.Freeze(); + contextual.Information("Second"); + contextual.Information("Third"); + contextual.Information("Fourth"); // No crash :-) + } - [Fact] - public void ReloadableLoggerRespectsMinimumLevelOverrides() - { - var emittedEvents = new List(); - var logger = new LoggerConfiguration() - .MinimumLevel.Override("Test", LogEventLevel.Warning) - .WriteTo.Sink(new ListSink(emittedEvents)) - .CreateBootstrapLogger(); + [Fact] + public void ReloadableLoggerRespectsMinimumLevelOverrides() + { + var emittedEvents = new List(); + var logger = new LoggerConfiguration() + .MinimumLevel.Override("Test", LogEventLevel.Warning) + .WriteTo.Sink(new ListSink(emittedEvents)) + .CreateBootstrapLogger(); - var limited = logger - .ForContext("X", 1) - .ForContext(Constants.SourceContextPropertyName, "Test.Stuff"); - - var notLimited = logger.ForContext(); - - foreach (var context in new[] { limited, notLimited }) - { - // Suppressed by both sinks - context.Debug("First"); + var limited = logger + .ForContext("X", 1) + .ForContext(Constants.SourceContextPropertyName, "Test.Stuff"); + + var notLimited = logger.ForContext(); + + foreach (var context in new[] { limited, notLimited }) + { + // Suppressed by both sinks + context.Debug("First"); - // Suppressed by the limited logger - context.Information("Second"); - - // Emitted by both loggers - context.Warning("Third"); - } + // Suppressed by the limited logger + context.Information("Second"); - Assert.Equal(3, emittedEvents.Count); - Assert.Equal(2, emittedEvents.Count(le => le.Level == LogEventLevel.Warning)); + // Emitted by both loggers + context.Warning("Third"); } + + Assert.Equal(3, emittedEvents.Count); + Assert.Equal(2, emittedEvents.Count(le => le.Level == LogEventLevel.Warning)); + } - [Fact] - public void ReloadableLoggersRecordEnrichment() - { - var emittedEvents = new List(); - - var logger = new LoggerConfiguration() - .WriteTo.Sink(new ListSink(emittedEvents)) - .CreateBootstrapLogger(); + [Fact] + public void ReloadableLoggersRecordEnrichment() + { + var emittedEvents = new List(); + + var logger = new LoggerConfiguration() + .WriteTo.Sink(new ListSink(emittedEvents)) + .CreateBootstrapLogger(); - var outer = logger - .ForContext("A", new object()); - var inner = outer.ForContext("B", "test"); - - inner.Information("First"); - - logger.Reload(lc => lc.WriteTo.Sink(new ListSink(emittedEvents))); - - inner.Information("Second"); + var outer = logger + .ForContext("A", new object()); + var inner = outer.ForContext("B", "test"); + + inner.Information("First"); + + logger.Reload(lc => lc.WriteTo.Sink(new ListSink(emittedEvents))); + + inner.Information("Second"); - logger.Freeze(); - - inner.Information("Third"); - - outer.ForContext("B", "test").Information("Fourth"); - - logger.ForContext("A", new object()) - .ForContext("B", "test") - .Information("Fifth"); - - Assert.Equal(5, emittedEvents.Count); - Assert.All(emittedEvents, e => Assert.Equal(2, e.Properties.Count)); - } + logger.Freeze(); + + inner.Information("Third"); + + outer.ForContext("B", "test").Information("Fourth"); + + logger.ForContext("A", new object()) + .ForContext("B", "test") + .Information("Fifth"); + + Assert.Equal(5, emittedEvents.Count); + Assert.All(emittedEvents, e => Assert.Equal(2, e.Properties.Count)); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj index 39904a4..1f5c9d6 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj +++ b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj @@ -11,7 +11,7 @@ $(DefineConstants);NO_RELOADABLE_LOGGER - + @@ -22,5 +22,5 @@ - + diff --git a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs index c9ba14b..53dce78 100644 --- a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs @@ -6,104 +6,103 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Serilog.Extensions.Hosting.Tests +namespace Serilog.Extensions.Hosting.Tests; + +public class SerilogHostBuilderExtensionsTests { - public class SerilogHostBuilderExtensionsTests + [Fact] + public void ServicesAreRegisteredWhenCallingUseSerilog() + { + // Arrange + var collection = new ServiceCollection(); + IHostBuilder builder = new FakeHostBuilder(collection); + + // Act + builder.UseSerilog(); + + // Assert + IServiceProvider provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + } + + [Fact] + public void ServicesAreRegisteredWhenCallingUseSerilogWithLogger() + { + // Arrange + var collection = new ServiceCollection(); + IHostBuilder builder = new FakeHostBuilder(collection); + ILogger logger = new LoggerConfiguration().CreateLogger(); + + // Act + builder.UseSerilog(logger); + + // Assert + IServiceProvider provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + provider.GetRequiredService(); + } + + [Fact] + public void ServicesAreRegisteredWhenCallingUseSerilogWithConfigureDelegate() + { + // Arrange + var collection = new ServiceCollection(); + IHostBuilder builder = new FakeHostBuilder(collection); + + // Act + builder.UseSerilog((_, _) => { }); + + // Assert + IServiceProvider provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + provider.GetRequiredService(); + } + + private class FakeHostBuilder : IHostBuilder { - [Fact] - public void ServicesAreRegisteredWhenCallingUseSerilog() + private readonly IServiceCollection _collection; + + public FakeHostBuilder(IServiceCollection collection) => _collection = collection; + + public IHostBuilder ConfigureHostConfiguration(Action configureDelegate) { - // Arrange - var collection = new ServiceCollection(); - IHostBuilder builder = new FakeHostBuilder(collection); + throw new NotImplementedException(); + } - // Act - builder.UseSerilog(); + public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) + { + throw new NotImplementedException(); + } - // Assert - IServiceProvider provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); + public IHostBuilder ConfigureServices(Action configureDelegate) + { + configureDelegate(null, _collection); + return this; } - [Fact] - public void ServicesAreRegisteredWhenCallingUseSerilogWithLogger() + public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) { - // Arrange - var collection = new ServiceCollection(); - IHostBuilder builder = new FakeHostBuilder(collection); - ILogger logger = new LoggerConfiguration().CreateLogger(); - - // Act - builder.UseSerilog(logger); - - // Assert - IServiceProvider provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); - provider.GetRequiredService(); + throw new NotImplementedException(); } - [Fact] - public void ServicesAreRegisteredWhenCallingUseSerilogWithConfigureDelegate() + public IHostBuilder UseServiceProviderFactory(Func> factory) { - // Arrange - var collection = new ServiceCollection(); - IHostBuilder builder = new FakeHostBuilder(collection); - - // Act - builder.UseSerilog((_, _) => { }); - - // Assert - IServiceProvider provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); - provider.GetRequiredService(); + throw new NotImplementedException(); } - private class FakeHostBuilder : IHostBuilder + public IHostBuilder ConfigureContainer(Action configureDelegate) { - private readonly IServiceCollection _collection; - - public FakeHostBuilder(IServiceCollection collection) => _collection = collection; - - public IHostBuilder ConfigureHostConfiguration(Action configureDelegate) - { - throw new NotImplementedException(); - } - - public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) - { - throw new NotImplementedException(); - } - - public IHostBuilder ConfigureServices(Action configureDelegate) - { - configureDelegate(null, _collection); - return this; - } - - public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) - { - throw new NotImplementedException(); - } - - public IHostBuilder UseServiceProviderFactory(Func> factory) - { - throw new NotImplementedException(); - } - - public IHostBuilder ConfigureContainer(Action configureDelegate) - { - throw new NotImplementedException(); - } - - public IHost Build() - { - throw new NotImplementedException(); - } - - public IDictionary Properties { get; } + throw new NotImplementedException(); } + + public IHost Build() + { + throw new NotImplementedException(); + } + + public IDictionary Properties { get; } } } diff --git a/test/Serilog.Extensions.Hosting.Tests/SerilogServiceCollectionExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/SerilogServiceCollectionExtensionsTests.cs index 7fd9752..51913ad 100644 --- a/test/Serilog.Extensions.Hosting.Tests/SerilogServiceCollectionExtensionsTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/SerilogServiceCollectionExtensionsTests.cs @@ -3,56 +3,55 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Serilog.Extensions.Hosting.Tests +namespace Serilog.Extensions.Hosting.Tests; + +public class SerilogServiceCollectionExtensionsTests { - public class SerilogServiceCollectionExtensionsTests + [Fact] + public void ServicesAreRegisteredWhenCallingAddSerilog() + { + // Arrange + var collection = new ServiceCollection(); + + // Act + collection.AddSerilog(); + + // Assert + using var provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + } + + [Fact] + public void ServicesAreRegisteredWhenCallingAddSerilogWithLogger() { - [Fact] - public void ServicesAreRegisteredWhenCallingAddSerilog() - { - // Arrange - var collection = new ServiceCollection(); - - // Act - collection.AddSerilog(); - - // Assert - using var provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); - } - - [Fact] - public void ServicesAreRegisteredWhenCallingAddSerilogWithLogger() - { - // Arrange - var collection = new ServiceCollection(); - ILogger logger = new LoggerConfiguration().CreateLogger(); - - // Act - collection.AddSerilog(logger); - - // Assert - using var provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); - provider.GetRequiredService(); - } - - [Fact] - public void ServicesAreRegisteredWhenCallingAddSerilogWithConfigureDelegate() - { - // Arrange - var collection = new ServiceCollection(); - - // Act - collection.AddSerilog(_ => { }); - - // Assert - using var provider = collection.BuildServiceProvider(); - provider.GetRequiredService(); - provider.GetRequiredService(); - provider.GetRequiredService(); - } + // Arrange + var collection = new ServiceCollection(); + ILogger logger = new LoggerConfiguration().CreateLogger(); + + // Act + collection.AddSerilog(logger); + + // Assert + using var provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + provider.GetRequiredService(); + } + + [Fact] + public void ServicesAreRegisteredWhenCallingAddSerilogWithConfigureDelegate() + { + // Arrange + var collection = new ServiceCollection(); + + // Act + collection.AddSerilog(_ => { }); + + // Assert + using var provider = collection.BuildServiceProvider(); + provider.GetRequiredService(); + provider.GetRequiredService(); + provider.GetRequiredService(); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs b/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs index 6a090d1..ff1632d 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs +++ b/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs @@ -3,352 +3,351 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Extensions.Hosting.Tests.Support +namespace Serilog.Extensions.Hosting.Tests.Support; + +public class DisposeTrackingLogger : ILogger, IDisposable { - public class DisposeTrackingLogger : ILogger, IDisposable - { - public bool IsDisposed { get; set; } - - public ILogger ForContext(ILogEventEnricher enricher) - { - return new LoggerConfiguration().CreateLogger(); - } - - public ILogger ForContext(IEnumerable enrichers) - { - return new LoggerConfiguration().CreateLogger(); - } - - public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) - { - return new LoggerConfiguration().CreateLogger(); - } - - public ILogger ForContext() - { - return new LoggerConfiguration().CreateLogger(); - } - - public ILogger ForContext(Type source) - { - return new LoggerConfiguration().CreateLogger(); - } - - public void Write(LogEvent logEvent) - { - } - - public void Write(LogEventLevel level, string messageTemplate) - { - } - - public void Write(LogEventLevel level, string messageTemplate, T propertyValue) - { - } - - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) - { - } - - public void Write(LogEventLevel level, Exception exception, string messageTemplate) - { - } - - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, - T1 propertyValue1) - { - } - - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, - T1 propertyValue1, T2 propertyValue2) - { - } - - public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public bool IsEnabled(LogEventLevel level) - { - return false; - } - - public void Verbose(string messageTemplate) - { - } - - public void Verbose(string messageTemplate, T propertyValue) - { - } - - public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Verbose(string messageTemplate, params object[] propertyValues) - { - } - - public void Verbose(Exception exception, string messageTemplate) - { - } - - public void Verbose(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public void Debug(string messageTemplate) - { - } - - public void Debug(string messageTemplate, T propertyValue) - { - } - - public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Debug(string messageTemplate, params object[] propertyValues) - { - } - - public void Debug(Exception exception, string messageTemplate) - { - } - - public void Debug(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Debug(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public void Information(string messageTemplate) - { - } - - public void Information(string messageTemplate, T propertyValue) - { - } - - public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Information(string messageTemplate, params object[] propertyValues) - { - } - - public void Information(Exception exception, string messageTemplate) - { - } - - public void Information(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Information(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public void Warning(string messageTemplate) - { - } - - public void Warning(string messageTemplate, T propertyValue) - { - } - - public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Warning(string messageTemplate, params object[] propertyValues) - { - } - - public void Warning(Exception exception, string messageTemplate) - { - } - - public void Warning(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Warning(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public void Error(string messageTemplate) - { - } - - public void Error(string messageTemplate, T propertyValue) - { - } - - public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Error(string messageTemplate, params object[] propertyValues) - { - } - - public void Error(Exception exception, string messageTemplate) - { - } - - public void Error(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Error(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public void Fatal(string messageTemplate) - { - } - - public void Fatal(string messageTemplate, T propertyValue) - { - } - - public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - } - - public void Fatal(string messageTemplate, params object[] propertyValues) - { - } - - public void Fatal(Exception exception, string messageTemplate) - { - } - - public void Fatal(Exception exception, string messageTemplate, T propertyValue) - { - } - - public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - } - - public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, - T2 propertyValue2) - { - } - - public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) - { - } - - public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, - out IEnumerable boundProperties) - { - parsedTemplate = null; - boundProperties = null; - return false; - } - - public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) - { - property = null; - return false; - } - - public void Dispose() - { - IsDisposed = true; - } + public bool IsDisposed { get; set; } + + public ILogger ForContext(ILogEventEnricher enricher) + { + return new LoggerConfiguration().CreateLogger(); + } + + public ILogger ForContext(IEnumerable enrichers) + { + return new LoggerConfiguration().CreateLogger(); + } + + public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + return new LoggerConfiguration().CreateLogger(); + } + + public ILogger ForContext() + { + return new LoggerConfiguration().CreateLogger(); + } + + public ILogger ForContext(Type source) + { + return new LoggerConfiguration().CreateLogger(); + } + + public void Write(LogEvent logEvent) + { + } + + public void Write(LogEventLevel level, string messageTemplate) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1, T2 propertyValue2) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public bool IsEnabled(LogEventLevel level) + { + return false; + } + + public void Verbose(string messageTemplate) + { + } + + public void Verbose(string messageTemplate, T propertyValue) + { + } + + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Verbose(string messageTemplate, params object[] propertyValues) + { + } + + public void Verbose(Exception exception, string messageTemplate) + { + } + + public void Verbose(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Debug(string messageTemplate) + { + } + + public void Debug(string messageTemplate, T propertyValue) + { + } + + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Debug(string messageTemplate, params object[] propertyValues) + { + } + + public void Debug(Exception exception, string messageTemplate) + { + } + + public void Debug(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Debug(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Information(string messageTemplate) + { + } + + public void Information(string messageTemplate, T propertyValue) + { + } + + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Information(string messageTemplate, params object[] propertyValues) + { + } + + public void Information(Exception exception, string messageTemplate) + { + } + + public void Information(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Information(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Warning(string messageTemplate) + { + } + + public void Warning(string messageTemplate, T propertyValue) + { + } + + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Warning(string messageTemplate, params object[] propertyValues) + { + } + + public void Warning(Exception exception, string messageTemplate) + { + } + + public void Warning(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Warning(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Error(string messageTemplate) + { + } + + public void Error(string messageTemplate, T propertyValue) + { + } + + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Error(string messageTemplate, params object[] propertyValues) + { + } + + public void Error(Exception exception, string messageTemplate) + { + } + + public void Error(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Error(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Fatal(string messageTemplate) + { + } + + public void Fatal(string messageTemplate, T propertyValue) + { + } + + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Fatal(string messageTemplate, params object[] propertyValues) + { + } + + public void Fatal(Exception exception, string messageTemplate) + { + } + + public void Fatal(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + { + } + + public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, + out IEnumerable boundProperties) + { + parsedTemplate = null; + boundProperties = null; + return false; + } + + public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + property = null; + return false; + } + + public void Dispose() + { + IsDisposed = true; } } diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/ListSink.cs b/test/Serilog.Extensions.Hosting.Tests/Support/ListSink.cs index e94caaf..b8777c9 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Support/ListSink.cs +++ b/test/Serilog.Extensions.Hosting.Tests/Support/ListSink.cs @@ -5,20 +5,19 @@ using Serilog.Core; using Serilog.Events; -namespace Serilog.Extensions.Hosting.Tests.Support +namespace Serilog.Extensions.Hosting.Tests.Support; + +public class ListSink : ILogEventSink { - public class ListSink : ILogEventSink - { - readonly List _list; + readonly List _list; - public ListSink(List list) - { - _list = list; - } + public ListSink(List list) + { + _list = list; + } - public void Emit(LogEvent logEvent) - { - _list.Add(logEvent); - } + public void Emit(LogEvent logEvent) + { + _list.Add(logEvent); } } \ No newline at end of file diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs index 5137cef..df7a1ac 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs +++ b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs @@ -4,18 +4,17 @@ using System.Threading; using Serilog.Events; -namespace Serilog.Extensions.Hosting.Tests.Support +namespace Serilog.Extensions.Hosting.Tests.Support; + +static class Some { - static class Some - { - static int _next; + static int _next; - public static int Int32() => Interlocked.Increment(ref _next); + public static int Int32() => Interlocked.Increment(ref _next); - public static string String(string tag = null) => $"s_{tag}{Int32()}"; + public static string String(string tag = null) => $"s_{tag}{Int32()}"; - public static LogEventProperty LogEventProperty() => new LogEventProperty(String("name"), new ScalarValue(Int32())); + public static LogEventProperty LogEventProperty() => new LogEventProperty(String("name"), new ScalarValue(Int32())); - public static ILogger Logger() => new LoggerConfiguration().CreateLogger(); - } + public static ILogger Logger() => new LoggerConfiguration().CreateLogger(); }