@@ -44,7 +44,7 @@ public static bool TryGetStatus(this Activity activity, out StatusCode statusCod
4444
4545 ActivityStatusTagEnumerator state = default ;
4646
47- ActivityTagsEnumeratorFactory < ActivityStatusTagEnumerator > . Enumerate ( activity , ref state ) ;
47+ ActivityTagsEnumeratorFactory < ActivityStatusTagEnumerator > . Enumerate ( activity , ref state , null ) ;
4848
4949 if ( ! state . StatusCode . HasValue )
5050 {
@@ -72,7 +72,7 @@ public static object GetTagValue(this Activity activity, string tagName)
7272
7373 ActivitySingleTagEnumerator state = new ActivitySingleTagEnumerator ( tagName ) ;
7474
75- ActivityTagsEnumeratorFactory < ActivitySingleTagEnumerator > . Enumerate ( activity , ref state ) ;
75+ ActivityTagsEnumeratorFactory < ActivitySingleTagEnumerator > . Enumerate ( activity , ref state , null ) ;
7676
7777 return state . Value ;
7878 }
@@ -91,7 +91,7 @@ public static bool TryCheckFirstTag(this Activity activity, string tagName, out
9191
9292 ActivityFirstTagEnumerator state = new ActivityFirstTagEnumerator ( tagName ) ;
9393
94- ActivityTagsEnumeratorFactory < ActivityFirstTagEnumerator > . Enumerate ( activity , ref state ) ;
94+ ActivityTagsEnumeratorFactory < ActivityFirstTagEnumerator > . Enumerate ( activity , ref state , null ) ;
9595
9696 if ( state . Value == null )
9797 {
@@ -109,14 +109,15 @@ public static bool TryCheckFirstTag(this Activity activity, string tagName, out
109109 /// <typeparam name="T">The struct <see cref="IActivityEnumerator{T}"/> implementation to use for the enumeration.</typeparam>
110110 /// <param name="activity">Activity instance.</param>
111111 /// <param name="tagEnumerator">Tag enumerator.</param>
112+ /// <param name="maxTags">Maximum number of tags to enumerate.</param>
112113 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
113114 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Design" , "CA1062:Validate arguments of public methods" , Justification = "ActivityProcessor is hot path" ) ]
114- public static void EnumerateTags < T > ( this Activity activity , ref T tagEnumerator )
115+ public static void EnumerateTags < T > ( this Activity activity , ref T tagEnumerator , int ? maxTags = null )
115116 where T : struct , IActivityEnumerator < KeyValuePair < string , object > >
116117 {
117118 Debug . Assert ( activity != null , "Activity should not be null" ) ;
118119
119- ActivityTagsEnumeratorFactory < T > . Enumerate ( activity , ref tagEnumerator ) ;
120+ ActivityTagsEnumeratorFactory < T > . Enumerate ( activity , ref tagEnumerator , maxTags ) ;
120121 }
121122
122123 /// <summary>
@@ -125,14 +126,15 @@ public static void EnumerateTags<T>(this Activity activity, ref T tagEnumerator)
125126 /// <typeparam name="T">The struct <see cref="IActivityEnumerator{T}"/> implementation to use for the enumeration.</typeparam>
126127 /// <param name="activity">Activity instance.</param>
127128 /// <param name="linkEnumerator">Link enumerator.</param>
129+ /// <param name="maxLinks">Maximum number of links to enumerate.</param>
128130 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
129131 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Design" , "CA1062:Validate arguments of public methods" , Justification = "ActivityProcessor is hot path" ) ]
130- public static void EnumerateLinks < T > ( this Activity activity , ref T linkEnumerator )
132+ public static void EnumerateLinks < T > ( this Activity activity , ref T linkEnumerator , int ? maxLinks = null )
131133 where T : struct , IActivityEnumerator < ActivityLink >
132134 {
133135 Debug . Assert ( activity != null , "Activity should not be null" ) ;
134136
135- ActivityLinksEnumeratorFactory < T > . Enumerate ( activity , ref linkEnumerator ) ;
137+ ActivityLinksEnumeratorFactory < T > . Enumerate ( activity , ref linkEnumerator , maxLinks ) ;
136138 }
137139
138140 /// <summary>
@@ -141,12 +143,13 @@ public static void EnumerateLinks<T>(this Activity activity, ref T linkEnumerato
141143 /// <typeparam name="T">The struct <see cref="IActivityEnumerator{T}"/> implementation to use for the enumeration.</typeparam>
142144 /// <param name="activityLink">ActivityLink instance.</param>
143145 /// <param name="tagEnumerator">Tag enumerator.</param>
146+ /// <param name="maxTags">Maximum number of tags to enumerate.</param>
144147 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
145148 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Design" , "CA1062:Validate arguments of public methods" , Justification = "ActivityProcessor is hot path" ) ]
146- public static void EnumerateTags < T > ( this ActivityLink activityLink , ref T tagEnumerator )
149+ public static void EnumerateTags < T > ( this ActivityLink activityLink , ref T tagEnumerator , int ? maxTags = null )
147150 where T : struct , IActivityEnumerator < KeyValuePair < string , object > >
148151 {
149- ActivityTagsEnumeratorFactory < T > . Enumerate ( activityLink , ref tagEnumerator ) ;
152+ ActivityTagsEnumeratorFactory < T > . Enumerate ( activityLink , ref tagEnumerator , maxTags ) ;
150153 }
151154
152155 /// <summary>
@@ -155,14 +158,15 @@ public static void EnumerateTags<T>(this ActivityLink activityLink, ref T tagEnu
155158 /// <typeparam name="T">The struct <see cref="IActivityEnumerator{T}"/> implementation to use for the enumeration.</typeparam>
156159 /// <param name="activity">Activity instance.</param>
157160 /// <param name="eventEnumerator">Event enumerator.</param>
161+ /// <param name="maxEvents">Maximum number of events to enumerate.</param>
158162 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
159163 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Design" , "CA1062:Validate arguments of public methods" , Justification = "ActivityProcessor is hot path" ) ]
160- public static void EnumerateEvents < T > ( this Activity activity , ref T eventEnumerator )
164+ public static void EnumerateEvents < T > ( this Activity activity , ref T eventEnumerator , int ? maxEvents = null )
161165 where T : struct , IActivityEnumerator < ActivityEvent >
162166 {
163167 Debug . Assert ( activity != null , "Activity should not be null" ) ;
164168
165- ActivityEventsEnumeratorFactory < T > . Enumerate ( activity , ref eventEnumerator ) ;
169+ ActivityEventsEnumeratorFactory < T > . Enumerate ( activity , ref eventEnumerator , maxEvents ) ;
166170 }
167171
168172 /// <summary>
@@ -171,12 +175,13 @@ public static void EnumerateEvents<T>(this Activity activity, ref T eventEnumera
171175 /// <typeparam name="T">The struct <see cref="IActivityEnumerator{T}"/> implementation to use for the enumeration.</typeparam>
172176 /// <param name="activityEvent">ActivityEvent instance.</param>
173177 /// <param name="tagEnumerator">Tag enumerator.</param>
178+ /// <param name="maxTags">Maximum number of tags to enumerate.</param>
174179 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
175180 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Design" , "CA1062:Validate arguments of public methods" , Justification = "ActivityProcessor is hot path" ) ]
176- public static void EnumerateTags < T > ( this ActivityEvent activityEvent , ref T tagEnumerator )
181+ public static void EnumerateTags < T > ( this ActivityEvent activityEvent , ref T tagEnumerator , int ? maxTags = null )
177182 where T : struct , IActivityEnumerator < KeyValuePair < string , object > >
178183 {
179- ActivityTagsEnumeratorFactory < T > . Enumerate ( activityEvent , ref tagEnumerator ) ;
184+ ActivityTagsEnumeratorFactory < T > . Enumerate ( activityEvent , ref tagEnumerator , maxTags ) ;
180185 }
181186
182187 private struct ActivitySingleTagEnumerator : IActivityEnumerator < KeyValuePair < string , object > >
@@ -265,7 +270,7 @@ private static readonly DictionaryEnumerator<string, object, TState>.AllocationF
265270 private static readonly DictionaryEnumerator < string , object , TState > . ForEachDelegate ForEachTagValueCallbackRef = ForEachTagValueCallback ;
266271
267272 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
268- public static void Enumerate ( Activity activity , ref TState state )
273+ public static void Enumerate ( Activity activity , ref TState state , int ? maxTags )
269274 {
270275 var tagObjects = activity . TagObjects ;
271276
@@ -274,14 +279,20 @@ public static void Enumerate(Activity activity, ref TState state)
274279 return ;
275280 }
276281
282+ if ( maxTags . HasValue )
283+ {
284+ SkipAllocationFreeEnumeration ( tagObjects , ref state , maxTags . Value ) ;
285+ return ;
286+ }
287+
277288 ActivityTagObjectsEnumerator (
278289 tagObjects ,
279290 ref state ,
280291 ForEachTagValueCallbackRef ) ;
281292 }
282293
283294 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
284- public static void Enumerate ( ActivityLink activityLink , ref TState state )
295+ public static void Enumerate ( ActivityLink activityLink , ref TState state , int ? maxTags )
285296 {
286297 var tags = activityLink . Tags ;
287298
@@ -290,14 +301,20 @@ public static void Enumerate(ActivityLink activityLink, ref TState state)
290301 return ;
291302 }
292303
304+ if ( maxTags . HasValue )
305+ {
306+ SkipAllocationFreeEnumeration ( tags , ref state , maxTags . Value ) ;
307+ return ;
308+ }
309+
293310 ActivityTagsCollectionEnumerator (
294311 tags ,
295312 ref state ,
296313 ForEachTagValueCallbackRef ) ;
297314 }
298315
299316 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
300- public static void Enumerate ( ActivityEvent activityEvent , ref TState state )
317+ public static void Enumerate ( ActivityEvent activityEvent , ref TState state , int ? maxTags )
301318 {
302319 var tags = activityEvent . Tags ;
303320
@@ -306,12 +323,31 @@ public static void Enumerate(ActivityEvent activityEvent, ref TState state)
306323 return ;
307324 }
308325
326+ if ( maxTags . HasValue )
327+ {
328+ SkipAllocationFreeEnumeration ( tags , ref state , maxTags . Value ) ;
329+ return ;
330+ }
331+
309332 ActivityTagsCollectionEnumerator (
310333 tags ,
311334 ref state ,
312335 ForEachTagValueCallbackRef ) ;
313336 }
314337
338+ // TODO: When a limit has been configured an allocation-free enumerator is not used.
339+ // Need to either:
340+ // 1) modify the dynamically generated code to only enumerate up to the max number of items, or
341+ // 2) wait until .NET 7 is released and do this more easily with the new enumerator functions
342+ private static void SkipAllocationFreeEnumeration ( IEnumerable < KeyValuePair < string , object > > tags , ref TState state , int maxTags )
343+ {
344+ var enumerator = tags . GetEnumerator ( ) ;
345+ for ( var i = 0 ; enumerator . MoveNext ( ) && i < maxTags ; ++ i )
346+ {
347+ state . ForEach ( enumerator . Current ) ;
348+ }
349+ }
350+
315351 private static bool ForEachTagValueCallback ( ref TState state , KeyValuePair < string , object > item )
316352 => state . ForEach ( item ) ;
317353 }
@@ -328,7 +364,7 @@ private static readonly ListEnumerator<ActivityLink, TState>.AllocationFreeForEa
328364 private static readonly ListEnumerator < ActivityLink , TState > . ForEachDelegate ForEachLinkCallbackRef = ForEachLinkCallback ;
329365
330366 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
331- public static void Enumerate ( Activity activity , ref TState state )
367+ public static void Enumerate ( Activity activity , ref TState state , int ? maxLinks )
332368 {
333369 var activityLinks = activity . Links ;
334370
@@ -337,6 +373,21 @@ public static void Enumerate(Activity activity, ref TState state)
337373 return ;
338374 }
339375
376+ // TODO: When a limit has been configured an allocation-free enumerator is not used.
377+ // Need to either:
378+ // 1) modify the dynamically generated code to only enumerate up to the max number of items, or
379+ // 2) wait until .NET 7 is released and do this more easily with the new enumerator functions
380+ if ( maxLinks . HasValue )
381+ {
382+ var enumerator = activityLinks . GetEnumerator ( ) ;
383+ for ( var i = 0 ; enumerator . MoveNext ( ) && i < maxLinks ; ++ i )
384+ {
385+ state . ForEach ( enumerator . Current ) ;
386+ }
387+
388+ return ;
389+ }
390+
340391 ActivityLinksEnumerator (
341392 activityLinks ,
342393 ref state ,
@@ -359,7 +410,7 @@ private static readonly ListEnumerator<ActivityEvent, TState>.AllocationFreeForE
359410 private static readonly ListEnumerator < ActivityEvent , TState > . ForEachDelegate ForEachEventCallbackRef = ForEachEventCallback ;
360411
361412 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
362- public static void Enumerate ( Activity activity , ref TState state )
413+ public static void Enumerate ( Activity activity , ref TState state , int ? maxEvents )
363414 {
364415 var activityEvents = activity . Events ;
365416
@@ -368,6 +419,21 @@ public static void Enumerate(Activity activity, ref TState state)
368419 return ;
369420 }
370421
422+ // TODO: When a limit has been configured an allocation-free enumerator is not used.
423+ // Need to either:
424+ // 1) modify the dynamically generated code to only enumerate up to the max number of items, or
425+ // 2) wait until .NET 7 is released and do this more easily with the new enumerator functions
426+ if ( maxEvents . HasValue )
427+ {
428+ var enumerator = activityEvents . GetEnumerator ( ) ;
429+ for ( var i = 0 ; enumerator . MoveNext ( ) && i < maxEvents ; ++ i )
430+ {
431+ state . ForEach ( enumerator . Current ) ;
432+ }
433+
434+ return ;
435+ }
436+
371437 ActivityEventsEnumerator (
372438 activityEvents ,
373439 ref state ,
0 commit comments