1414// limitations under the License.
1515// </copyright>
1616
17+ #nullable enable
18+
1719using System . Collections . Concurrent ;
20+ using System . Diagnostics ;
1821using System . Runtime . CompilerServices ;
1922using OpenTelemetry . Internal ;
2023
@@ -23,11 +26,12 @@ namespace OpenTelemetry.Metrics;
2326internal sealed class AggregatorStore
2427{
2528 private static readonly string MetricPointCapHitFixMessage = "Consider opting in for the experimental SDK feature to emit all the throttled metrics under the overflow attribute by setting env variable OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE = true. You could also modify instrumentation to reduce the number of unique key/value pair combinations. Or use Views to drop unwanted tags. Or use MeterProviderBuilder.SetMaxMetricPointsPerMetricStream to set higher limit." ;
26- private static readonly Comparison < KeyValuePair < string , object > > DimensionComparisonDelegate = ( x , y ) => x . Key . CompareTo ( y . Key ) ;
29+ private static readonly Comparison < KeyValuePair < string , object ? > > DimensionComparisonDelegate = ( x , y ) => x . Key . CompareTo ( y . Key ) ;
30+ private static readonly ExemplarFilter DefaultExemplarFilter = new AlwaysOffExemplarFilter ( ) ;
2731
2832 private readonly object lockZeroTags = new ( ) ;
2933 private readonly object lockOverflowTag = new ( ) ;
30- private readonly HashSet < string > tagKeysInteresting ;
34+ private readonly HashSet < string > ? tagKeysInteresting ;
3135 private readonly int tagsKeysInterestingCount ;
3236
3337 private readonly ConcurrentDictionary < Tags , int > tagsToMetricPointIndexDictionary =
@@ -60,7 +64,7 @@ internal AggregatorStore(
6064 AggregationTemporality temporality ,
6165 int maxMetricPoints ,
6266 bool emitOverflowAttribute ,
63- ExemplarFilter exemplarFilter = null )
67+ ExemplarFilter ? exemplarFilter = null )
6468 {
6569 this . name = metricStreamIdentity . InstrumentName ;
6670 this . maxMetricPoints = maxMetricPoints ;
@@ -73,7 +77,7 @@ internal AggregatorStore(
7377 this . exponentialHistogramMaxSize = metricStreamIdentity . ExponentialHistogramMaxSize ;
7478 this . exponentialHistogramMaxScale = metricStreamIdentity . ExponentialHistogramMaxScale ;
7579 this . StartTimeExclusive = DateTimeOffset . UtcNow ;
76- this . exemplarFilter = exemplarFilter ?? new AlwaysOffExemplarFilter ( ) ;
80+ this . exemplarFilter = exemplarFilter ?? DefaultExemplarFilter ;
7781 if ( metricStreamIdentity . TagKeys == null )
7882 {
7983 this . updateLongCallback = this . UpdateLong ;
@@ -98,9 +102,9 @@ internal AggregatorStore(
98102 }
99103 }
100104
101- private delegate void UpdateLongDelegate ( long value , ReadOnlySpan < KeyValuePair < string , object > > tags ) ;
105+ private delegate void UpdateLongDelegate ( long value , ReadOnlySpan < KeyValuePair < string , object ? > > tags ) ;
102106
103- private delegate void UpdateDoubleDelegate ( double value , ReadOnlySpan < KeyValuePair < string , object > > tags ) ;
107+ private delegate void UpdateDoubleDelegate ( double value , ReadOnlySpan < KeyValuePair < string , object ? > > tags ) ;
104108
105109 internal DateTimeOffset StartTimeExclusive { get ; private set ; }
106110
@@ -115,12 +119,12 @@ internal bool IsExemplarEnabled()
115119 return this . exemplarFilter is not AlwaysOffExemplarFilter ;
116120 }
117121
118- internal void Update ( long value , ReadOnlySpan < KeyValuePair < string , object > > tags )
122+ internal void Update ( long value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
119123 {
120124 this . updateLongCallback ( value , tags ) ;
121125 }
122126
123- internal void Update ( double value , ReadOnlySpan < KeyValuePair < string , object > > tags )
127+ internal void Update ( double value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
124128 {
125129 this . updateDoubleCallback ( value , tags ) ;
126130 }
@@ -234,15 +238,15 @@ private void InitializeOverflowTagPointIfNotInitialized()
234238 {
235239 if ( ! this . overflowTagMetricPointInitialized )
236240 {
237- this . metricPoints [ 1 ] = new MetricPoint ( this , this . aggType , new KeyValuePair < string , object > [ ] { new ( "otel.metric.overflow" , true ) } , this . histogramBounds , this . exponentialHistogramMaxSize , this . exponentialHistogramMaxScale ) ;
241+ this . metricPoints [ 1 ] = new MetricPoint ( this , this . aggType , new KeyValuePair < string , object ? > [ ] { new ( "otel.metric.overflow" , true ) } , this . histogramBounds , this . exponentialHistogramMaxSize , this . exponentialHistogramMaxScale ) ;
238242 this . overflowTagMetricPointInitialized = true ;
239243 }
240244 }
241245 }
242246 }
243247
244248 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
245- private int LookupAggregatorStore ( KeyValuePair < string , object > [ ] tagKeysAndValues , int length )
249+ private int LookupAggregatorStore ( KeyValuePair < string , object ? > [ ] tagKeysAndValues , int length )
246250 {
247251 var givenTags = new Tags ( tagKeysAndValues ) ;
248252
@@ -275,10 +279,10 @@ private int LookupAggregatorStore(KeyValuePair<string, object>[] tagKeysAndValue
275279 // so we need to make a deep copy for Dictionary storage.
276280 if ( length <= ThreadStaticStorage . MaxTagCacheSize )
277281 {
278- var givenTagKeysAndValues = new KeyValuePair < string , object > [ length ] ;
282+ var givenTagKeysAndValues = new KeyValuePair < string , object ? > [ length ] ;
279283 tagKeysAndValues . CopyTo ( givenTagKeysAndValues . AsSpan ( ) ) ;
280284
281- var sortedTagKeysAndValues = new KeyValuePair < string , object > [ length ] ;
285+ var sortedTagKeysAndValues = new KeyValuePair < string , object ? > [ length ] ;
282286 tempSortedTagKeysAndValues . CopyTo ( sortedTagKeysAndValues . AsSpan ( ) ) ;
283287
284288 givenTags = new Tags ( givenTagKeysAndValues ) ;
@@ -328,7 +332,7 @@ private int LookupAggregatorStore(KeyValuePair<string, object>[] tagKeysAndValue
328332 }
329333
330334 // Note: We are using storage from ThreadStatic, so need to make a deep copy for Dictionary storage.
331- var givenTagKeysAndValues = new KeyValuePair < string , object > [ length ] ;
335+ var givenTagKeysAndValues = new KeyValuePair < string , object ? > [ length ] ;
332336
333337 tagKeysAndValues . CopyTo ( givenTagKeysAndValues . AsSpan ( ) ) ;
334338
@@ -366,7 +370,7 @@ private int LookupAggregatorStore(KeyValuePair<string, object>[] tagKeysAndValue
366370 return aggregatorIndex ;
367371 }
368372
369- private void UpdateLong ( long value , ReadOnlySpan < KeyValuePair < string , object > > tags )
373+ private void UpdateLong ( long value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
370374 {
371375 try
372376 {
@@ -407,7 +411,7 @@ private void UpdateLong(long value, ReadOnlySpan<KeyValuePair<string, object>> t
407411 }
408412 }
409413
410- private void UpdateLongCustomTags ( long value , ReadOnlySpan < KeyValuePair < string , object > > tags )
414+ private void UpdateLongCustomTags ( long value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
411415 {
412416 try
413417 {
@@ -448,7 +452,7 @@ private void UpdateLongCustomTags(long value, ReadOnlySpan<KeyValuePair<string,
448452 }
449453 }
450454
451- private void UpdateDouble ( double value , ReadOnlySpan < KeyValuePair < string , object > > tags )
455+ private void UpdateDouble ( double value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
452456 {
453457 try
454458 {
@@ -489,7 +493,7 @@ private void UpdateDouble(double value, ReadOnlySpan<KeyValuePair<string, object
489493 }
490494 }
491495
492- private void UpdateDoubleCustomTags ( double value , ReadOnlySpan < KeyValuePair < string , object > > tags )
496+ private void UpdateDoubleCustomTags ( double value , ReadOnlySpan < KeyValuePair < string , object ? > > tags )
493497 {
494498 try
495499 {
@@ -530,7 +534,7 @@ private void UpdateDoubleCustomTags(double value, ReadOnlySpan<KeyValuePair<stri
530534 }
531535 }
532536
533- private int FindMetricAggregatorsDefault ( ReadOnlySpan < KeyValuePair < string , object > > tags )
537+ private int FindMetricAggregatorsDefault ( ReadOnlySpan < KeyValuePair < string , object ? > > tags )
534538 {
535539 int tagLength = tags . Length ;
536540 if ( tagLength == 0 )
@@ -546,7 +550,7 @@ private int FindMetricAggregatorsDefault(ReadOnlySpan<KeyValuePair<string, objec
546550 return this . LookupAggregatorStore ( tagKeysAndValues , tagLength ) ;
547551 }
548552
549- private int FindMetricAggregatorsCustomTag ( ReadOnlySpan < KeyValuePair < string , object > > tags )
553+ private int FindMetricAggregatorsCustomTag ( ReadOnlySpan < KeyValuePair < string , object ? > > tags )
550554 {
551555 int tagLength = tags . Length ;
552556 if ( tagLength == 0 || this . tagsKeysInterestingCount == 0 )
@@ -555,12 +559,11 @@ private int FindMetricAggregatorsCustomTag(ReadOnlySpan<KeyValuePair<string, obj
555559 return 0 ;
556560 }
557561
558- // TODO: Get only interesting tags
559- // from the incoming tags
560-
561562 var storage = ThreadStaticStorage . GetStorage ( ) ;
562563
563- storage . SplitToKeysAndValues ( tags , tagLength , this . tagKeysInteresting , out var tagKeysAndValues , out var actualLength ) ;
564+ Debug . Assert ( this . tagKeysInteresting != null , "this.tagKeysInteresting was null" ) ;
565+
566+ storage . SplitToKeysAndValues ( tags , tagLength , this . tagKeysInteresting ! , out var tagKeysAndValues , out var actualLength ) ;
564567
565568 // Actual number of tags depend on how many
566569 // of the incoming tags has user opted to
@@ -571,6 +574,8 @@ private int FindMetricAggregatorsCustomTag(ReadOnlySpan<KeyValuePair<string, obj
571574 return 0 ;
572575 }
573576
574- return this . LookupAggregatorStore ( tagKeysAndValues , actualLength ) ;
577+ Debug . Assert ( tagKeysAndValues != null , "tagKeysAndValues was null" ) ;
578+
579+ return this . LookupAggregatorStore ( tagKeysAndValues ! , actualLength ) ;
575580 }
576581}
0 commit comments