@@ -18,8 +18,9 @@ public class LoggerFactory : ILoggerFactory
1818 private KeyValuePair < ILoggerProvider , string > [ ] _providers = new KeyValuePair < ILoggerProvider , string > [ 0 ] ;
1919 private readonly object _sync = new object ( ) ;
2020 private volatile bool _disposed ;
21- private readonly IConfiguration _configuration ;
21+ private IConfiguration _configuration ;
2222 private IChangeToken _changeToken ;
23+ private IDisposable _changeTokenRegistration ;
2324 private Dictionary < string , LogLevel > _defaultFilter ;
2425 private Func < string , string , LogLevel , bool > _genericFilters ;
2526 private Dictionary < string , Func < string , LogLevel , bool > > _providerFilters = new Dictionary < string , Func < string , LogLevel , bool > > ( ) ;
@@ -41,11 +42,40 @@ public LoggerFactory(IConfiguration configuration)
4142 throw new ArgumentNullException ( nameof ( configuration ) ) ;
4243 }
4344
45+ UseConfiguration ( configuration ) ;
46+ }
47+
48+ /// <summary>
49+ /// Replaces the <see cref="IConfiguration"/> used for filtering.
50+ /// </summary>
51+ /// <param name="configuration">The new configuration to use.</param>
52+ /// <returns>The <see cref="LoggerFactory"/> so that additional calls can be chained.</returns>
53+ public LoggerFactory UseConfiguration ( IConfiguration configuration )
54+ {
55+ if ( configuration == _configuration )
56+ {
57+ return this ;
58+ }
59+
60+ // unregister the previous configuration callback if there was one
61+ _changeTokenRegistration ? . Dispose ( ) ;
62+
4463 _configuration = configuration ;
45- _changeToken = configuration . GetReloadToken ( ) ;
46- _changeToken . RegisterChangeCallback ( OnConfigurationReload , null ) ;
64+
65+ if ( configuration == null )
66+ {
67+ _changeToken = null ;
68+ _changeTokenRegistration = null ;
69+ }
70+ else
71+ {
72+ _changeToken = _configuration . GetReloadToken ( ) ;
73+ _changeTokenRegistration = _changeToken ? . RegisterChangeCallback ( OnConfigurationReload , null ) ;
74+ }
4775
4876 LoadDefaultConfigValues ( ) ;
77+
78+ return this ;
4979 }
5080
5181 public ILogger CreateLogger ( string categoryName )
@@ -132,8 +162,22 @@ public void AddProvider(string providerName, ILoggerProvider provider)
132162 }
133163 }
134164
135- public void AddFilter ( string providerName , string categoryName , Func < LogLevel , bool > filter )
165+ /// <summary>
166+ /// Adds a filter that applies to <paramref name="providerName"/> and <paramref name="categoryName"/> with the given
167+ /// <paramref name="filter"/>.
168+ /// </summary>
169+ /// <param name="providerName">The name of the provider.</param>
170+ /// <param name="categoryName">The name of the logger category.</param>
171+ /// <param name="filter">The filter that applies to logs for <paramref name="providerName"/> and <paramref name="categoryName"/>.
172+ /// Returning true means allow log through, false means reject log.</param>
173+ /// <returns>The <see cref="LoggerFactory"/> so that additional calls can be chained.</returns>
174+ public LoggerFactory AddFilter ( string providerName , string categoryName , Func < LogLevel , bool > filter )
136175 {
176+ if ( filter == null )
177+ {
178+ throw new ArgumentNullException ( nameof ( filter ) ) ;
179+ }
180+
137181 lock ( _sync )
138182 {
139183 if ( _categoryFilters . TryGetValue ( categoryName , out var previousFilter ) )
@@ -166,46 +210,25 @@ public void AddFilter(string providerName, string categoryName, Func<LogLevel, b
166210 } ;
167211 }
168212 }
213+
214+ return this ;
169215 }
170216
171- public void AddFilter ( string providerName , string categoryName , LogLevel minLevel )
217+ /// <summary>
218+ /// Adds a filter that applies to <paramref name="providerName"/> with the given <paramref name="filter"/>.
219+ /// </summary>
220+ /// <param name="providerName">The name of the provider.</param>
221+ /// <param name="filter">The filter that applies to logs for <paramref name="providerName"/>.
222+ /// The string argument is the category being logged to.
223+ /// Returning true means allow log through, false means reject log.</param>
224+ /// <returns>The <see cref="LoggerFactory"/> so that additional calls can be chained.</returns>
225+ public LoggerFactory AddFilter ( string providerName , Func < string , LogLevel , bool > filter )
172226 {
173- lock ( _sync )
227+ if ( filter == null )
174228 {
175- if ( _categoryFilters . TryGetValue ( categoryName , out var previousFilter ) )
176- {
177- _categoryFilters [ categoryName ] = ( currentProviderName , level ) =>
178- {
179- if ( previousFilter ( currentProviderName , level ) )
180- {
181- if ( string . Equals ( providerName , currentProviderName ) )
182- {
183- return level >= minLevel ;
184- }
185-
186- return true ;
187- }
188-
189- return false ;
190- } ;
191- }
192- else
193- {
194- _categoryFilters [ categoryName ] = ( currentProviderName , level ) =>
195- {
196- if ( string . Equals ( providerName , currentProviderName ) )
197- {
198- return level >= minLevel ;
199- }
200-
201- return true ;
202- } ;
203- }
229+ throw new ArgumentNullException ( nameof ( filter ) ) ;
204230 }
205- }
206231
207- public void AddFilter ( string providerName , Func < string , LogLevel , bool > filter )
208- {
209232 lock ( _sync )
210233 {
211234 if ( _providerFilters . TryGetValue ( providerName , out var value ) )
@@ -225,46 +248,24 @@ public void AddFilter(string providerName, Func<string, LogLevel, bool> filter)
225248 _providerFilters [ providerName ] = ( category , level ) => filter ( category , level ) ;
226249 }
227250 }
251+
252+ return this ;
228253 }
229254
230- public void AddFilter ( string providerName , Func < LogLevel , bool > filter )
255+ /// <summary>
256+ /// Adds a filter that applies to all logs.
257+ /// </summary>
258+ /// <param name="filter">The filter that applies to logs.
259+ /// The first string is the provider name and the second string is the category name being logged to.
260+ /// Returning true means allow log through, false means reject log.</param>
261+ /// <returns>The <see cref="LoggerFactory"/> so that additional calls can be chained.</returns>
262+ public LoggerFactory AddFilter ( Func < string , string , LogLevel , bool > filter )
231263 {
232- lock ( _sync )
264+ if ( filter == null )
233265 {
234- if ( _categoryFilters . TryGetValue ( "Default" , out var value ) )
235- {
236- _categoryFilters [ "Default" ] = ( currentProviderName , level ) =>
237- {
238- if ( value ( currentProviderName , level ) )
239- {
240- if ( string . Equals ( providerName , currentProviderName ) )
241- {
242- return filter ( level ) ;
243- }
244-
245- return true ;
246- }
247-
248- return false ;
249- } ;
250- }
251- else
252- {
253- _categoryFilters [ "Default" ] = ( currentProviderName , level ) =>
254- {
255- if ( string . Equals ( providerName , currentProviderName ) )
256- {
257- return filter ( level ) ;
258- }
259-
260- return true ;
261- } ;
262- }
266+ throw new ArgumentNullException ( nameof ( filter ) ) ;
263267 }
264- }
265268
266- public void AddFilter ( Func < string , string , LogLevel , bool > filter )
267- {
268269 lock ( _sync )
269270 {
270271 var previousFilters = _genericFilters ;
@@ -278,10 +279,23 @@ public void AddFilter(Func<string, string, LogLevel, bool> filter)
278279 return false ;
279280 } ;
280281 }
282+
283+ return this ;
281284 }
282285
283- public void AddFilter ( IDictionary < string , LogLevel > filter )
286+ /// <summary>
287+ /// Adds a filter to all logs.
288+ /// </summary>
289+ /// <param name="filter">The filter that applies to logs.
290+ /// The key is the category and the <see cref="LogLevel"/> is the minimum level allowed.</param>
291+ /// <returns>The <see cref="LoggerFactory"/> so that additional calls can be chained.</returns>
292+ public LoggerFactory AddFilter ( IDictionary < string , LogLevel > filter )
284293 {
294+ if ( filter == null )
295+ {
296+ throw new ArgumentNullException ( nameof ( filter ) ) ;
297+ }
298+
285299 lock ( _sync )
286300 {
287301 foreach ( var kvp in filter )
@@ -304,84 +318,39 @@ public void AddFilter(IDictionary<string, LogLevel> filter)
304318 }
305319 }
306320 }
321+
322+ return this ;
307323 }
308324
309- public void AddFilter ( string providerName , IDictionary < string , LogLevel > filter )
325+ /// <summary>
326+ /// Adds a filter that applies to <paramref name="providerName"/> and <paramref name="categoryName"/>, allowing logs with the given
327+ /// minimum <see cref="LogLevel"/> or higher.
328+ /// </summary>
329+ /// <param name="providerName">The name of the provider.</param>
330+ /// <param name="categoryName">The name of the logger category.</param>
331+ /// <param name="minLevel">The minimum <see cref="LogLevel"/> that logs from
332+ /// <paramref name="providerName"/> and <paramref name="categoryName"/> are allowed.</param>
333+ public LoggerFactory AddFilter ( string providerName , string categoryName , LogLevel minLevel )
310334 {
311- lock ( _sync )
312- {
313- foreach ( var kvp in filter )
314- {
315- if ( _categoryFilters . TryGetValue ( kvp . Key , out var currentFilter ) )
316- {
317- _categoryFilters [ kvp . Key ] = ( currentProviderName , level ) =>
318- {
319- if ( currentFilter ( currentProviderName , level ) )
320- {
321- if ( string . Equals ( providerName , currentProviderName ) )
322- {
323- return level >= kvp . Value ;
324- }
325-
326- return true ;
327- }
328-
329- return false ;
330- } ;
331- }
332- else
333- {
334- _categoryFilters [ kvp . Key ] = ( currentProviderName , level ) =>
335- {
336- if ( string . Equals ( providerName , currentProviderName ) )
337- {
338- return level >= kvp . Value ;
339- }
340-
341- return true ;
342- } ;
343- }
344- }
345- }
335+ return AddFilter ( providerName , categoryName , level => level >= minLevel ) ;
346336 }
347337
348- public void AddFilter ( Func < string , bool > providerNames , IDictionary < string , LogLevel > filter )
338+ /// <summary>
339+ /// Adds a filter that applies to <paramref name="providerName"/> with the given
340+ /// <paramref name="filter"/>.
341+ /// </summary>
342+ /// <param name="providerName">The name of the provider.</param>
343+ /// <param name="filter">The filter that applies to logs for <paramref name="providerName"/>.
344+ /// Returning true means allow log through, false means reject log.</param>
345+ public LoggerFactory AddFilter ( string providerName , Func < LogLevel , bool > filter )
349346 {
350- lock ( _sync )
347+ if ( filter == null )
351348 {
352- foreach ( var kvp in filter )
353- {
354- if ( _categoryFilters . TryGetValue ( kvp . Key , out var currentFilter ) )
355- {
356- _categoryFilters [ kvp . Key ] = ( providerName , level ) =>
357- {
358- if ( providerNames ( providerName ) )
359- {
360- if ( currentFilter ( providerName , level ) )
361- {
362- return level >= kvp . Value ;
363- }
364-
365- return false ;
366- }
367-
368- return true ;
369- } ;
370- }
371- else
372- {
373- _categoryFilters [ kvp . Key ] = ( providerName , level ) =>
374- {
375- if ( providerNames ( providerName ) )
376- {
377- return level >= kvp . Value ;
378- }
379-
380- return true ;
381- } ;
382- }
383- }
349+ throw new ArgumentNullException ( nameof ( filter ) ) ;
384350 }
351+
352+ // Using 'Default' for the category name means this filter will apply for all category names
353+ return AddFilter ( providerName , "Default" , filter ) ;
385354 }
386355
387356 // TODO: Figure out how to do this better, perhaps a new IConfigurableLogger interface?
@@ -479,7 +448,7 @@ private void OnConfigurationReload(object state)
479448 finally
480449 {
481450 // The token will change each time it reloads, so we need to register again.
482- _changeToken . RegisterChangeCallback ( OnConfigurationReload , null ) ;
451+ _changeTokenRegistration = _changeToken . RegisterChangeCallback ( OnConfigurationReload , null ) ;
483452 }
484453 }
485454
@@ -519,6 +488,12 @@ private static IEnumerable<string> GetKeyPrefixes(string name)
519488 private void LoadDefaultConfigValues ( )
520489 {
521490 var replacementDefaultFilters = new Dictionary < string , LogLevel > ( ) ;
491+ if ( _configuration == null )
492+ {
493+ _defaultFilter = replacementDefaultFilters ;
494+ return ;
495+ }
496+
522497 var logLevelSection = _configuration . GetSection ( "LogLevel" ) ;
523498
524499 if ( logLevelSection != null )
@@ -547,6 +522,8 @@ public void Dispose()
547522 {
548523 _disposed = true ;
549524
525+ _changeTokenRegistration ? . Dispose ( ) ;
526+
550527 foreach ( var provider in _providers )
551528 {
552529 try
0 commit comments