From f36cba849b85720d96e5a6fe26fe93c7f37155d5 Mon Sep 17 00:00:00 2001 From: dudu Date: Sat, 11 Feb 2023 22:34:14 +0800 Subject: [PATCH] feat: support ILoggingBuilder --- .../SerilogHostBuilderExtensions.cs | 99 +++++++++++-------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs index d588000..c9d8c97 100644 --- a/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs +++ b/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs @@ -18,6 +18,7 @@ using Microsoft.Extensions.Logging; using Serilog.Extensions.Hosting; using Serilog.Extensions.Logging; + // ReSharper disable MemberCanBePrivate.Global namespace Serilog @@ -31,13 +32,13 @@ public static class SerilogHostBuilderExtensions // 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 + private class RegisteredLogger { public RegisteredLogger(ILogger logger) { Logger = logger; } - + public ILogger Logger { get; } } @@ -54,43 +55,63 @@ public RegisteredLogger(ILogger logger) /// 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) + { + return builder.ConfigureServices((context, services) => + services.AddLogging(logging => logging.AddSerilog(logger, dispose, providers))); + } + + /// + /// Sets Serilog as the logging provider. + /// + /// The logging 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 ILoggingBuilder AddSerilog( + this ILoggingBuilder builder, + ILogger logger = null, bool dispose = false, LoggerProviderCollection providers = null) { if (builder == null) throw new ArgumentNullException(nameof(builder)); - builder.ConfigureServices((_, collection) => + var services = builder.Services; + if (providers != null) { - if (providers != null) + services.AddSingleton(services => { - collection.AddSingleton(services => - { - var factory = new SerilogLoggerFactory(logger, dispose, providers); + var factory = new SerilogLoggerFactory(logger, dispose, providers); - foreach (var provider in services.GetServices()) - factory.AddProvider(provider); + foreach (var provider in services.GetServices()) + factory.AddProvider(provider); - return factory; - }); - } - else - { - collection.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)); - } + return factory; + }); + } + else + { + services.AddSingleton(services => new SerilogLoggerFactory(logger, dispose)); + } - if (logger != null) - { - // This won't (and shouldn't) take ownership of the logger. - collection.AddSingleton(logger); + if (logger != null) + { + // This won't (and shouldn't) take ownership of the logger. + services.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); - }); + // Still need to use RegisteredLogger as it is used by ConfigureDiagnosticContext. + services.AddSingleton(new RegisteredLogger(logger)); + } + bool useRegisteredLogger = logger != null; + ConfigureDiagnosticContext(services, useRegisteredLogger); return builder; } @@ -147,7 +168,7 @@ public static IHostBuilder UseSerilog( { if (builder == null) throw new ArgumentNullException(nameof(builder)); 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; @@ -155,7 +176,7 @@ public static IHostBuilder UseSerilog( #else const bool useReload = false; #endif - + builder.ConfigureServices((context, collection) => { LoggerProviderCollection loggerProviders = null; @@ -163,7 +184,7 @@ public static IHostBuilder UseSerilog( { loggerProviders = new LoggerProviderCollection(); } - + collection.AddSingleton(services => { ILogger logger; @@ -174,11 +195,11 @@ public static IHostBuilder UseSerilog( { if (loggerProviders != null) cfg.WriteTo.Providers(loggerProviders); - + configureLogger(context, services, cfg); return cfg; }); - + logger = reloadable.Freeze(); } else @@ -203,11 +224,11 @@ public static IHostBuilder UseSerilog( var logger = services.GetRequiredService().Logger; return logger.ForContext(new NullEnricher()); }); - + collection.AddSingleton(services => { var logger = services.GetRequiredService().Logger; - + ILogger registeredLogger = null; if (preserveStaticLogger) { @@ -233,15 +254,15 @@ public static IHostBuilder UseSerilog( ConfigureDiagnosticContext(collection, preserveStaticLogger); }); - + return builder; } - static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger) + private static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRegisteredLogger) { if (collection == null) throw new ArgumentNullException(nameof(collection)); - // Registered to provide two services... + // Registered to provide two services... // Consumed by e.g. middleware collection.AddSingleton(services => { @@ -252,4 +273,4 @@ static void ConfigureDiagnosticContext(IServiceCollection collection, bool useRe collection.AddSingleton(services => services.GetRequiredService()); } } -} +} \ No newline at end of file