1515using System ;
1616using Microsoft . AspNetCore . Hosting ;
1717using Microsoft . Extensions . Logging ;
18- using Serilog . AspNetCore ;
18+ using Serilog . Extensions . Logging ;
1919using Microsoft . Extensions . DependencyInjection ;
2020
2121namespace Serilog
@@ -33,12 +33,38 @@ public static class SerilogWebHostBuilderExtensions
3333 /// <param name="dispose">When true, dispose <paramref name="logger"/> when the framework disposes the provider. If the
3434 /// logger is not specified but <paramref name="dispose"/> is true, the <see cref="Log.CloseAndFlush()"/> method will be
3535 /// called on the static <see cref="Log"/> class instead.</param>
36+ /// <param name="providers">A <see cref="LoggerProviderCollection"/> registered in the Serilog pipeline using the
37+ /// <c>WriteTo.Providers()</c> configuration method, enabling other <see cref="ILoggerProvider"/>s to receive events. By
38+ /// default, only Serilog sinks will receive events.</param>
3639 /// <returns>The web host builder.</returns>
37- public static IWebHostBuilder UseSerilog ( this IWebHostBuilder builder , Serilog . ILogger logger = null , bool dispose = false )
40+ public static IWebHostBuilder UseSerilog (
41+ this IWebHostBuilder builder ,
42+ ILogger logger = null ,
43+ bool dispose = false ,
44+ LoggerProviderCollection providers = null )
3845 {
3946 if ( builder == null ) throw new ArgumentNullException ( nameof ( builder ) ) ;
47+
4048 builder . ConfigureServices ( collection =>
41- collection . AddSingleton < ILoggerFactory > ( services => new SerilogLoggerFactory ( logger , dispose ) ) ) ;
49+ {
50+ if ( providers != null )
51+ {
52+ collection . AddSingleton < ILoggerFactory > ( services =>
53+ {
54+ var factory = new SerilogLoggerFactory ( logger , dispose , providers ) ;
55+
56+ foreach ( var provider in services . GetServices < ILoggerProvider > ( ) )
57+ factory . AddProvider ( provider ) ;
58+
59+ return factory ;
60+ } ) ;
61+ }
62+ else
63+ {
64+ collection . AddSingleton < ILoggerFactory > ( services => new SerilogLoggerFactory ( logger , dispose ) ) ;
65+ }
66+ } ) ;
67+
4268 return builder ;
4369 }
4470
@@ -50,27 +76,56 @@ public static IWebHostBuilder UseSerilog(this IWebHostBuilder builder, Serilog.I
5076 /// <param name="builder">The web host builder to configure.</param>
5177 /// <param name="configureLogger">The delegate for configuring the <see cref="LoggerConfiguration" /> that will be used to construct a <see cref="Logger" />.</param>
5278 /// <param name="preserveStaticLogger">Indicates whether to preserve the value of <see cref="Log.Logger"/>.</param>
79+ /// <param name="writeToProviders">By default, Serilog does not write events to <see cref="ILoggerProvider"/>s registered through
80+ /// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
81+ /// <c>true</c> to write events to all providers.</param>
5382 /// <returns>The web host builder.</returns>
54- public static IWebHostBuilder UseSerilog ( this IWebHostBuilder builder , Action < WebHostBuilderContext , LoggerConfiguration > configureLogger , bool preserveStaticLogger = false )
83+ public static IWebHostBuilder UseSerilog (
84+ this IWebHostBuilder builder ,
85+ Action < WebHostBuilderContext , LoggerConfiguration > configureLogger ,
86+ bool preserveStaticLogger = false ,
87+ bool writeToProviders = false )
5588 {
5689 if ( builder == null ) throw new ArgumentNullException ( nameof ( builder ) ) ;
5790 if ( configureLogger == null ) throw new ArgumentNullException ( nameof ( configureLogger ) ) ;
5891 builder . ConfigureServices ( ( context , collection ) =>
5992 {
6093 var loggerConfiguration = new LoggerConfiguration ( ) ;
94+
95+ LoggerProviderCollection loggerProviders = null ;
96+ if ( writeToProviders )
97+ {
98+ loggerProviders = new LoggerProviderCollection ( ) ;
99+ loggerConfiguration . WriteTo . Providers ( loggerProviders ) ;
100+ }
101+
61102 configureLogger ( context , loggerConfiguration ) ;
62103 var logger = loggerConfiguration . CreateLogger ( ) ;
104+
105+ ILogger registeredLogger = null ;
63106 if ( preserveStaticLogger )
64- {
65- collection . AddSingleton < ILoggerFactory > ( services => new SerilogLoggerFactory ( logger , true ) ) ;
66- }
67- else
68107 {
69108 // Passing a `null` logger to `SerilogLoggerFactory` results in disposal via
70109 // `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op.
71110 Log . Logger = logger ;
72- collection . AddSingleton < ILoggerFactory > ( services => new SerilogLoggerFactory ( null , true ) ) ;
73111 }
112+ else
113+ {
114+ registeredLogger = logger ;
115+ }
116+
117+ collection . AddSingleton < ILoggerFactory > ( services =>
118+ {
119+ var factory = new SerilogLoggerFactory ( registeredLogger , true , loggerProviders ) ;
120+
121+ if ( writeToProviders )
122+ {
123+ foreach ( var provider in services . GetServices < ILoggerProvider > ( ) )
124+ factory . AddProvider ( provider ) ;
125+ }
126+
127+ return factory ;
128+ } ) ;
74129 } ) ;
75130 return builder ;
76131 }
0 commit comments