1717 */
1818
1919pub mod prom_utils;
20- use std:: { path:: Path , sync:: OnceLock } ;
20+ use std:: {
21+ collections:: VecDeque ,
22+ path:: Path ,
23+ sync:: { Mutex , OnceLock } ,
24+ } ;
2125
2226use crate :: {
2327 handlers:: { TelemetryType , http:: metrics_path} ,
@@ -247,7 +251,7 @@ pub static PROCESS_CPU_USAGE_CORES: Lazy<Gauge> = Lazy::new(|| {
247251 Gauge :: with_opts (
248252 Opts :: new (
249253 "process_cpu_usage_cores" ,
250- "CPU cores used by the Parseable cgroup, or zero when cgroup usage is unavailable " ,
254+ "Average CPU cores used by the Parseable cgroup over the last minute " ,
251255 )
252256 . namespace ( METRICS_NAMESPACE ) ,
253257 )
@@ -337,8 +341,23 @@ impl ProcessMetricsAccumulator {
337341pub static PROCESS_METRICS_ACCUMULATOR : Lazy < ProcessMetricsAccumulator > =
338342 Lazy :: new ( ProcessMetricsAccumulator :: default) ;
339343
344+ const CPU_USAGE_CORES_WINDOW_SAMPLES : usize = 12 ;
345+ static CPU_USAGE_CORES_SAMPLES : Lazy < Mutex < VecDeque < f64 > > > =
346+ Lazy :: new ( || Mutex :: new ( VecDeque :: with_capacity ( CPU_USAGE_CORES_WINDOW_SAMPLES ) ) ) ;
347+
348+ fn update_cpu_usage_cores_average ( samples : & mut VecDeque < f64 > , sample : f64 ) -> f64 {
349+ if samples. len ( ) == CPU_USAGE_CORES_WINDOW_SAMPLES {
350+ samples. pop_front ( ) ;
351+ }
352+ samples. push_back ( sample) ;
353+
354+ samples. iter ( ) . sum :: < f64 > ( ) / samples. len ( ) as f64
355+ }
356+
340357pub fn record_process_cpu_usage_cores ( cpu_usage_cores : f64 ) {
341- PROCESS_CPU_USAGE_CORES . set ( cpu_usage_cores) ;
358+ let mut samples = CPU_USAGE_CORES_SAMPLES . lock ( ) . unwrap ( ) ;
359+ let average = update_cpu_usage_cores_average ( & mut samples, cpu_usage_cores) ;
360+ PROCESS_CPU_USAGE_CORES . set ( average) ;
342361}
343362
344363pub fn record_process_metrics_sample (
@@ -363,7 +382,9 @@ pub fn record_process_metrics_sample(
363382mod process_metrics_tests {
364383 use crate :: metrics:: PROCESS_METRICS_INIT ;
365384
366- use super :: ProcessMetricsAccumulator ;
385+ use super :: {
386+ CPU_USAGE_CORES_WINDOW_SAMPLES , ProcessMetricsAccumulator , update_cpu_usage_cores_average,
387+ } ;
367388
368389 #[ test]
369390 fn averages_process_metric_samples ( ) {
@@ -374,6 +395,20 @@ mod process_metrics_tests {
374395 assert_eq ! ( accumulator. record( 10.0 , 100 ) , ( 10.0 , 100.0 ) ) ;
375396 assert_eq ! ( accumulator. record( 20.0 , 300 ) , ( 10.8 , 116.0 ) ) ;
376397 }
398+
399+ #[ test]
400+ fn cpu_usage_cores_window_is_one_minute_of_samples ( ) {
401+ let mut samples = std:: collections:: VecDeque :: new ( ) ;
402+ let mut average = 0.0 ;
403+ for sample in 1 ..=CPU_USAGE_CORES_WINDOW_SAMPLES + 1 {
404+ average = update_cpu_usage_cores_average ( & mut samples, sample as f64 ) ;
405+ }
406+
407+ assert_eq ! ( samples. len( ) , CPU_USAGE_CORES_WINDOW_SAMPLES ) ;
408+ assert_eq ! ( samples. front( ) , Some ( & 2.0 ) ) ;
409+ assert_eq ! ( samples. back( ) , Some ( & 13.0 ) ) ;
410+ assert_eq ! ( average, 7.5 ) ;
411+ }
377412}
378413
379414pub static QUERY_EXECUTE_TIME : Lazy < HistogramVec > = Lazy :: new ( || {
0 commit comments