1- use procfs:: process:: Process ;
1+ use std:: time:: { Instant , SystemTime , UNIX_EPOCH } ;
2+
3+ use procfs:: process:: { LimitValue , Process } ;
24use prometheus_client:: {
35 collector:: Collector ,
46 encoding:: { DescriptorEncoder , EncodeMetric } ,
5- metrics:: counter:: ConstCounter ,
7+ metrics:: { counter:: ConstCounter , gauge :: ConstGauge } ,
68 registry:: Unit ,
79} ;
810
@@ -14,45 +16,100 @@ pub struct ProcessCollector {
1416impl Collector for ProcessCollector {
1517 fn encode ( & self , mut encoder : DescriptorEncoder ) -> Result < ( ) , std:: fmt:: Error > {
1618 let tps = procfs:: ticks_per_second ( ) ;
17- // process_cpu_seconds_total Total user and system CPU time spent in seconds.
18- // process_max_fds Maximum number of open file descriptors.
19- // process_open_fds Number of open file descriptors.
20- // process_virtual_memory_bytes Virtual memory size in bytes.
21- // process_resident_memory_bytes Resident memory size in bytes.
22- // process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.
23- // process_start_time_seconds Start time of the process since unix epoch in seconds.
24- // process_network_receive_bytes_total Number of bytes received by the process over the network.
25- // process_network_transmit_bytes_total Number of bytes sent by the process over the network.
2619
27- if let Ok ( proc) = Process :: myself ( ) {
28- if let Ok ( stat) = proc. stat ( ) {
29- let cpu_time = ( stat. stime + stat. utime ) / tps as u64 ;
30- let counter = ConstCounter :: new ( cpu_time) ;
31- let metric_encoder = encoder. encode_descriptor (
32- "process_cpu_seconds_total" ,
33- "Total user and system CPU time spent in seconds." ,
34- Some ( & Unit :: Seconds ) ,
35- counter. metric_type ( ) ,
36- ) ?;
37- counter. encode ( metric_encoder) ?;
20+ // TODO: handle errors
21+ let proc = match Process :: myself ( ) {
22+ Ok ( proc) => proc,
23+ Err ( _) => {
24+ return Ok ( ( ) ) ;
3825 }
39-
40- if let Ok ( limits) = proc. limits ( ) {
41- let max_fds = match limits. max_open_files . soft_limit {
42- procfs:: process:: LimitValue :: Value ( v) => v,
43- procfs:: process:: LimitValue :: Unlimited => 0 ,
44- } ;
45- let counter = ConstCounter :: new ( max_fds) ;
46- let metric_encoder = encoder. encode_descriptor (
47- "process_max_fds" ,
48- "Maximum number of open file descriptors." ,
49- None ,
50- counter. metric_type ( ) ,
51- ) ?;
52- counter. encode ( metric_encoder) ?;
26+ } ;
27+ let stat = match proc. stat ( ) {
28+ Ok ( stat) => stat,
29+ Err ( _) => {
30+ return Ok ( ( ) ) ;
5331 }
32+ } ;
33+
34+ let cpu_time = ( stat. stime + stat. utime ) / tps;
35+ let counter = ConstCounter :: new ( cpu_time) ;
36+ let metric_encoder = encoder. encode_descriptor (
37+ "process_cpu_seconds_total" ,
38+ "Total user and system CPU time spent in seconds." ,
39+ Some ( & Unit :: Seconds ) ,
40+ counter. metric_type ( ) ,
41+ ) ?;
42+ counter. encode ( metric_encoder) ?;
43+
44+ if let Ok ( limits) = proc. limits ( ) {
45+ let max_open_files = limits. max_open_files ;
46+ let max_fds = match max_open_files. soft_limit {
47+ LimitValue :: Unlimited => match max_open_files. hard_limit {
48+ LimitValue :: Unlimited => 0 ,
49+ LimitValue :: Value ( hard) => hard,
50+ } ,
51+ LimitValue :: Value ( soft) => soft,
52+ } ;
53+ let gauge = ConstGauge :: new ( max_fds as i64 ) ;
54+ let metric_encoder = encoder. encode_descriptor (
55+ "process_max_fds" ,
56+ "Maximum number of open file descriptors." ,
57+ None ,
58+ gauge. metric_type ( ) ,
59+ ) ?;
60+ gauge. encode ( metric_encoder) ?;
61+
62+ let max_address_space = limits. max_address_space ;
63+ let max_virtual_memory = match max_address_space. soft_limit {
64+ LimitValue :: Unlimited => match max_address_space. hard_limit {
65+ LimitValue :: Unlimited => 0 ,
66+ LimitValue :: Value ( hard) => hard,
67+ } ,
68+ LimitValue :: Value ( soft) => soft,
69+ } ;
70+ let gauge = ConstGauge :: new ( max_fds as i64 ) ;
71+ let metric_encoder = encoder. encode_descriptor (
72+ "process_virtual_memory_max_bytes" ,
73+ "Maximum amount of virtual memory available in bytes." ,
74+ None ,
75+ gauge. metric_type ( ) ,
76+ ) ?;
77+ gauge. encode ( metric_encoder) ?;
5478 }
5579
80+ let vm_bytes = ConstGauge :: new ( stat. vsize as i64 ) ;
81+ let vme = encoder. encode_descriptor (
82+ "process_virtual_memory_bytes" ,
83+ "Virtual memory size in bytes" ,
84+ Some ( & Unit :: Bytes ) ,
85+ vm_bytes. metric_type ( ) ,
86+ ) ?;
87+ vm_bytes. encode ( vme) ?;
88+
89+ // TODO: add rss_bytes (fix self.page_size)
90+ //
91+ // let rss_bytes = ConstGauge::new((stat.rss * self.page_size) as i64);
92+ // let rsse = encoder.encode_descriptor(
93+ // "process_resident_memory_bytes",
94+ // "Resident memory size in bytes.",
95+ // Some(&Unit::Bytes),
96+ // rss_bytes.metric_type(),
97+ // )?;
98+ // rss_bytes.encode(rsse)?;
99+
100+ let start_time_from_epoch = SystemTime :: now ( )
101+ . duration_since ( UNIX_EPOCH )
102+ // TODO: remove expect
103+ . expect ( "process start time" ) ;
104+ let start_time = ConstGauge :: new ( start_time_from_epoch. as_secs_f64 ( ) ) ;
105+ let start_time_metric = encoder. encode_descriptor (
106+ "process_start_time_seconds" ,
107+ "Start time of the process since unix epoch in seconds." ,
108+ Some ( & Unit :: Seconds ) ,
109+ start_time. metric_type ( ) ,
110+ ) ?;
111+ start_time. encode ( start_time_metric) ?;
112+
56113 Ok ( ( ) )
57114 }
58115}
0 commit comments