1414
1515namespace Datadog . Trace . OTelMetrics
1616{
17- internal class MetricPoint
17+ internal class MetricPoint ( string instrumentName , string meterName , string instrumentType , string temporality , Dictionary < string , object ? > tags , bool isIntegerValue = false )
1818 {
19- private static readonly double [ ] DefaultHistogramBounds = [ 0 , 5 , 10 , 25 , 50 , 75 , 100 , 250 , 500 , 750 , 1000 , 2500 , 5000 , 7500 , 10000 ] ;
19+ // Static fields first
20+ internal static readonly double [ ] DefaultHistogramBounds = [ 0 , 5 , 10 , 25 , 50 , 75 , 100 , 250 , 500 , 750 , 1000 , 2500 , 5000 , 7500 , 10000 ] ;
2021
21- // Histogram-specific
22- private readonly long [ ] _runningBucketCounts ;
22+ // Instance fields
23+ private readonly long [ ] _runningBucketCounts = instrumentType == "Histogram" ? new long [ DefaultHistogramBounds . Length + 1 ] : [ ] ;
2324 private readonly object _histogramLock = new ( ) ;
24-
25- // Thread-safe running values (hot path)
2625 private long _runningCountValue ; // For counters and histogram count
2726 private double _runningDoubleValue ; // For gauges and histogram sum
2827 private double _runningMin = double . PositiveInfinity ;
2928 private double _runningMax = double . NegativeInfinity ;
3029
31- public MetricPoint ( string instrumentName , string meterName , string instrumentType , string temporality , Dictionary < string , object ? > tags )
32- {
33- // Initialize histogram buckets if needed
34- if ( instrumentType == "Histogram" )
35- {
36- _runningBucketCounts = new long [ DefaultHistogramBounds . Length + 1 ] ; // +1 for overflow
37- SnapshotBucketCounts = new long [ DefaultHistogramBounds . Length + 1 ] ;
38- }
39- else
40- {
41- _runningBucketCounts = [ ] ;
42- SnapshotBucketCounts = [ ] ;
43- }
44-
45- InstrumentName = instrumentName ;
46- MeterName = meterName ;
47- InstrumentType = instrumentType ;
48- AggregationTemporality = temporality ;
49- Tags = tags ;
50- StartTime = DateTimeOffset . UtcNow ;
51- EndTime = DateTimeOffset . UtcNow ;
52- }
53-
54- public string InstrumentName { get ; }
30+ // Constructor
5531
56- public string MeterName { get ; }
32+ // Public properties
33+ public string InstrumentName { get ; } = instrumentName ;
5734
58- public string InstrumentType { get ; }
35+ public string MeterName { get ; } = meterName ;
5936
60- public string AggregationTemporality { get ; }
37+ public string InstrumentType { get ; } = instrumentType ;
6138
62- public Dictionary < string , object ? > Tags { get ; }
39+ public string AggregationTemporality { get ; } = temporality ;
6340
64- public DateTimeOffset StartTime { get ; private set ; }
41+ public Dictionary < string , object ? > Tags { get ; } = tags ;
6542
66- public DateTimeOffset EndTime { get ; private set ; }
43+ public bool IsIntegerValue { get ; set ; } = isIntegerValue ;
6744
68- // Snapshot values (export time)
69- public long SnapshotCount { get ; private set ; }
45+ // Internal properties for collection access
46+ internal long RunningCount => _runningCountValue ;
7047
71- public double SnapshotSum { get ; private set ; }
48+ internal double RunningSum => _runningDoubleValue ;
7249
73- public double SnapshotGaugeValue { get ; private set ; }
50+ internal double RunningMin => _runningMin ;
7451
75- public double SnapshotMin { get ; private set ; }
52+ internal double RunningMax => _runningMax ;
7653
77- public double SnapshotMax { get ; private set ; }
78-
79- public long [ ] SnapshotBucketCounts { get ; private set ; }
54+ internal long [ ] RunningBucketCounts => _runningBucketCounts ;
8055
8156 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
8257 public void UpdateCounter ( double value )
@@ -86,16 +61,12 @@ public void UpdateCounter(double value)
8661 {
8762 _runningDoubleValue += value ;
8863 }
89-
90- EndTime = DateTimeOffset . UtcNow ;
9164 }
9265
9366 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
9467 public void UpdateGauge ( double value )
9568 {
96- // Lock-free gauge update (like OTel)
9769 Interlocked . Exchange ( ref _runningDoubleValue , value ) ;
98- EndTime = DateTimeOffset . UtcNow ;
9970 }
10071
10172 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -104,7 +75,6 @@ public void UpdateHistogram(double value)
10475 // Find bucket index first (outside lock for performance)
10576 var bucketIndex = FindBucketIndex ( value ) ;
10677
107- // Minimal lock scope (like OTel)
10878 lock ( _histogramLock )
10979 {
11080 unchecked
@@ -117,57 +87,6 @@ public void UpdateHistogram(double value)
11787 _runningMin = Math . Min ( _runningMin , value ) ;
11888 _runningMax = Math . Max ( _runningMax , value ) ;
11989 }
120-
121- EndTime = DateTimeOffset . UtcNow ;
122- }
123-
124- public void TakeSnapshot ( bool outputDelta )
125- {
126- EndTime = DateTimeOffset . UtcNow ;
127-
128- switch ( InstrumentType )
129- {
130- case "Counter" :
131- if ( outputDelta )
132- {
133- var currentValue = Interlocked . CompareExchange ( ref _runningDoubleValue , 0 , 0 ) ; // Datadog read pattern
134- SnapshotSum = currentValue - SnapshotSum ; // Delta calculation
135- }
136- else
137- {
138- SnapshotSum = Interlocked . CompareExchange ( ref _runningDoubleValue , 0 , 0 ) ; // Cumulative
139- }
140-
141- break ;
142-
143- case "Gauge" :
144- SnapshotGaugeValue = Interlocked . CompareExchange ( ref _runningDoubleValue , 0 , 0 ) ;
145- break ;
146-
147- case "Histogram" :
148- lock ( _histogramLock )
149- {
150- SnapshotCount = _runningCountValue ;
151- SnapshotSum = _runningDoubleValue ;
152- SnapshotMin = _runningMin ;
153- SnapshotMax = _runningMax ;
154-
155- // Copy bucket counts
156- Array . Copy ( _runningBucketCounts , SnapshotBucketCounts , _runningBucketCounts . Length ) ;
157-
158- if ( outputDelta )
159- {
160- // Reset for delta
161- _runningCountValue = 0 ;
162- _runningDoubleValue = 0 ;
163- _runningMin = double . PositiveInfinity ;
164- _runningMax = double . NegativeInfinity ;
165- Array . Clear ( _runningBucketCounts ) ;
166- }
167- }
168-
169- break ;
170- }
17190 }
17291
17392 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
0 commit comments