@@ -14,39 +14,25 @@ internal sealed class LinuxUtilizationProvider : ISnapshotProvider
1414{
1515 private const double One = 1.0 ;
1616 private const long Hundred = 100L ;
17- private const double CpuLimitThreshold110Percent = 1.1 ;
1817
19- // Meters to track CPU utilization threshold exceedances
20- private readonly Counter < long > ? _cpuUtilizationLimit100PercentExceededCounter ;
21- private readonly Counter < long > ? _cpuUtilizationLimit110PercentExceededCounter ;
22-
23- private readonly bool _useDeltaNrPeriods ;
2418 private readonly object _cpuLocker = new ( ) ;
2519 private readonly object _memoryLocker = new ( ) ;
2620 private readonly ILogger < LinuxUtilizationProvider > _logger ;
2721 private readonly ILinuxUtilizationParser _parser ;
2822 private readonly ulong _memoryLimit ;
23+ private readonly long _cpuPeriodsInterval ;
2924 private readonly TimeSpan _cpuRefreshInterval ;
3025 private readonly TimeSpan _memoryRefreshInterval ;
3126 private readonly TimeProvider _timeProvider ;
32- private readonly double _scaleRelativeToCpuLimit ;
33- private readonly double _scaleRelativeToCpuRequest ;
3427 private readonly double _scaleRelativeToCpuRequestForTrackerApi ;
3528
3629 private DateTimeOffset _refreshAfterCpu ;
3730 private DateTimeOffset _refreshAfterMemory ;
38-
39- // Track the actual timestamp when we read CPU values
40- private DateTimeOffset _lastCpuMeasurementTime ;
41-
4231 private double _cpuPercentage = double . NaN ;
4332 private double _lastCpuCoresUsed = double . NaN ;
4433 private double _memoryPercentage ;
4534 private long _previousCgroupCpuTime ;
4635 private long _previousHostCpuTime ;
47- private long _cpuUtilizationLimit100PercentExceeded ;
48- private long _cpuUtilizationLimit110PercentExceeded ;
49- private long _cpuPeriodsInterval ;
5036 private long _previousCgroupCpuPeriodCounter ;
5137 public SystemResources Resources { get ; }
5238
@@ -59,7 +45,6 @@ public LinuxUtilizationProvider(IOptions<ResourceMonitoringOptions> options, ILi
5945 DateTimeOffset now = _timeProvider . GetUtcNow ( ) ;
6046 _cpuRefreshInterval = options . Value . CpuConsumptionRefreshInterval ;
6147 _memoryRefreshInterval = options . Value . MemoryConsumptionRefreshInterval ;
62- _useDeltaNrPeriods = options . Value . UseDeltaNrPeriodsForCpuCalculation ;
6348 _refreshAfterCpu = now ;
6449 _refreshAfterMemory = now ;
6550 _memoryLimit = _parser . GetAvailableMemoryInBytes ( ) ;
@@ -69,8 +54,8 @@ public LinuxUtilizationProvider(IOptions<ResourceMonitoringOptions> options, ILi
6954 float hostCpus = _parser . GetHostCpuCount ( ) ;
7055 float cpuLimit = _parser . GetCgroupLimitedCpus ( ) ;
7156 float cpuRequest = _parser . GetCgroupRequestCpu ( ) ;
72- _scaleRelativeToCpuLimit = hostCpus / cpuLimit ;
73- _scaleRelativeToCpuRequest = hostCpus / cpuRequest ;
57+ float scaleRelativeToCpuLimit = hostCpus / cpuLimit ;
58+ float scaleRelativeToCpuRequest = hostCpus / cpuRequest ;
7459 _scaleRelativeToCpuRequestForTrackerApi = hostCpus ; // the division by cpuRequest is performed later on in the ResourceUtilization class
7560
7661#pragma warning disable CA2000 // Dispose objects before losing scope
@@ -80,28 +65,23 @@ public LinuxUtilizationProvider(IOptions<ResourceMonitoringOptions> options, ILi
8065 var meter = meterFactory . Create ( ResourceUtilizationInstruments . MeterName ) ;
8166#pragma warning restore CA2000 // Dispose objects before losing scope
8267
83- if ( options . Value . CalculateCpuUsageWithoutHostDelta )
68+ if ( options . Value . UseLinuxCpuUsageV2 )
8469 {
8570 cpuLimit = _parser . GetCgroupLimitV2 ( ) ;
86-
87- // Try to get the CPU request from cgroup
8871 cpuRequest = _parser . GetCgroupRequestCpuV2 ( ) ;
8972
9073 // Get Cpu periods interval from cgroup
9174 _cpuPeriodsInterval = _parser . GetCgroupPeriodsIntervalInMicroSecondsV2 ( ) ;
9275 ( _previousCgroupCpuTime , _previousCgroupCpuPeriodCounter ) = _parser . GetCgroupCpuUsageInNanosecondsAndCpuPeriodsV2 ( ) ;
9376
94- // Initialize the counters
95- _cpuUtilizationLimit100PercentExceededCounter = meter . CreateCounter < long > ( "cpu_utilization_limit_100_percent_exceeded" ) ;
96- _cpuUtilizationLimit110PercentExceededCounter = meter . CreateCounter < long > ( "cpu_utilization_limit_110_percent_exceeded" ) ;
9777 _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuLimitUtilization , observeValue : ( ) => CpuUtilizationLimit ( cpuLimit ) , unit : "1" ) ;
98- _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuRequestUtilization , observeValue : ( ) => CpuUtilizationWithoutHostDelta ( ) / cpuRequest , unit : "1" ) ;
78+ _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuRequestUtilization , observeValue : ( ) => CpuUtilizationRequest ( cpuRequest ) , unit : "1" ) ;
9979 }
10080 else
10181 {
102- _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuLimitUtilization , observeValue : ( ) => CpuUtilization ( ) * _scaleRelativeToCpuLimit , unit : "1" ) ;
103- _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuRequestUtilization , observeValue : ( ) => CpuUtilization ( ) * _scaleRelativeToCpuRequest , unit : "1" ) ;
104- _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ProcessCpuUtilization , observeValue : ( ) => CpuUtilization ( ) * _scaleRelativeToCpuRequest , unit : "1" ) ;
82+ _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuLimitUtilization , observeValue : ( ) => CpuUtilization ( ) * scaleRelativeToCpuLimit , unit : "1" ) ;
83+ _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerCpuRequestUtilization , observeValue : ( ) => CpuUtilization ( ) * scaleRelativeToCpuRequest , unit : "1" ) ;
84+ _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ProcessCpuUtilization , observeValue : ( ) => CpuUtilization ( ) * scaleRelativeToCpuRequest , unit : "1" ) ;
10585 }
10686
10787 _ = meter . CreateObservableGauge ( name : ResourceUtilizationInstruments . ContainerMemoryLimitUtilization , observeValue : MemoryUtilization , unit : "1" ) ;
@@ -115,10 +95,9 @@ public LinuxUtilizationProvider(IOptions<ResourceMonitoringOptions> options, ILi
11595 _logger . SystemResourcesInfo ( cpuLimit , cpuRequest , _memoryLimit , _memoryLimit ) ;
11696 }
11797
118- public double CpuUtilizationWithoutHostDelta ( )
98+ public double CpuUtilizationV2 ( )
11999 {
120100 DateTimeOffset now = _timeProvider . GetUtcNow ( ) ;
121- double actualElapsedNanoseconds = ( now - _lastCpuMeasurementTime ) . TotalNanoseconds ;
122101 lock ( _cpuLocker )
123102 {
124103 if ( now < _refreshAfterCpu )
@@ -127,79 +106,34 @@ public double CpuUtilizationWithoutHostDelta()
127106 }
128107 }
129108
130- var ( cpuUsageTime , cpuPeriodCounter ) = _parser . GetCgroupCpuUsageInNanosecondsAndCpuPeriodsV2 ( ) ;
109+ ( long cpuUsageTime , long cpuPeriodCounter ) = _parser . GetCgroupCpuUsageInNanosecondsAndCpuPeriodsV2 ( ) ;
131110 lock ( _cpuLocker )
132111 {
133- if ( now >= _refreshAfterCpu )
112+ if ( now < _refreshAfterCpu )
134113 {
135- long deltaCgroup = cpuUsageTime - _previousCgroupCpuTime ;
136- double coresUsed ;
137-
138- if ( _useDeltaNrPeriods )
139- {
140- long deltaPeriodCount = cpuPeriodCounter - _previousCgroupCpuPeriodCounter ;
141- long deltaCpuPeriodInNanoseconds = deltaPeriodCount * _cpuPeriodsInterval * 1000 ;
142-
143- if ( deltaCgroup > 0 && deltaPeriodCount > 0 )
144- {
145- coresUsed = deltaCgroup / ( double ) deltaCpuPeriodInNanoseconds ;
146-
147- _logger . CpuUsageDataV2 ( cpuUsageTime , _previousCgroupCpuTime , deltaCpuPeriodInNanoseconds , coresUsed ) ;
148-
149- _lastCpuCoresUsed = coresUsed ;
150- _refreshAfterCpu = now . Add ( _cpuRefreshInterval ) ;
151- _previousCgroupCpuTime = cpuUsageTime ;
152- _previousCgroupCpuPeriodCounter = cpuPeriodCounter ;
153- }
154- }
155- else
156- {
157- if ( deltaCgroup > 0 )
158- {
159- coresUsed = deltaCgroup / actualElapsedNanoseconds ;
160-
161- _logger . CpuUsageDataV2 ( cpuUsageTime , _previousCgroupCpuTime , actualElapsedNanoseconds , coresUsed ) ;
162-
163- _lastCpuCoresUsed = coresUsed ;
164- _refreshAfterCpu = now . Add ( _cpuRefreshInterval ) ;
165- _previousCgroupCpuTime = cpuUsageTime ;
166-
167- // Update the timestamp for next calculation
168- _lastCpuMeasurementTime = now ;
169- }
170- }
114+ return _lastCpuCoresUsed ;
171115 }
172- }
173116
174- return _lastCpuCoresUsed ;
175- }
117+ long deltaCgroup = cpuUsageTime - _previousCgroupCpuTime ;
118+ long deltaPeriodCount = cpuPeriodCounter - _previousCgroupCpuPeriodCounter ;
176119
177- /// <summary>
178- /// Calculates CPU utilization relative to the CPU limit.
179- /// </summary>
180- /// <param name="cpuLimit">The CPU limit to use for the calculation.</param>
181- /// <returns>CPU usage as a ratio of the limit.</returns>
182- public double CpuUtilizationLimit ( float cpuLimit )
183- {
184- double utilization = CpuUtilizationWithoutHostDelta ( ) / cpuLimit ;
120+ if ( deltaCgroup <= 0 || deltaPeriodCount <= 0 )
121+ {
122+ return _lastCpuCoresUsed ;
123+ }
185124
186- // Increment counter if utilization exceeds 1 (100%)
187- if ( utilization > 1.0 )
188- {
189- _cpuUtilizationLimit100PercentExceededCounter ? . Add ( 1 ) ;
190- _cpuUtilizationLimit100PercentExceeded ++ ;
191- _logger . CounterMessage100 ( _cpuUtilizationLimit100PercentExceeded ) ;
192- }
125+ long deltaCpuPeriodInNanoseconds = deltaPeriodCount * _cpuPeriodsInterval * 1000 ;
126+ double coresUsed = deltaCgroup / ( double ) deltaCpuPeriodInNanoseconds ;
193127
194- // Increment counter if utilization exceeds 110%
195- if ( utilization > CpuLimitThreshold110Percent )
196- {
197- _cpuUtilizationLimit110PercentExceededCounter ? . Add ( 1 ) ;
198- _cpuUtilizationLimit110PercentExceeded ++ ;
199- _logger . CounterMessage110 ( _cpuUtilizationLimit110PercentExceeded ) ;
128+ _logger . CpuUsageDataV2 ( cpuUsageTime , _previousCgroupCpuTime , deltaCpuPeriodInNanoseconds , coresUsed ) ;
129+
130+ _lastCpuCoresUsed = coresUsed ;
131+ _refreshAfterCpu = now . Add ( _cpuRefreshInterval ) ;
132+ _previousCgroupCpuTime = cpuUsageTime ;
133+ _previousCgroupCpuPeriodCounter = cpuPeriodCounter ;
200134 }
201135
202- return utilization ;
136+ return _lastCpuCoresUsed ;
203137 }
204138
205139 public double CpuUtilization ( )
@@ -219,23 +153,27 @@ public double CpuUtilization()
219153
220154 lock ( _cpuLocker )
221155 {
222- if ( now >= _refreshAfterCpu )
156+ if ( now < _refreshAfterCpu )
223157 {
224- long deltaHost = hostCpuTime - _previousHostCpuTime ;
225- long deltaCgroup = cgroupCpuTime - _previousCgroupCpuTime ;
226-
227- if ( deltaHost > 0 && deltaCgroup > 0 )
228- {
229- double percentage = Math . Min ( One , ( double ) deltaCgroup / deltaHost ) ;
158+ return _cpuPercentage ;
159+ }
230160
231- _logger . CpuUsageData ( cgroupCpuTime , hostCpuTime , _previousCgroupCpuTime , _previousHostCpuTime , percentage ) ;
161+ long deltaHost = hostCpuTime - _previousHostCpuTime ;
162+ long deltaCgroup = cgroupCpuTime - _previousCgroupCpuTime ;
232163
233- _cpuPercentage = percentage ;
234- _refreshAfterCpu = now . Add ( _cpuRefreshInterval ) ;
235- _previousCgroupCpuTime = cgroupCpuTime ;
236- _previousHostCpuTime = hostCpuTime ;
237- }
164+ if ( deltaHost <= 0 || deltaCgroup <= 0 )
165+ {
166+ return _cpuPercentage ;
238167 }
168+
169+ double percentage = Math . Min ( One , ( double ) deltaCgroup / deltaHost ) ;
170+
171+ _logger . CpuUsageData ( cgroupCpuTime , hostCpuTime , _previousCgroupCpuTime , _previousHostCpuTime , percentage ) ;
172+
173+ _cpuPercentage = percentage ;
174+ _refreshAfterCpu = now . Add ( _cpuRefreshInterval ) ;
175+ _previousCgroupCpuTime = cgroupCpuTime ;
176+ _previousHostCpuTime = hostCpuTime ;
239177 }
240178
241179 return _cpuPercentage ;
@@ -288,4 +226,7 @@ public Snapshot GetSnapshot()
288226 userTimeSinceStart : TimeSpan . FromTicks ( ( long ) ( cgroupTime / Hundred * _scaleRelativeToCpuRequestForTrackerApi ) ) ,
289227 memoryUsageInBytes : memoryUsed ) ;
290228 }
229+
230+ private double CpuUtilizationRequest ( double cpuRequest ) => Math . Min ( One , CpuUtilizationV2 ( ) / cpuRequest ) ;
231+ private double CpuUtilizationLimit ( double cpuLimit ) => Math . Min ( One , CpuUtilizationV2 ( ) / cpuLimit ) ;
291232}
0 commit comments