1- use std:: { collections:: VecDeque , io, path:: Path , sync:: atomic:: Ordering } ;
1+ mod cgroup;
2+
3+ use std:: { collections:: VecDeque , io, sync:: atomic:: Ordering } ;
24
3- use cgroups_rs:: cgroup:: Cgroup ;
45use metrics:: gauge;
56use nix:: errno:: Errno ;
67use procfs:: ProcError :: PermissionDenied ;
@@ -9,6 +10,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
910use tracing:: { error, warn} ;
1011
1112use crate :: observer:: memory:: { Regions , Rollup } ;
13+ use cgroup:: v2;
1214
1315use super :: RSS_BYTES ;
1416
@@ -27,8 +29,8 @@ pub enum Error {
2729 /// Wrapper for [`procfs::ProcError`]
2830 #[ error( "Unable to read procfs: {0}" ) ]
2931 Proc ( #[ from] procfs:: ProcError ) ,
30- #[ error( "Unable to read cgroups : {0}" ) ]
31- CGroups ( #[ from] cgroups_rs :: error :: Error ) ,
32+ #[ error( "Unable to read cgroup : {0}" ) ]
33+ CGroup ( #[ from] v2 :: Error ) ,
3234}
3335
3436macro_rules! report_status_field {
@@ -401,96 +403,8 @@ impl Sampler {
401403 // if possible we compute the working set of the cgroup
402404 // using the same heuristic as kubernetes:
403405 // total_usage - inactive_file
404- let cgroup = get_cgroup ( pid as _ ) ?;
405- if let Some ( memory_controller) =
406- cgroup. controller_of :: < cgroups_rs:: memory:: MemController > ( )
407- {
408- let mem_stat = memory_controller. memory_stat ( ) ;
409-
410- let inactive_file = if cgroup. v2 ( ) {
411- mem_stat. stat . inactive_file
412- } else {
413- mem_stat. stat . total_inactive_file
414- } ;
415- let usage = mem_stat. usage_in_bytes ;
416- let working_set = if usage < inactive_file {
417- 0
418- } else {
419- usage - inactive_file
420- } ;
421-
422- gauge ! ( "working_set_bytes" ) . set ( working_set as f64 ) ;
423- gauge ! ( "memory.working_set_bytes" ) . set ( working_set as f64 ) ;
424-
425- gauge ! ( "memory.fail_cnt" ) . set ( mem_stat. fail_cnt as f64 ) ;
426- gauge ! ( "memory.limit_bytes" ) . set ( mem_stat. limit_in_bytes as f64 ) ;
427- gauge ! ( "memory.usage_in_bytes" ) . set ( mem_stat. usage_in_bytes as f64 ) ;
428- gauge ! ( "memory.max_usage_in_bytes" ) . set ( mem_stat. max_usage_in_bytes as f64 ) ;
429- gauge ! ( "memory.soft_limit_in_bytes" ) . set ( mem_stat. soft_limit_in_bytes as f64 ) ;
430-
431- gauge ! ( "memory.stat.cache" ) . set ( mem_stat. stat . cache as f64 ) ;
432- gauge ! ( "memory.stat.rss" ) . set ( mem_stat. stat . rss as f64 ) ;
433- gauge ! ( "memory.stat.rss_huge" ) . set ( mem_stat. stat . rss_huge as f64 ) ;
434- gauge ! ( "memory.stat.shmem" ) . set ( mem_stat. stat . shmem as f64 ) ;
435- gauge ! ( "memory.stat.mapped_file" ) . set ( mem_stat. stat . mapped_file as f64 ) ;
436- gauge ! ( "memory.stat.dirty" ) . set ( mem_stat. stat . dirty as f64 ) ;
437- gauge ! ( "memory.stat.writeback" ) . set ( mem_stat. stat . writeback as f64 ) ;
438- gauge ! ( "memory.stat.swap" ) . set ( mem_stat. stat . swap as f64 ) ;
439- gauge ! ( "memory.stat.pgpgin" ) . set ( mem_stat. stat . pgpgin as f64 ) ;
440- gauge ! ( "memory.stat.pgpgout" ) . set ( mem_stat. stat . pgpgout as f64 ) ;
441- gauge ! ( "memory.stat.pgfault" ) . set ( mem_stat. stat . pgfault as f64 ) ;
442- gauge ! ( "memory.stat.pgmajfault" ) . set ( mem_stat. stat . pgmajfault as f64 ) ;
443- gauge ! ( "memory.stat.inactive_anon" ) . set ( mem_stat. stat . inactive_anon as f64 ) ;
444- gauge ! ( "memory.stat.active_anon" ) . set ( mem_stat. stat . active_anon as f64 ) ;
445- gauge ! ( "memory.stat.inactive_file" ) . set ( mem_stat. stat . inactive_file as f64 ) ;
446- gauge ! ( "memory.stat.active_file" ) . set ( mem_stat. stat . active_file as f64 ) ;
447- gauge ! ( "memory.stat.unevictable" ) . set ( mem_stat. stat . unevictable as f64 ) ;
448- gauge ! ( "memory.stat.hierarchical_memory_limit" )
449- . set ( mem_stat. stat . hierarchical_memory_limit as f64 ) ;
450- gauge ! ( "memory.stat.hierarchical_memsw_limit" )
451- . set ( mem_stat. stat . hierarchical_memsw_limit as f64 ) ;
452- gauge ! ( "memory.stat.total_cache" ) . set ( mem_stat. stat . total_cache as f64 ) ;
453- gauge ! ( "memory.stat.total_rss" ) . set ( mem_stat. stat . total_rss as f64 ) ;
454- gauge ! ( "memory.stat.total_rss_huge" ) . set ( mem_stat. stat . total_rss_huge as f64 ) ;
455- gauge ! ( "memory.stat.total_shmem" ) . set ( mem_stat. stat . total_shmem as f64 ) ;
456- gauge ! ( "memory.stat.total_mapped_file" ) . set ( mem_stat. stat . total_mapped_file as f64 ) ;
457- gauge ! ( "memory.stat.total_dirty" ) . set ( mem_stat. stat . total_dirty as f64 ) ;
458- gauge ! ( "memory.stat.total_writeback" ) . set ( mem_stat. stat . total_writeback as f64 ) ;
459- gauge ! ( "memory.stat.total_swap" ) . set ( mem_stat. stat . total_swap as f64 ) ;
460- gauge ! ( "memory.stat.total_pgpgin" ) . set ( mem_stat. stat . total_pgpgin as f64 ) ;
461- gauge ! ( "memory.stat.total_pgpgout" ) . set ( mem_stat. stat . total_pgpgout as f64 ) ;
462- gauge ! ( "memory.stat.total_pgfault" ) . set ( mem_stat. stat . total_pgfault as f64 ) ;
463- gauge ! ( "memory.stat.total_pgmajfault" ) . set ( mem_stat. stat . total_pgmajfault as f64 ) ;
464- gauge ! ( "memory.stat.total_inactive_anon" )
465- . set ( mem_stat. stat . total_inactive_anon as f64 ) ;
466- gauge ! ( "memory.stat.total_active_anon" ) . set ( mem_stat. stat . total_active_anon as f64 ) ;
467- gauge ! ( "memory.stat.total_inactive_file" )
468- . set ( mem_stat. stat . total_inactive_file as f64 ) ;
469- gauge ! ( "memory.stat.total_active_file" ) . set ( mem_stat. stat . total_active_file as f64 ) ;
470- gauge ! ( "memory.stat.total_unevictable" ) . set ( mem_stat. stat . total_unevictable as f64 ) ;
471- }
472- // Load the CPU controller and get the cpu.stat String out of the
473- // cgroup, parse whatever fields are present and report them back
474- // out as metrics.
475- if let Some ( cpu_controller) = cgroup. controller_of :: < cgroups_rs:: cpu:: CpuController > ( ) {
476- let cpu = cpu_controller. cpu ( ) ;
477- for line in cpu. stat . lines ( ) {
478- let mut fields = line. split_whitespace ( ) ;
479- let metric_name = fields. next ( ) . unwrap_or_default ( ) ;
480- let value = fields. next ( ) . unwrap_or_default ( ) ;
481- gauge ! ( format!( "cpu.{metric_name}" ) )
482- . set ( value. parse :: < f64 > ( ) . unwrap_or_default ( ) ) ;
483- }
484- if let Ok ( shares) = cpu_controller. shares ( ) {
485- gauge ! ( "cpu.shares" ) . set ( shares as f64 ) ;
486- }
487- if let Ok ( cfs_period) = cpu_controller. cfs_period ( ) {
488- gauge ! ( "cpu.cfs_period" ) . set ( cfs_period as f64 ) ;
489- }
490- if let Ok ( cfs_quota) = cpu_controller. cfs_quota ( ) {
491- gauge ! ( "cpu.cfs_quota" ) . set ( cfs_quota as f64 ) ;
492- }
493- }
406+ let cgroup_path = v2:: get_path ( pid) . await ?;
407+ v2:: poll ( cgroup_path) . await ?;
494408 }
495409
496410 gauge ! ( "num_processes" ) . set ( total_processes as f64 ) ;
@@ -608,38 +522,3 @@ fn percentage(delta_ticks: f64, delta_time: f64, num_cores: f64) -> f64 {
608522
609523 overall_percentage. clamp ( 0.0 , 100.0 * num_cores)
610524}
611-
612- #[ inline]
613- fn get_cgroup ( pid : u32 ) -> Result < Cgroup , Error > {
614- let hierarchies = cgroups_rs:: hierarchies:: auto ( ) ;
615- if hierarchies. v2 ( ) {
616- // for cgroups v2, we parse `/proc/<pid>/cgroup` looking for the main cgroup
617- // relative path. We then use this to load the correct cgroup.
618- // For unknown reasons, the cgroups_rs lib is not able to do this on its own.
619- // Heavily inspired by
620- // https://github.com/containerd/rust-extensions/blob/3d4de340d83aa06dff24fbf73d7d584ebe77c7ec/crates/shim/src/cgroup.rs#L178
621-
622- let eof = || io:: Error :: from ( io:: ErrorKind :: UnexpectedEof ) ;
623- let path = format ! ( "/proc/{pid}/cgroup" ) ;
624- let content = std:: fs:: read_to_string ( path) ?;
625-
626- let first_line = content. lines ( ) . next ( ) . ok_or_else ( eof) ?;
627- let ( _, path_part) = first_line. split_once ( "::" ) . ok_or_else ( eof) ?;
628-
629- let mut path_parts = path_part. split ( '/' ) . skip ( 1 ) ;
630- let namespace = path_parts. next ( ) . ok_or_else ( eof) ?;
631- let cgroup_name = path_parts. next ( ) . ok_or_else ( eof) ?;
632-
633- Ok ( Cgroup :: load (
634- hierarchies,
635- format ! ( "/sys/fs/cgroup/{namespace}/{cgroup_name}" ) . as_str ( ) ,
636- ) )
637- } else {
638- let relative_paths = cgroups_rs:: cgroup:: get_cgroups_relative_paths_by_pid ( pid) ?;
639- Ok ( Cgroup :: load_with_relative_paths (
640- hierarchies,
641- Path :: new ( "." ) ,
642- relative_paths,
643- ) )
644- }
645- }
0 commit comments