@@ -160,10 +160,19 @@ void ApplyMinimumLevel(LoggerConfiguration loggerConfiguration)
160
160
loggerConfiguration . MinimumLevel . ControlledBy ( globalMinimumLevelSwitch ) ;
161
161
}
162
162
163
+ // Level overrides may be set via environment variables. In that case it may be problematic to use dots in
164
+ // variable name, see https://github.com/dotnet/AspNetCore.Docs/issues/17378, so all dots should be replaces
165
+ // with double underscore. The consequence is that configuration becomes "nested" and GetSection("Override").GetChildren()
166
+ // call returns nothing since this method returns only immediate descendant configuration sub-sections.
167
+ // The workaround is to use AsEnumerable(true) method to retrieve all descendants and then manually replace : with .
168
+ var flattenDescendants = minimumLevelDirective . GetSection ( "Override" ) . AsEnumerable ( true ) . ToList ( ) ;
169
+
163
170
foreach ( var overrideDirective in minimumLevelDirective . GetSection ( "Override" ) . GetChildren ( ) )
164
171
{
165
172
var overridePrefix = overrideDirective . Key ;
166
173
var overridenLevelOrSwitch = overrideDirective . Value ;
174
+ // filter out "normal" keys
175
+ flattenDescendants . RemoveAll ( p => p . Key == overridePrefix ) ;
167
176
if ( Enum . TryParse ( overridenLevelOrSwitch , out LogEventLevel _ ) )
168
177
{
169
178
ApplyMinimumLevelConfiguration ( overrideDirective , ( configuration , levelSwitch ) =>
@@ -180,6 +189,29 @@ void ApplyMinimumLevel(LoggerConfiguration loggerConfiguration)
180
189
}
181
190
}
182
191
192
+ // Process remaining configuration values if any. Note that this code path does not call
193
+ // SubscribeToLoggingLevelChanges as ApplyMinimumLevelConfiguration does above. This can
194
+ // be improved some time later.
195
+ foreach ( var pair in flattenDescendants )
196
+ {
197
+ var overridePrefix = pair . Key . Replace ( ':' , '.' ) ;
198
+ var overridenLevelOrSwitch = pair . Value ;
199
+ if ( Enum . TryParse ( overridenLevelOrSwitch , out LogEventLevel _ ) )
200
+ {
201
+ var minimumLevel = ParseLogEventLevel ( overridenLevelOrSwitch ! ) ;
202
+
203
+ var levelSwitch = new LoggingLevelSwitch ( minimumLevel ) ;
204
+ loggerConfiguration . MinimumLevel . Override ( overridePrefix , levelSwitch ) ;
205
+ _resolutionContext . ReaderOptions . OnLevelSwitchCreated ? . Invoke ( overridePrefix , levelSwitch ) ;
206
+ }
207
+ else if ( ! string . IsNullOrEmpty ( overridenLevelOrSwitch ) )
208
+ {
209
+ var overrideSwitch = _resolutionContext . LookUpLevelSwitchByName ( overridenLevelOrSwitch ! ) ;
210
+ // not calling ApplyMinimumLevel local function because here we have a reference to a LogLevelSwitch already
211
+ loggerConfiguration . MinimumLevel . Override ( overridePrefix , overrideSwitch ) ;
212
+ }
213
+ }
214
+
183
215
void ApplyMinimumLevelConfiguration ( IConfigurationSection directive , Action < LoggerMinimumLevelConfiguration , LoggingLevelSwitch > applyConfigAction )
184
216
{
185
217
var minimumLevel = ParseLogEventLevel ( directive . Value ! ) ;
0 commit comments