@@ -24,6 +24,7 @@ public sealed class SerilogLoggerProvider : ILoggerProvider, ILogEventEnricher,
2424    // May be null; if it is, Log.Logger will be lazily used 
2525    readonly  ILogger ?  _logger ; 
2626    readonly  Action ?  _dispose ; 
27+     readonly  ThreadLocal < ScopeCollector >  _scopeCollector  =  new ( ( )  =>  new  ScopeCollector ( ) ) ; 
2728#if FEATURE_ASYNCDISPOSABLE 
2829    readonly  Func < ValueTask > ?  _disposeAsync ; 
2930#endif
@@ -90,35 +91,38 @@ public IDisposable BeginScope<T>(T state)
9091    /// <inheritdoc /> 
9192    public  void  Enrich ( LogEvent  logEvent ,  ILogEventPropertyFactory  propertyFactory ) 
9293    { 
93-         List < LogEventPropertyValue > ?  scopeItems  =  null ; 
94+         var  scopeCollector  =  _scopeCollector . Value ! ; 
95+ 
9496        for  ( var  scope  =  CurrentScope ;  scope  !=  null ;  scope  =  scope . Parent ) 
9597        { 
9698            scope . EnrichAndCreateScopeItem ( logEvent ,  propertyFactory ,  out  var  scopeItem ) ; 
9799
98100            if  ( scopeItem  !=  null ) 
99101            { 
100-                 scopeItems  ??=  [ ] ; 
101-                 scopeItems . Add ( scopeItem ) ; 
102+                 scopeCollector . AddItem ( scopeItem ) ; 
102103            } 
103104        } 
104105
105-         scopeItems ? . Reverse ( ) ; 
106+         scopeCollector . ReverseItems ( ) ; 
106107
107-         _externalScopeProvider ? . ForEachScope ( ( state ,  accumulatingLogEvent )  => 
108+         _externalScopeProvider ? . ForEachScope ( static   ( state ,  parameters )  => 
108109        { 
109110            SerilogLoggerScope . EnrichWithStateAndCreateScopeItem ( 
110-                 accumulatingLogEvent ,  propertyFactory ,  state ,  update :  true ,  out  var  scopeItem ) ; 
111+                 parameters . LogEvent , 
112+                 parameters . PropertyFactory , 
113+                 state , 
114+                 update :  true , 
115+                 out  var  scopeItem ) ; 
111116
112117            if  ( scopeItem  !=  null ) 
113118            { 
114-                 scopeItems  ??=  new  List < LogEventPropertyValue > ( ) ; 
115-                 scopeItems . Add ( scopeItem ) ; 
119+                 parameters . ScopeCollector . AddItem ( scopeItem ) ; 
116120            } 
117-         } ,  logEvent ) ; 
121+         } ,  ( ScopeCollector :   scopeCollector ,   PropertyFactory :   propertyFactory ,   LogEvent :   logEvent ) ) ; 
118122
119-         if  ( scopeItems   !=   null ) 
123+         if  ( scopeCollector . Complete ( )   is   {   }   items ) 
120124        { 
121-             logEvent . AddPropertyIfAbsent ( new  LogEventProperty ( ScopePropertyName ,  new  SequenceValue ( scopeItems ) ) ) ; 
125+             logEvent . AddPropertyIfAbsent ( new  LogEventProperty ( ScopePropertyName ,  new  SequenceValue ( items ) ) ) ; 
122126        } 
123127    } 
124128
@@ -149,4 +153,27 @@ public ValueTask DisposeAsync()
149153        return  _disposeAsync ? . Invoke ( )  ??  default ; 
150154    } 
151155#endif
156+ 
157+     /// <summary> 
158+     /// A wrapper around a list to allow lazy initialization when iterating through scopes. 
159+     /// </summary> 
160+     sealed  class  ScopeCollector 
161+     { 
162+         List < LogEventPropertyValue > ?  _scopeItems ; 
163+ 
164+         public  void  AddItem ( LogEventPropertyValue  scopeItem ) 
165+         { 
166+             _scopeItems  ??=  [ ] ; 
167+             _scopeItems . Add ( scopeItem ) ; 
168+         } 
169+ 
170+         public  void  ReverseItems ( )  =>  _scopeItems ? . Reverse ( ) ; 
171+ 
172+         public  List < LogEventPropertyValue > ?  Complete ( ) 
173+         { 
174+             var  scopeItems  =  _scopeItems ; 
175+             _scopeItems  =  null ; 
176+             return  scopeItems ; 
177+         } 
178+     } 
152179} 
0 commit comments