From 9aa37c9c8961cc34751952842825377cc49d846c Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 15 Mar 2024 09:18:17 +1000 Subject: [PATCH 01/11] Publishing key update --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index aa80e5e..f52401f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ deploy: - provider: NuGet skip_symbols: true api_key: - secure: EN9f+XXE3fW+ebL4wxrIbafdtbNvRfddBN8UUixvctYh4qMBHzr1JdnM83QsM1zo + secure: H96ajkMxwIafhF2vrr+UAUS10bFcAL/1wc3iphidRiYi9WoTc2i8shTLtF+75ODb on: branch: /^(main|dev)$/ - provider: GitHub From 5d2461dde4810700fd0c11934584f651b9d056c8 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Fri, 22 Mar 2024 14:51:23 +0300 Subject: [PATCH 02/11] Whitespace formatting --- samples/WebApplicationSample/Program.cs | 2 +- .../Extensions/Hosting/DiagnosticContext.cs | 2 +- .../Hosting/InjectedLoggerSettings.cs | 6 +++--- .../SerilogHostBuilderExtensions.cs | 8 ++++---- .../SerilogServiceCollectionExtensions.cs | 18 +++++++++--------- ...ggerSettingsConfigurationExtensionsTests.cs | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/samples/WebApplicationSample/Program.cs b/samples/WebApplicationSample/Program.cs index 4cf73b8..7144476 100644 --- a/samples/WebApplicationSample/Program.cs +++ b/samples/WebApplicationSample/Program.cs @@ -12,7 +12,7 @@ public static int Main(string[] args) Log.Logger = new LoggerConfiguration() .WriteTo.Console() .CreateBootstrapLogger(); - + Log.Information("Starting up!"); try diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs index 44462ac..fb9ac66 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs @@ -50,7 +50,7 @@ public void Set(string propertyName, object value, bool destructureObjects = fal if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); var collector = AmbientDiagnosticContextCollector.Current; - if (collector != null && + if (collector != null && (_logger ?? Log.Logger).BindProperty(propertyName, value, destructureObjects, out var property)) { collector.AddOrUpdate(property); diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs index 97e37ea..1ab94ef 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/InjectedLoggerSettings.cs @@ -19,7 +19,7 @@ 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); @@ -28,10 +28,10 @@ public void Configure(LoggerConfiguration loggerConfiguration) 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/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs index 7f0ab0d..3146232 100644 --- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs @@ -38,8 +38,8 @@ public static class SerilogHostBuilderExtensions /// default, only Serilog sinks will receive events. /// The host builder. public static IHostBuilder UseSerilog( - this IHostBuilder builder, - ILogger logger = null, + this IHostBuilder builder, + ILogger logger = null, bool dispose = false, LoggerProviderCollection providers = null) { @@ -105,7 +105,7 @@ public static IHostBuilder UseSerilog( { if (builder == null) throw new ArgumentNullException(nameof(builder)); if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); - + builder.ConfigureServices((context, collection) => { collection.AddSerilog( @@ -114,7 +114,7 @@ public static IHostBuilder UseSerilog( preserveStaticLogger: preserveStaticLogger, writeToProviders: writeToProviders); }); - + return builder; } } diff --git a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs index e6055c0..88bbc97 100644 --- a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs @@ -37,7 +37,7 @@ public RegisteredLogger(ILogger logger) { Logger = logger; } - + public ILogger Logger { get; } } @@ -54,8 +54,8 @@ public RegisteredLogger(ILogger logger) /// default, only Serilog sinks will receive events. /// The service collection. public static IServiceCollection AddSerilog( - this IServiceCollection collection, - ILogger logger = null, + this IServiceCollection collection, + ILogger logger = null, bool dispose = false, LoggerProviderCollection providers = null) { @@ -136,7 +136,7 @@ public static IServiceCollection AddSerilog( { 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; @@ -144,13 +144,13 @@ public static IServiceCollection AddSerilog( #else const bool useReload = false; #endif - + LoggerProviderCollection loggerProviders = null; if (writeToProviders) { loggerProviders = new LoggerProviderCollection(); } - + collection.AddSingleton(services => { ILogger logger; @@ -190,11 +190,11 @@ public static IServiceCollection AddSerilog( var logger = services.GetRequiredService().Logger; return logger.ForContext(new NullEnricher()); }); - + collection.AddSingleton(services => { var logger = services.GetRequiredService().Logger; - + ILogger registeredLogger = null; if (preserveStaticLogger) { @@ -219,7 +219,7 @@ public static IServiceCollection AddSerilog( }); ConfigureDiagnosticContext(collection, preserveStaticLogger); - + return collection; } diff --git a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs index 54a8154..ce46fb7 100644 --- a/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/LoggerSettingsConfigurationExtensionsTests.cs @@ -13,7 +13,7 @@ public class LoggerSettingsConfigurationExtensionsTests public void SinksAreInjectedFromTheServiceProvider() { var emittedEvents = new List(); - + var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(new ListSink(emittedEvents)); using var services = serviceCollection.BuildServiceProvider(); @@ -21,9 +21,9 @@ public void SinksAreInjectedFromTheServiceProvider() 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); } From c51b78c628994e358ac2217fc195fefeb36f1675 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Fri, 22 Mar 2024 14:56:54 +0300 Subject: [PATCH 03/11] 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(); } From 74b38849f973947c3a1d564b1625873407991c83 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 5 Apr 2024 14:43:57 +1000 Subject: [PATCH 04/11] Update samples and README to use recent .NET host APIs --- README.md | 66 ++++++++---------- samples/SimpleServiceSample/Program.cs | 62 ++++++++--------- samples/WebApplicationSample/Program.cs | 68 ++++++++++--------- samples/WebApplicationSample/Startup.cs | 41 ----------- samples/WebApplicationSample/appsettings.json | 5 +- 5 files changed, 98 insertions(+), 144 deletions(-) delete mode 100644 samples/WebApplicationSample/Startup.cs diff --git a/README.md b/README.md index 096f513..47e6cf9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,10 @@ Serilog logging for _Microsoft.Extensions.Hosting_. This package routes framework log messages through Serilog, so you can get information about the framework's internal operations written to the same Serilog sinks as your application events. -**ASP.NET Core** applications should consider [using _Serilog.AspNetCore_ instead](https://github.com/serilog/serilog-aspnetcore), which bundles this package and includes other ASP.NET Core-specific features. +**Versioning:** This package tracks the versioning and target framework support of its +[_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency. Most users should choose the version of _Serilog.AspNetCore_ that matches +their application's target framework. I.e. if you're targeting .NET 7.x, choose a 7.x version of _Serilog.AspNetCore_. If +you're targeting .NET 8.x, choose an 8.x _Serilog.AspNetCore_ version, and so on. ### Instructions @@ -13,46 +16,37 @@ dotnet add package Serilog.Extensions.Hosting dotnet add package Serilog.Sinks.Console ``` -**Next**, in your application's _Program.cs_ file, configure Serilog first. A `try`/`catch` block will ensure any configuration issues are appropriately logged: +**Next**, in your application's _Program.cs_ file, configure Serilog first. A `try`/`catch` block will ensure any configuration issues are appropriately logged. Call `AddSerilog()` on the host application builder: ```csharp -public class Program +using Serilog; + +Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); + +try { - public static int Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); - - try - { - Log.Information("Starting host"); - BuildHost(args).Run(); - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "Host terminated unexpectedly"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } - } -``` + Log.Information("Starting host"); -**Then**, add `UseSerilog()` to the host builder in `BuildHost()`. + var builder = Host.CreateApplicationBuilder(args); + builder.Services.AddHostedService(); + builder.Services.AddSerilog(); -```csharp - public static IHost BuildHost(string[] args) => - new HostBuilder() - .ConfigureServices(services => services.AddSingleton()) - .UseSerilog() // <- Add this line - .Build(); + var app = builder.Build(); + + await app.RunAsync(); + return 0; +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly"); + return 1; +} +finally +{ + await Log.CloseAndFlushAsync(); } ``` diff --git a/samples/SimpleServiceSample/Program.cs b/samples/SimpleServiceSample/Program.cs index c9a5b17..f6a8a3e 100644 --- a/samples/SimpleServiceSample/Program.cs +++ b/samples/SimpleServiceSample/Program.cs @@ -2,41 +2,39 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; +using SimpleServiceSample; -namespace SimpleServiceSample; +Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateBootstrapLogger(); -public static class Program +try { - public static int Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateBootstrapLogger(); + Log.Information("Getting the motors running..."); - 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(); - } - } + var builder = Host.CreateApplicationBuilder(args); + + builder.Services.AddHostedService(); - 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()); + builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration + .ReadFrom.Configuration(builder.Configuration) + .ReadFrom.Services(services) + .Enrich.FromLogContext() + .WriteTo.Console()); + + var app = builder.Build(); + + await app.RunAsync(); + + return 0; +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host terminated unexpectedly"); + return 1; +} +finally +{ + await Log.CloseAndFlushAsync(); } diff --git a/samples/WebApplicationSample/Program.cs b/samples/WebApplicationSample/Program.cs index 7c1c019..e6fa7e6 100644 --- a/samples/WebApplicationSample/Program.cs +++ b/samples/WebApplicationSample/Program.cs @@ -1,43 +1,45 @@ using System; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Serilog; -namespace WebApplicationSample; -public static class Program -{ - public static int Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .WriteTo.Console() - .CreateBootstrapLogger(); +Log.Logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateBootstrapLogger(); - Log.Information("Starting up!"); + Log.Information("Starting up!"); + +try +{ + var builder = WebApplication.CreateBuilder(); - try - { - CreateHostBuilder(args).Build().Run(); + builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration + .WriteTo.Console() + .ReadFrom.Configuration(builder.Configuration) + .ReadFrom.Services(services)); - Log.Information("Stopped cleanly"); - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "An unhandled exception occured during bootstrapping"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } - } + var app = builder.Build(); - 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 + app.MapGet("/", () => + { + Log.Information("Saying hello"); + return "Hello World!"; + }); + + await app.RunAsync(); + + Log.Information("Stopped cleanly"); + return 0; +} +catch (Exception ex) +{ + Log.Fatal(ex, "An unhandled exception occured during bootstrapping"); + return 1; +} +finally +{ + await Log.CloseAndFlushAsync(); +} diff --git a/samples/WebApplicationSample/Startup.cs b/samples/WebApplicationSample/Startup.cs deleted file mode 100644 index 2ac4443..0000000 --- a/samples/WebApplicationSample/Startup.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Serilog; - -namespace WebApplicationSample; - -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 configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapGet("/", async context => - { - Log.Information("Saying hello"); - await context.Response.WriteAsync("Hello World!"); - }); - }); - } -} \ No newline at end of file diff --git a/samples/WebApplicationSample/appsettings.json b/samples/WebApplicationSample/appsettings.json index 633356d..5521089 100644 --- a/samples/WebApplicationSample/appsettings.json +++ b/samples/WebApplicationSample/appsettings.json @@ -3,8 +3,9 @@ "MinimumLevel": { "Default": "Information", "Override": { - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.AspNetCore.Hosting": "Information", + "Microsoft.AspNetCore.Mvc": "Warning", + "Microsoft.AspNetCore.Routing": "Warning" } }, "WriteTo": [ From 4d2de16ce4c3f8e5b99c4d1703f7d0f5a6a24131 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 5 Apr 2024 14:48:14 +1000 Subject: [PATCH 05/11] Fix README versioning section wording --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 47e6cf9..71fa26d 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Serilog logging for _Microsoft.Extensions.Hosting_. This package routes framework log messages through Serilog, so you can get information about the framework's internal operations written to the same Serilog sinks as your application events. **Versioning:** This package tracks the versioning and target framework support of its -[_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency. Most users should choose the version of _Serilog.AspNetCore_ that matches -their application's target framework. I.e. if you're targeting .NET 7.x, choose a 7.x version of _Serilog.AspNetCore_. If -you're targeting .NET 8.x, choose an 8.x _Serilog.AspNetCore_ version, and so on. +[_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency. Most users should choose the version of _Serilog.Extensions.Hosting_ that matches +their application's target framework. I.e. if you're targeting .NET 7.x, choose a 7.x version of _Serilog.Extensions.Hosting_. If +you're targeting .NET 8.x, choose an 8.x _Serilog.Extensions.Hosting_ version, and so on. ### Instructions @@ -82,7 +82,3 @@ You can alternatively configure Serilog using a delegate as shown below: This has the advantage of making the `hostingContext`'s `Configuration` object available for configuration of the logger, but at the expense of ignoring `Exception`s raised earlier in program startup. If this method is used, `Log.Logger` is assigned implicitly, and closed when the app is shut down. - -### Versioning - -This package tracks the versioning and target framework support of its [_Microsoft.Extensions.Hosting_](https://nuget.org/packages/Microsoft.Extensions.Hosting) dependency. From 21bb78a917a4c9a761953fbabbbf117193d9de9b Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 5 Apr 2024 15:19:15 +1000 Subject: [PATCH 06/11] Remove outdated recommendation to set `Microsoft` to `Warning` [skip ci] --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 71fa26d..20840f5 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,6 @@ A more complete example, showing _appsettings.json_ configuration, can be found With _Serilog.Extensions.Hosting_ installed and configured, you can write log messages directly through Serilog or any `ILogger` interface injected by .NET. All loggers will use the same underlying implementation, levels, and destinations. -**Tip:** change the minimum level for `Microsoft` to `Warning` - ### Inline initialization You can alternatively configure Serilog using a delegate as shown below: From 4ec0cc22077a09b977f59f4283d74e43d6aa40b8 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Fri, 5 Apr 2024 15:20:57 +1000 Subject: [PATCH 07/11] One more outdated README example [skip ci] --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 20840f5..92c14e5 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,12 @@ You can alternatively configure Serilog using a delegate as shown below: ```csharp // dotnet add package Serilog.Settings.Configuration - .UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration - .ReadFrom.Configuration(hostingContext.Configuration) - .Enrich.FromLogContext() - .WriteTo.Console()) +builder.Services.AddSerilog((services, loggerConfiguration) => loggerConfiguration + .ReadFrom.Configuration(builder.Configuration) + .Enrich.FromLogContext() + .WriteTo.Console()) ``` -This has the advantage of making the `hostingContext`'s `Configuration` object available for configuration of the logger, but at the expense of ignoring `Exception`s raised earlier in program startup. +This has the advantage of making `builder`'s `Configuration` object available for configuration of the logger, but at the expense of ignoring `Exception`s raised earlier in program startup. If this method is used, `Log.Logger` is assigned implicitly, and closed when the app is shut down. From 796456dcb4d7a776c14124cd27be022ee811b500 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 27 Nov 2024 13:44:07 +1000 Subject: [PATCH 08/11] Update to .NET 9 SDK and Microsoft.Extensions.Hosting 9.0.0; Actions build; extend CreateBoostrapLogger() support to all TFMs --- .DS_Store | Bin 0 -> 6148 bytes .github/.DS_Store | Bin 0 -> 6148 bytes .github/workflows/ci.yml | 41 + Build.ps1 | 93 +- Directory.Build.props | 25 + Directory.Version.props | 6 + appveyor.yml | 28 - build.sh | 11 - global.json | 2 +- .../SimpleServiceSample.csproj | 9 +- .../WebApplicationSample.csproj | 9 +- serilog-extensions-hosting.sln | 15 +- .../AmbientDiagnosticContextCollector.cs | 10 +- .../Hosting/CachingReloadableLogger.cs | 105 +- .../Extensions/Hosting/DiagnosticContext.cs | 4 +- .../Hosting/DiagnosticContextCollector.cs | 14 +- .../Extensions/Hosting/LoggerBase.cs | 918 ++++++++++++++++++ .../Extensions/Hosting/ReloadableLogger.cs | 155 +-- .../Hosting/SerilogLoggerFactory.cs | 75 -- .../Properties/AssemblyInfo.cs | 5 +- .../Serilog.Extensions.Hosting.csproj | 37 +- .../SerilogHostBuilderExtensions.cs | 4 +- .../SerilogServiceCollectionExtensions.cs | 22 +- .../DiagnosticContextTests.cs | 11 +- .../ReloadableLoggerTests.cs | 8 +- .../Serilog.Extensions.Hosting.Tests.csproj | 21 +- .../SerilogHostBuilderExtensionsTests.cs | 14 +- .../Support/DisposeTrackingLogger.cs | 353 ------- .../Support/Some.cs | 2 +- 29 files changed, 1265 insertions(+), 732 deletions(-) create mode 100644 .DS_Store create mode 100644 .github/.DS_Store create mode 100644 .github/workflows/ci.yml create mode 100644 Directory.Build.props create mode 100644 Directory.Version.props delete mode 100644 appveyor.yml delete mode 100644 build.sh create mode 100644 src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs delete mode 100644 src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs delete mode 100644 test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6c2a51eb0e9a639fe9fd4ae4b6f5e9fa36f7473c GIT binary patch literal 6148 zcmeHKJ8DBQ5S&d6F{E+nQYQ%H2EsTe@CA%xNCE~IiThXiTsc~1KSj)oJG*e0h1E!_ z9SKeG_ALNg9JbHE48WA`h@%f<^L_V`-BrYhbe{2!12)^w*WG46%Kkgx+y^}24IlXW z&EM~QOC|-RfE17dQa}n^Sb-|A)5i;+tK+1A6u5l_{QJ=8j=gY5j86xLXaR^5hQm0I zUV_*>KA|o_QDlw^6ErunX@m6`ga7au#teOw2o2@z&i`#jAi*#5|)F=g{z^MZF zxtw|Zf1#i0|4&I;NdYPFuN1J!ao5S-N%0YOq)zQ5o> $GITHUB_ENV + - name: Build and Publish + env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: pwsh + run: | + ./Build.ps1 diff --git a/Build.ps1 b/Build.ps1 index cce9432..e798284 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -1,56 +1,79 @@ -echo "build: Build started" +Write-Output "build: Tool versions follow" + +dotnet --version +dotnet --list-sdks + +Write-Output "build: Build started" Push-Location $PSScriptRoot +try { + if(Test-Path .\artifacts) { + Write-Output "build: Cleaning ./artifacts" + Remove-Item ./artifacts -Force -Recurse + } -if(Test-Path .\artifacts) { - echo "build: Cleaning .\artifacts" - Remove-Item .\artifacts -Force -Recurse -} + & dotnet restore --no-cache + + $dbp = [Xml] (Get-Content .\Directory.Version.props) + $versionPrefix = $dbp.Project.PropertyGroup.VersionPrefix + + Write-Output "build: Package version prefix is $versionPrefix" + + $branch = @{ $true = $env:CI_TARGET_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$NULL -ne $env:CI_TARGET_BRANCH]; + $revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:CI_BUILD_NUMBER, 10); $false = "local" }[$NULL -ne $env:CI_BUILD_NUMBER]; + $suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)) -replace '([^a-zA-Z0-9\-]*)', '')-$revision"}[$branch -eq "main" -and $revision -ne "local"] + $commitHash = $(git rev-parse --short HEAD) + $buildSuffix = @{ $true = "$($suffix)-$($commitHash)"; $false = "$($branch)-$($commitHash)" }[$suffix -ne ""] -& dotnet restore --no-cache + Write-Output "build: Package version suffix is $suffix" + Write-Output "build: Build version suffix is $buildSuffix" -$branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL]; -$revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL]; -$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"] + & dotnet build -c Release --version-suffix=$buildSuffix /p:ContinuousIntegrationBuild=true + if($LASTEXITCODE -ne 0) { throw "Build failed" } -echo "build: Version suffix is $suffix" + foreach ($src in Get-ChildItem src/*) { + Push-Location $src -foreach ($src in ls src/*) { - Push-Location $src + Write-Output "build: Packaging project in $src" - echo "build: Packaging project in $src" + if ($suffix) { + & dotnet pack -c Release --no-build --no-restore -o ../../artifacts --version-suffix=$suffix + } else { + & dotnet pack -c Release --no-build --no-restore -o ../../artifacts + } + if($LASTEXITCODE -ne 0) { throw "Packaging failed" } - if($suffix) { - & dotnet pack -c Release --include-source -o ..\..\artifacts --version-suffix=$suffix - } else { - & dotnet pack -c Release --include-source -o ..\..\artifacts + Pop-Location } - - if($LASTEXITCODE -ne 0) { exit 1 } - Pop-Location -} + foreach ($test in Get-ChildItem test/*.Tests) { + Push-Location $test -foreach ($test in ls test/*.PerformanceTests) { - Push-Location $test + Write-Output "build: Testing project in $test" - echo "build: Building performance test project in $test" + & dotnet test -c Release --no-build --no-restore + if($LASTEXITCODE -ne 0) { throw "Testing failed" } - & dotnet build -c Release - if($LASTEXITCODE -ne 0) { exit 2 } + Pop-Location + } - Pop-Location -} + if ($env:NUGET_API_KEY) { + # GitHub Actions will only supply this to branch builds and not PRs. We publish + # builds from any branch this action targets (i.e. main and dev). -foreach ($test in ls test/*.Tests) { - Push-Location $test + Write-Output "build: Publishing NuGet packages" - echo "build: Testing project in $test" + foreach ($nupkg in Get-ChildItem artifacts/*.nupkg) { + & dotnet nuget push -k $env:NUGET_API_KEY -s https://api.nuget.org/v3/index.json "$nupkg" + if($LASTEXITCODE -ne 0) { throw "Publishing failed" } + } - & dotnet test -c Release - if($LASTEXITCODE -ne 0) { exit 3 } + if (!($suffix)) { + Write-Output "build: Creating release for version $versionPrefix" + iex "gh release create v$versionPrefix --title v$versionPrefix --generate-notes $(get-item ./artifacts/*.nupkg) $(get-item ./artifacts/*.snupkg)" + } + } +} finally { Pop-Location } - -Pop-Location diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..c114992 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,25 @@ + + + + + latest + True + + true + $(MSBuildThisFileDirectory)assets/Serilog.snk + false + enable + enable + true + true + true + true + snupkg + + + + + + + diff --git a/Directory.Version.props b/Directory.Version.props new file mode 100644 index 0000000..c8c7b22 --- /dev/null +++ b/Directory.Version.props @@ -0,0 +1,6 @@ + + + + 9.0.0 + + diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index f52401f..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: '{build}' -skip_tags: true -image: Visual Studio 2022 -test: off -build_script: -- pwsh: | - Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1" - ./dotnet-install.ps1 -JSonFile global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet' - ./Build.ps1 -artifacts: -- path: artifacts/Serilog.*.nupkg -skip_commits: - files: - - README.md -deploy: -- provider: NuGet - skip_symbols: true - api_key: - secure: H96ajkMxwIafhF2vrr+UAUS10bFcAL/1wc3iphidRiYi9WoTc2i8shTLtF+75ODb - on: - branch: /^(main|dev)$/ -- provider: GitHub - auth_token: - secure: p4LpVhBKxGS5WqucHxFQ5c7C8cP74kbNB0Z8k9Oxx/PMaDQ1+ibmoexNqVU5ZlmX - artifact: /Serilog.*\.nupkg/ - tag: v$(appveyor_build_version) - on: - branch: main diff --git a/build.sh b/build.sh deleted file mode 100644 index 433a9b4..0000000 --- a/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -dotnet --info -dotnet restore - -for path in src/**/*.csproj; do - dotnet build -f netstandard2.0 -c Release ${path} -done - -for path in test/*.Tests/*.csproj; do - dotnet test -f netcoreapp2.0 -c Release ${path} -done diff --git a/global.json b/global.json index d079f83..db8627a 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { + "version": "9.0.100", "allowPrerelease": false, - "version": "8.0.100", "rollForward": "latestFeature" } } diff --git a/samples/SimpleServiceSample/SimpleServiceSample.csproj b/samples/SimpleServiceSample/SimpleServiceSample.csproj index 3451be2..9890c70 100644 --- a/samples/SimpleServiceSample/SimpleServiceSample.csproj +++ b/samples/SimpleServiceSample/SimpleServiceSample.csproj @@ -1,7 +1,8 @@  - net8.0 + net9.0 + false @@ -9,9 +10,9 @@ - - - + + + diff --git a/samples/WebApplicationSample/WebApplicationSample.csproj b/samples/WebApplicationSample/WebApplicationSample.csproj index 8fbe382..ff0965f 100644 --- a/samples/WebApplicationSample/WebApplicationSample.csproj +++ b/samples/WebApplicationSample/WebApplicationSample.csproj @@ -1,7 +1,8 @@ - net8.0 + net9.0 + false @@ -9,9 +10,9 @@ - - - + + + diff --git a/serilog-extensions-hosting.sln b/serilog-extensions-hosting.sln index 2208752..37c65ef 100644 --- a/serilog-extensions-hosting.sln +++ b/serilog-extensions-hosting.sln @@ -11,11 +11,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{F240 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{9C21B9DF-AEDD-4AA6-BEA4-912DEF3E5B8E}" ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml - Build.ps1 = Build.ps1 - global.json = global.json README.md = README.md assets\Serilog.snk = assets\Serilog.snk + Build.ps1 = Build.ps1 + global.json = global.json + Directory.Version.props = Directory.Version.props + Directory.Build.props = Directory.Build.props EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Extensions.Hosting", "src\Serilog.Extensions.Hosting\Serilog.Extensions.Hosting.csproj", "{0549D23F-986B-4FB2-BACE-16FD7A7BC9EF}" @@ -26,6 +27,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleServiceSample", "samp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplicationSample", "samples\WebApplicationSample\WebApplicationSample.csproj", "{1ACDCA67-F404-45AB-9348-98E55E03CB8C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{5C68E1CE-D650-4500-B32C-21EDD0AAA0A7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{10168223-6AEF-4B08-B6FD-50C6FD3B6E84}" + ProjectSection(SolutionItems) = preProject + .github\workflows\ci.yml = .github\workflows\ci.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +65,7 @@ Global {AD51759B-CD58-473F-9620-0B0E56A123A1} = {E30F638E-BBBE-4AD1-93CE-48CC69CFEFE1} {E5A82756-4619-4E6B-8B26-6D83E00E99F0} = {F2407211-6043-439C-8E06-3641634332E7} {1ACDCA67-F404-45AB-9348-98E55E03CB8C} = {F2407211-6043-439C-8E06-3641634332E7} + {10168223-6AEF-4B08-B6FD-50C6FD3B6E84} = {5C68E1CE-D650-4500-B32C-21EDD0AAA0A7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {811E61C5-3871-4633-AFAE-B35B619C8A10} diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs index 02eb1c9..a96545a 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/AmbientDiagnosticContextCollector.cs @@ -12,21 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Threading; - namespace Serilog.Extensions.Hosting; class AmbientDiagnosticContextCollector : IDisposable { - static readonly AsyncLocal AmbientCollector = - new AsyncLocal(); + static readonly AsyncLocal AmbientCollector = new(); // The indirection here ensures that completing collection cleans up the collector in all // execution contexts. Via @benaadams' addition to `HttpContextAccessor` :-) - DiagnosticContextCollector _collector; + DiagnosticContextCollector? _collector; - public static DiagnosticContextCollector Current => AmbientCollector.Value?._collector; + public static DiagnosticContextCollector? Current => AmbientCollector.Value?._collector; public static DiagnosticContextCollector Begin() { diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs index 7f235e5..3b9d058 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/CachingReloadableLogger.cs @@ -12,23 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if !NO_RELOADABLE_LOGGER - -using System; -using System.Collections.Generic; -using System.Threading; +using System.Diagnostics.CodeAnalysis; using Serilog.Core; using Serilog.Events; namespace Serilog.Extensions.Hosting; -class CachingReloadableLogger : ILogger, IReloadableLogger +class CachingReloadableLogger : LoggerBase, ILogger, IReloadableLogger { readonly ReloadableLogger _reloadableLogger; readonly Func _configure; readonly IReloadableLogger _parent; - - ILogger _root, _cached; + + ILogger _root; + ILogger? _cached; bool _frozen; public CachingReloadableLogger(ReloadableLogger reloadableLogger, ILogger root, IReloadableLogger parent, Func configure) @@ -48,10 +45,10 @@ public ILogger ReloadLogger() public ILogger ForContext(ILogEventEnricher enricher) { - if (enricher == null) return this; + if (enricher == null!) return this; if (_frozen) - return _cached.ForContext(enricher); + return _cached!.ForContext(enricher); if (_reloadableLogger.CreateChild( _root, @@ -71,10 +68,10 @@ public ILogger ForContext(ILogEventEnricher enricher) public ILogger ForContext(IEnumerable enrichers) { - if (enrichers == null) return this; + if (enrichers == null!) return this; if (_frozen) - return _cached.ForContext(enrichers); + return _cached!.ForContext(enrichers); if (_reloadableLogger.CreateChild( _root, @@ -92,12 +89,12 @@ public ILogger ForContext(IEnumerable enrichers) return child; } - public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false) { - if (propertyName == null) return this; + if (propertyName == null!) return this; if (_frozen) - return _cached.ForContext(propertyName, value, destructureObjects); + return _cached!.ForContext(propertyName, value, destructureObjects); ILogger child; if (value == null || value is string || value.GetType().IsPrimitive || value.GetType().IsEnum) @@ -147,7 +144,7 @@ public ILogger ForContext(string propertyName, object value, bool destructureObj public ILogger ForContext() { if (_frozen) - return _cached.ForContext(); + return _cached!.ForContext(); if (_reloadableLogger.CreateChild( _root, @@ -168,7 +165,7 @@ public ILogger ForContext() public ILogger ForContext(Type source) { if (_frozen) - return _cached.ForContext(source); + return _cached!.ForContext(source); if (_reloadableLogger.CreateChild( _root, @@ -186,7 +183,7 @@ public ILogger ForContext(Type source) return child; } - void Update(ILogger newRoot, ILogger newCached, bool frozen) + void Update(ILogger newRoot, ILogger? newCached, bool frozen) { _root = newRoot; _cached = newCached; @@ -194,18 +191,25 @@ void Update(ILogger newRoot, ILogger newCached, bool 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. +#if FEATURE_MBPW Interlocked.MemoryBarrierProcessWide(); - +#else + Thread.MemoryBarrier(); +#endif _frozen = frozen; +#if FEATURE_MBPW Interlocked.MemoryBarrierProcessWide(); +#else + Thread.MemoryBarrier(); +#endif } - public void Write(LogEvent logEvent) + public override void Write(LogEvent logEvent) { if (_frozen) { - _cached.Write(logEvent); + _cached!.Write(logEvent); return; } @@ -222,11 +226,11 @@ public void Write(LogEvent logEvent) } } - public void Write(LogEventLevel level, string messageTemplate) + public override void Write(LogEventLevel level, string messageTemplate) { if (_frozen) { - _cached.Write(level, messageTemplate); + _cached!.Write(level, messageTemplate); return; } @@ -244,11 +248,11 @@ public void Write(LogEventLevel level, string messageTemplate) } } - public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + public override void Write(LogEventLevel level, string messageTemplate, T propertyValue) { if (_frozen) { - _cached.Write(level, messageTemplate, propertyValue); + _cached!.Write(level, messageTemplate, propertyValue); return; } @@ -267,11 +271,11 @@ public void Write(LogEventLevel level, string messageTemplate, T propertyValu } } - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) { if (_frozen) { - _cached.Write(level, messageTemplate, propertyValue0, propertyValue1); + _cached!.Write(level, messageTemplate, propertyValue0, propertyValue1); return; } @@ -291,12 +295,12 @@ public void Write(LogEventLevel level, string messageTemplate, T0 proper } } - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) { if (_frozen) { - _cached.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + _cached!.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); return; } @@ -317,11 +321,11 @@ public void Write(LogEventLevel level, string messageTemplate, T0 pr } } - public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + public override void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues) { if (_frozen) { - _cached.Write(level, messageTemplate, propertyValues); + _cached!.Write(level, messageTemplate, propertyValues); return; } @@ -340,11 +344,11 @@ public void Write(LogEventLevel level, string messageTemplate, params object[] p } } - public void Write(LogEventLevel level, Exception exception, string messageTemplate) + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate) { if (_frozen) { - _cached.Write(level, exception, messageTemplate); + _cached!.Write(level, exception, messageTemplate); return; } @@ -363,11 +367,11 @@ public void Write(LogEventLevel level, Exception exception, string messageTempla } } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue) { if (_frozen) { - _cached.Write(level, exception, messageTemplate, propertyValue); + _cached!.Write(level, exception, messageTemplate, propertyValue); return; } @@ -387,12 +391,12 @@ public void Write(LogEventLevel level, Exception exception, string messageTem } } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) { if (_frozen) { - _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + _cached!.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); return; } @@ -413,12 +417,12 @@ public void Write(LogEventLevel level, Exception exception, string messa } } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) { if (_frozen) { - _cached.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + _cached!.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); return; } @@ -440,11 +444,11 @@ public void Write(LogEventLevel level, Exception exception, string m } } - public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues) { if (_frozen) { - _cached.Write(level, exception, messageTemplate, propertyValues); + _cached!.Write(level, exception, messageTemplate, propertyValues); return; } @@ -468,7 +472,7 @@ public bool IsEnabled(LogEventLevel level) { if (_frozen) { - return _cached.IsEnabled(level); + return _cached!.IsEnabled(level); } if (_reloadableLogger.InvokeIsEnabled( @@ -487,12 +491,15 @@ public bool IsEnabled(LogEventLevel level) return isEnabled; } - public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, - out IEnumerable boundProperties) + public bool BindMessageTemplate(string messageTemplate, object?[]? propertyValues, + [NotNullWhen(true)] + out MessageTemplate? parsedTemplate, + [NotNullWhen(true)] + out IEnumerable? boundProperties) { if (_frozen) { - return _cached.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + return _cached!.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); } if (_reloadableLogger.InvokeBindMessageTemplate( @@ -514,11 +521,13 @@ public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, return canBind; } - public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + public bool BindProperty(string? propertyName, object? value, bool destructureObjects, + [NotNullWhen(true)] + out LogEventProperty? property) { if (_frozen) { - return _cached.BindProperty(propertyName, value, destructureObjects, out property); + return _cached!.BindProperty(propertyName, value, destructureObjects, out property); } if (_reloadableLogger.InvokeBindProperty( @@ -540,5 +549,3 @@ public bool BindProperty(string propertyName, object value, bool destructureObje return canBind; } } - -#endif diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs index 7f4ee2b..62fce9f 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContext.cs @@ -23,13 +23,13 @@ namespace Serilog.Extensions.Hosting; /// Consumers should use to set context properties. public sealed class DiagnosticContext : IDiagnosticContext { - readonly ILogger _logger; + readonly ILogger? _logger; /// /// Construct a . /// /// A logger for binding properties in the context, or null to use . - public DiagnosticContext(ILogger logger) + public DiagnosticContext(ILogger? logger) { _logger = logger; } diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs index 05734f6..6ade4ff 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/DiagnosticContextCollector.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Serilog.Events; +using Serilog.Events; namespace Serilog.Extensions.Hosting; @@ -10,9 +8,9 @@ namespace Serilog.Extensions.Hosting; public sealed class DiagnosticContextCollector : IDisposable { readonly IDisposable _chainedDisposable; - readonly object _propertiesLock = new object(); - Exception _exception; - Dictionary _properties = new Dictionary(); + readonly object _propertiesLock = new(); + Exception? _exception; + Dictionary? _properties = new(); /// /// Construct a . @@ -70,7 +68,7 @@ public void SetException(Exception exception) /// True if properties could be collected. /// [Obsolete("Replaced by TryComplete(out IEnumerable properties, out Exception exception).")] - public bool TryComplete(out IEnumerable properties) + public bool TryComplete(out IEnumerable? properties) { return TryComplete(out properties, out _); } @@ -85,7 +83,7 @@ public bool TryComplete(out IEnumerable properties) /// True if properties could be collected. /// /// - public bool TryComplete(out IEnumerable properties, out Exception exception) + public bool TryComplete(out IEnumerable? properties, out Exception? exception) { lock (_propertiesLock) { diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs new file mode 100644 index 0000000..c52256b --- /dev/null +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/LoggerBase.cs @@ -0,0 +1,918 @@ +// Copyright 2020 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Serilog.Core; +using Serilog.Events; + +namespace Serilog.Extensions.Hosting; + +/// +/// Implements default methods for caching/reloadable loggers. +/// +public abstract class LoggerBase +{ + static readonly object[] NoPropertyValues = []; + + internal LoggerBase() + { + } + + /// + /// Write an event to the log. + /// + /// The event to write. + public abstract void Write(LogEvent logEvent); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, string messageTemplate); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// + /// + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, + T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public abstract void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate) + => Write(LogEventLevel.Verbose, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Verbose, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, params object?[]? propertyValues) + => Verbose((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Verbose, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate) + => Write(LogEventLevel.Debug, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Debug, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, params object?[]? propertyValues) + => Debug((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Debug, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Debug, exception, messageTemplate, propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate) + => Write(LogEventLevel.Information, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Information, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, params object?[]? propertyValues) + => Information((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Information, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception? exception, string messageTemplate, T0 propertyValue0, + T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Information, exception, messageTemplate, propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate) + => Write(LogEventLevel.Warning, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Warning, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, params object?[]? propertyValues) + => Warning((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Warning, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Warning, exception, messageTemplate, propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate) + => Write(LogEventLevel.Error, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Error, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, params object?[]? propertyValues) + => Error((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Error, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + => Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Error, exception, messageTemplate, propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate) + => Write(LogEventLevel.Fatal, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T propertyValue) + => Write(LogEventLevel.Fatal, messageTemplate, propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + => Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, params object?[]? propertyValues) + => Fatal((Exception?)null, messageTemplate, propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception? exception, string messageTemplate) + => Write(LogEventLevel.Fatal, exception, messageTemplate, NoPropertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception? exception, string messageTemplate, T propertyValue) + => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + T2 propertyValue2) + => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception? exception, string messageTemplate, params object?[]? propertyValues) + => Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValues); +} \ 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 729ae35..74d0169 100644 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs +++ b/src/Serilog.Extensions.Hosting/Extensions/Hosting/ReloadableLogger.cs @@ -12,12 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if !NO_RELOADABLE_LOGGER - -using System; -using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -using System.Threading; using Serilog.Core; using Serilog.Events; @@ -29,9 +25,9 @@ namespace Serilog.Extensions.Hosting; /// A Serilog that can be reconfigured without invalidating existing /// instances derived from it. /// -public sealed class ReloadableLogger : ILogger, IReloadableLogger, IDisposable +public sealed class ReloadableLogger : LoggerBase, ILogger, IReloadableLogger, IDisposable { - readonly object _sync = new object(); + readonly object _sync = new(); Logger _logger; // One-way; if the value is `true` it can never again be made `false`, allowing "double-checked" reads. If @@ -84,7 +80,11 @@ public Logger Freeze() // 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. +#if FEATURE_MBPW Interlocked.MemoryBarrierProcessWide(); +#else + Thread.MemoryBarrier(); +#endif return _logger; } @@ -100,7 +100,7 @@ public void Dispose() /// public ILogger ForContext(ILogEventEnricher enricher) { - if (enricher == null) return this; + if (enricher == null!) return this; if (_frozen) return _logger.ForContext(enricher); @@ -112,7 +112,7 @@ public ILogger ForContext(ILogEventEnricher enricher) /// public ILogger ForContext(IEnumerable enrichers) { - if (enrichers == null) return this; + if (enrichers == null!) return this; if (_frozen) return _logger.ForContext(enrichers); @@ -122,9 +122,9 @@ public ILogger ForContext(IEnumerable enrichers) } /// - public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false) { - if (propertyName == null) return this; + if (propertyName == null!) return this; if (_frozen) return _logger.ForContext(propertyName, value, destructureObjects); @@ -146,7 +146,7 @@ public ILogger ForContext() /// public ILogger ForContext(Type source) { - if (source == null) return this; + if (source == null!) return this; if (_frozen) return _logger.ForContext(source); @@ -155,8 +155,8 @@ public ILogger ForContext(Type source) return new CachingReloadableLogger(this, _logger, this, p => p.ForContext(source)); } - /// - public void Write(LogEvent logEvent) + /// + public override void Write(LogEvent logEvent) { if (_frozen) { @@ -170,8 +170,8 @@ public void Write(LogEvent logEvent) } } - /// - public void Write(LogEventLevel level, string messageTemplate) + /// + public override void Write(LogEventLevel level, string messageTemplate) { if (_frozen) { @@ -185,8 +185,8 @@ public void Write(LogEventLevel level, string messageTemplate) } } - /// - public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + /// + public override void Write(LogEventLevel level, string messageTemplate, T propertyValue) { if (_frozen) { @@ -200,8 +200,8 @@ public void Write(LogEventLevel level, string messageTemplate, T propertyValu } } - /// - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + /// + public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) { if (_frozen) { @@ -215,8 +215,8 @@ public void Write(LogEventLevel level, string messageTemplate, T0 proper } } - /// - public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + /// + public override void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) { if (_frozen) @@ -231,8 +231,8 @@ public void Write(LogEventLevel level, string messageTemplate, T0 pr } } - /// - public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + /// + public override void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues) { if (_frozen) { @@ -246,8 +246,8 @@ public void Write(LogEventLevel level, string messageTemplate, params object[] p } } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate) + /// + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate) { if (_frozen) { @@ -261,8 +261,8 @@ public void Write(LogEventLevel level, Exception exception, string messageTempla } } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + /// + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue) { if (_frozen) { @@ -276,8 +276,8 @@ public void Write(LogEventLevel level, Exception exception, string messageTem } } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + /// + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) { if (_frozen) { @@ -291,8 +291,8 @@ public void Write(LogEventLevel level, Exception exception, string messa } } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, + /// + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) { if (_frozen) @@ -307,8 +307,8 @@ public void Write(LogEventLevel level, Exception exception, string m } } - /// - public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + /// + public override void Write(LogEventLevel level, Exception? exception, string messageTemplate, params object?[]? propertyValues) { if (_frozen) { @@ -335,10 +335,13 @@ public bool IsEnabled(LogEventLevel level) return _logger.IsEnabled(level); } } - + /// - public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, - out IEnumerable boundProperties) + public bool BindMessageTemplate(string messageTemplate, object?[]? propertyValues, + [NotNullWhen(true)] + out MessageTemplate? parsedTemplate, + [NotNullWhen(true)] + out IEnumerable? boundProperties) { if (_frozen) { @@ -352,7 +355,7 @@ public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, } /// - public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + public bool BindProperty(string? propertyName, object? value, bool destructureObjects, [NotNullWhen(true)] out LogEventProperty? property) { if (_frozen) { @@ -365,8 +368,10 @@ public bool BindProperty(string propertyName, object value, bool destructureObje } } + // `newRoot` is null when the second returned tuple argument is `false`, but the signature of the method doesn't currently + // allow this to be expressed. [MethodImpl(MethodImplOptions.AggressiveInlining)] - (ILogger, bool) UpdateForCaller(ILogger root, ILogger cached, IReloadableLogger caller, out ILogger newRoot, out ILogger newCached, out bool frozen) + (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. @@ -381,9 +386,9 @@ public bool BindProperty(string propertyName, object value, bool destructureObje return (newCached, true); } - if (cached != null && root == _logger) + if (cached != null! && root == _logger) { - newRoot = default; + newRoot = default!; newCached = default; frozen = false; return (cached, false); @@ -395,7 +400,7 @@ public bool BindProperty(string propertyName, object value, bool destructureObje 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) + 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) { @@ -412,9 +417,9 @@ internal bool InvokeIsEnabled(ILogger root, ILogger cached, IReloadableLogger ca } } - 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) + internal bool InvokeBindMessageTemplate(ILogger root, ILogger? cached, IReloadableLogger caller, string messageTemplate, + object?[]? propertyValues, [NotNullWhen(true)] out MessageTemplate? parsedTemplate, [NotNullWhen(true)] out IEnumerable? boundProperties, + out bool canBind, out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -431,9 +436,9 @@ internal bool InvokeBindMessageTemplate(ILogger root, ILogger cached, IReloadabl } } - 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 InvokeBindProperty(ILogger root, ILogger? cached, IReloadableLogger caller, string? propertyName, + object? propertyValue, bool destructureObjects, [NotNullWhen(true)] out LogEventProperty? property, + out bool canBind, out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -450,7 +455,7 @@ internal bool InvokeBindProperty(ILogger root, ILogger cached, IReloadableLogger } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger newCached, out bool frozen) + internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEvent logEvent, out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -467,8 +472,8 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller } } - 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, + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -485,9 +490,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + internal bool InvokeWrite(ILogger root, ILogger? cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, T propertyValue, - out ILogger newRoot, out ILogger newCached, out bool frozen) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -504,9 +509,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger cal } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + 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) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -523,9 +528,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogge } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, + 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) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -542,9 +547,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableL } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, string messageTemplate, - object[] propertyValues, - 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) { @@ -561,8 +566,8 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller } } - 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, + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -579,9 +584,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + 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) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -598,9 +603,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger cal } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + 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) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -617,9 +622,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogge } } - internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller, LogEventLevel level, Exception exception, string messageTemplate, + 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) + out ILogger newRoot, out ILogger? newCached, out bool frozen) { if (_frozen) { @@ -636,9 +641,9 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableL } } - 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) + 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) { @@ -658,11 +663,11 @@ internal bool InvokeWrite(ILogger root, ILogger cached, IReloadableLogger caller internal bool CreateChild( ILogger root, IReloadableLogger parent, - ILogger cachedParent, + ILogger? cachedParent, Func configureChild, out ILogger child, out ILogger newRoot, - out ILogger newCached, + out ILogger? newCached, out bool frozen) { if (_frozen) @@ -675,11 +680,9 @@ internal bool CreateChild( // 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; + newRoot = default!; newCached = default; frozen = default; return false; } } - -#endif diff --git a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs b/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs deleted file mode 100644 index f60dae3..0000000 --- a/src/Serilog.Extensions.Hosting/Extensions/Hosting/SerilogLoggerFactory.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018 Serilog Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.ComponentModel; -using Microsoft.Extensions.Logging; -using Serilog.Debugging; -using Serilog.Extensions.Logging; - -// 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; - -/// -/// 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; - - /// - /// 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); - } - - /// - /// 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); - } - - /// - /// 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/Properties/AssemblyInfo.cs b/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs index 8ec980f..22cba5d 100644 --- a/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs +++ b/src/Serilog.Extensions.Hosting/Properties/AssemblyInfo.cs @@ -1,7 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -[assembly: AssemblyVersion("7.0.0.0")] +using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Serilog.Extensions.Hosting.Tests, PublicKey=" + "0024000004800000940000000602000000240000525341310004000001000100fb8d13fd344a1c" + diff --git a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj index bca67be..12ff5b6 100644 --- a/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj +++ b/src/Serilog.Extensions.Hosting/Serilog.Extensions.Hosting.csproj @@ -2,45 +2,42 @@ Serilog support for .NET Core logging in hosted services - - 8.0.0 Microsoft;Serilog Contributors - net462;netstandard2.0;net6.0;net7.0;net8.0 - latest - true - true - ../../assets/Serilog.snk - true - true + net462;netstandard2.0;netstandard2.1;net8.0;net9.0 serilog;aspnet;aspnetcore;hosting icon.png https://github.com/serilog/serilog-extensions-hosting Apache-2.0 - https://github.com/serilog/serilog-extensions-hosting - git - false Serilog README.md - - $(DefineConstants);NO_RELOADABLE_LOGGER + + $(DefineConstants);FEATURE_MBPW + + + + $(DefineConstants);FEATURE_MBPW + + + + $(DefineConstants);FEATURE_MBPW - - + + - - - - + + + + diff --git a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs index d8b8c4a..f777880 100644 --- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs @@ -39,9 +39,9 @@ public static class SerilogHostBuilderExtensions /// The host builder. public static IHostBuilder UseSerilog( this IHostBuilder builder, - ILogger logger = null, + ILogger? logger = null, bool dispose = false, - LoggerProviderCollection providers = null) + LoggerProviderCollection? providers = null) { if (builder == null) throw new ArgumentNullException(nameof(builder)); diff --git a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs index d0d21af..9e9591b 100644 --- a/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogServiceCollectionExtensions.cs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Serilog.Extensions.Hosting; using Serilog.Extensions.Logging; @@ -55,9 +53,9 @@ public RegisteredLogger(ILogger logger) /// The service collection. public static IServiceCollection AddSerilog( this IServiceCollection collection, - ILogger logger = null, + ILogger? logger = null, bool dispose = false, - LoggerProviderCollection providers = null) + LoggerProviderCollection? providers = null) { if (collection == null) throw new ArgumentNullException(nameof(collection)); @@ -75,7 +73,7 @@ public static IServiceCollection AddSerilog( } else { - collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)); + collection.AddSingleton(_ => new SerilogLoggerFactory(logger, dispose)); } if (logger != null) @@ -110,7 +108,7 @@ public static IServiceCollection AddSerilog( if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); return AddSerilog( collection, - (services, loggerConfiguration) => + (_, loggerConfiguration) => configureLogger(loggerConfiguration), preserveStaticLogger: preserveStaticLogger, writeToProviders: writeToProviders); @@ -138,14 +136,10 @@ public static IServiceCollection AddSerilog( 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; -#else - const bool useReload = false; -#endif - LoggerProviderCollection loggerProviders = null; + LoggerProviderCollection? loggerProviders = null; if (writeToProviders) { loggerProviders = new LoggerProviderCollection(); @@ -154,7 +148,6 @@ public static IServiceCollection AddSerilog( collection.AddSingleton(services => { ILogger logger; -#if !NO_RELOADABLE_LOGGER if (useReload) { reloadable!.Reload(cfg => @@ -169,7 +162,6 @@ public static IServiceCollection AddSerilog( logger = reloadable.Freeze(); } else -#endif { var loggerConfiguration = new LoggerConfiguration(); @@ -195,7 +187,7 @@ public static IServiceCollection AddSerilog( { var logger = services.GetRequiredService().Logger; - ILogger registeredLogger = null; + ILogger? registeredLogger = null; if (preserveStaticLogger) { registeredLogger = logger; @@ -231,7 +223,7 @@ static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRe // Consumed by e.g. middleware collection.AddSingleton(services => { - ILogger logger = useRegisteredLogger ? services.GetRequiredService().Logger : null; + ILogger? logger = useRegisteredLogger ? services.GetRequiredService().Logger : null; return new DiagnosticContext(logger); }); // Consumed by user code diff --git a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs index d66114b..ba36bc7 100644 --- a/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/DiagnosticContextTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Serilog.Events; +using Serilog.Events; using Serilog.Extensions.Hosting.Tests.Support; using Xunit; @@ -36,7 +33,7 @@ public async Task PropertiesAreCollectedInAnActiveContext() dc.Set(Some.String("second"), Some.Int32()); Assert.True(collector.TryComplete(out var properties, out var exception)); - Assert.Equal(2, properties.Count()); + Assert.Equal(2, properties!.Count()); Assert.Null(exception); Assert.False(collector.TryComplete(out _, out _)); @@ -99,7 +96,7 @@ public void ExistingPropertiesCanBeUpdated() dc.Set("name", 20); Assert.True(collector.TryComplete(out var properties, out var exception)); - var prop = Assert.Single(properties); + var prop = Assert.Single(properties!); var scalar = Assert.IsType(prop.Value); Assert.Equal(20, scalar.Value); Assert.Null(exception); @@ -115,6 +112,6 @@ public void ExistingExceptionCanBeUpdated() dc.SetException(new Exception("ex2")); Assert.True(collector.TryComplete(out _, out var collectedException)); - Assert.Equal("ex2", collectedException.Message); + Assert.Equal("ex2", collectedException!.Message); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs index 80a0239..cd24597 100644 --- a/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/ReloadableLoggerTests.cs @@ -1,8 +1,4 @@ -#if !NO_RELOADABLE_LOGGER - -using System.Collections.Generic; -using System.Linq; -using Serilog.Core; +using Serilog.Core; using Serilog.Events; using Serilog.Extensions.Hosting.Tests.Support; using Xunit; @@ -103,5 +99,3 @@ public void ReloadableLoggersRecordEnrichment() Assert.All(emittedEvents, e => Assert.Equal(2, e.Properties.Count)); } } - -#endif 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 1f5c9d6..2d764f6 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj +++ b/test/Serilog.Extensions.Hosting.Tests/Serilog.Extensions.Hosting.Tests.csproj @@ -1,15 +1,10 @@  - net4.8;net6.0;net7.0;net8.0 - ../../assets/Serilog.snk - true - true - latest - - - - $(DefineConstants);NO_RELOADABLE_LOGGER + + net4.8;net6.0;net8.0;net9.0 + false @@ -17,10 +12,10 @@ - - - - + + + + diff --git a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs index 53dce78..02aed72 100644 --- a/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs +++ b/test/Serilog.Extensions.Hosting.Tests/SerilogHostBuilderExtensionsTests.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -61,9 +59,9 @@ public void ServicesAreRegisteredWhenCallingUseSerilogWithConfigureDelegate() provider.GetRequiredService(); } - private class FakeHostBuilder : IHostBuilder + class FakeHostBuilder : IHostBuilder { - private readonly IServiceCollection _collection; + readonly IServiceCollection _collection; public FakeHostBuilder(IServiceCollection collection) => _collection = collection; @@ -79,16 +77,18 @@ public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) { - configureDelegate(null, _collection); + configureDelegate(null!, _collection); return this; } public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) + where TContainerBuilder: notnull { throw new NotImplementedException(); } public IHostBuilder UseServiceProviderFactory(Func> factory) + where TContainerBuilder: notnull { throw new NotImplementedException(); } @@ -103,6 +103,6 @@ public IHost Build() throw new NotImplementedException(); } - public IDictionary Properties { get; } + public IDictionary Properties { get; } = new Dictionary(); } } diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs b/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs deleted file mode 100644 index ff1632d..0000000 --- a/test/Serilog.Extensions.Hosting.Tests/Support/DisposeTrackingLogger.cs +++ /dev/null @@ -1,353 +0,0 @@ -using System; -using System.Collections.Generic; -using Serilog.Core; -using Serilog.Events; - -namespace Serilog.Extensions.Hosting.Tests.Support; - -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; - } -} diff --git a/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs index df7a1ac..8ea9d94 100644 --- a/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs +++ b/test/Serilog.Extensions.Hosting.Tests/Support/Some.cs @@ -12,7 +12,7 @@ static class Some 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())); From 4269818fc5437901ca9b5518e432f17e083ed9d3 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 27 Nov 2024 13:46:25 +1000 Subject: [PATCH 09/11] Remove .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes .github/.DS_Store | Bin 6148 -> 0 bytes .gitignore | 3 +++ 3 files changed, 3 insertions(+) delete mode 100644 .DS_Store delete mode 100644 .github/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 6c2a51eb0e9a639fe9fd4ae4b6f5e9fa36f7473c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ8DBQ5S&d6F{E+nQYQ%H2EsTe@CA%xNCE~IiThXiTsc~1KSj)oJG*e0h1E!_ z9SKeG_ALNg9JbHE48WA`h@%f<^L_V`-BrYhbe{2!12)^w*WG46%Kkgx+y^}24IlXW z&EM~QOC|-RfE17dQa}n^Sb-|A)5i;+tK+1A6u5l_{QJ=8j=gY5j86xLXaR^5hQm0I zUV_*>KA|o_QDlw^6ErunX@m6`ga7au#teOw2o2@z&i`#jAi*#5|)F=g{z^MZF zxtw|Zf1#i0|4&I;NdYPFuN1J!ao5S-N%0YOq)zQ5o Date: Wed, 27 Nov 2024 14:10:22 +1000 Subject: [PATCH 10/11] Update build badge [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92c14e5..9f0008a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Serilog.Extensions.Hosting [![Build status](https://ci.appveyor.com/api/projects/status/ue4s7htjwj88fulh?svg=true)](https://ci.appveyor.com/project/serilog/serilog-extensions-hosting) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Extensions.Hosting.svg?style=flat)](https://www.nuget.org/packages/Serilog.Extensions.Hosting/) +# Serilog.Extensions.Hosting [![Build status](https://github.com/serilog/serilog-extensions-hosting/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/serilog/serilog-extensions-hosting/actions) [![NuGet Version](http://img.shields.io/nuget/v/Serilog.Extensions.Hosting.svg?style=flat)](https://www.nuget.org/packages/Serilog.Extensions.Hosting/) Serilog logging for _Microsoft.Extensions.Hosting_. This package routes framework log messages through Serilog, so you can get information about the framework's internal operations written to the same Serilog sinks as your application events. From 87e316f7d31ae431747d1106976dfceffdecc32c Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Mon, 9 Dec 2024 10:30:09 +1000 Subject: [PATCH 11/11] Dev version bump [skip ci] --- Directory.Version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Version.props b/Directory.Version.props index c8c7b22..1249a7d 100644 --- a/Directory.Version.props +++ b/Directory.Version.props @@ -1,6 +1,6 @@ - 9.0.0 + 9.0.1