Line data Source code
1 : //! process metrics that the [`::prometheus`] crate doesn't provide.
2 :
3 : // This module has heavy inspiration from the prometheus crate's `process_collector.rs`.
4 :
5 : use once_cell::sync::Lazy;
6 : use prometheus::Gauge;
7 :
8 : use crate::UIntGauge;
9 :
10 : pub struct Collector {
11 : descs: Vec<prometheus::core::Desc>,
12 : vmlck: crate::UIntGauge,
13 : cpu_seconds_highres: Gauge,
14 : }
15 :
16 : const NMETRICS: usize = 2;
17 :
18 0 : static CLK_TCK_F64: Lazy<f64> = Lazy::new(|| {
19 0 : let long = unsafe { libc::sysconf(libc::_SC_CLK_TCK) };
20 0 : if long == -1 {
21 0 : panic!("sysconf(_SC_CLK_TCK) failed");
22 0 : }
23 0 : let convertible_to_f64: i32 =
24 0 : i32::try_from(long).expect("sysconf(_SC_CLK_TCK) is larger than i32");
25 0 : convertible_to_f64 as f64
26 0 : });
27 :
28 : impl prometheus::core::Collector for Collector {
29 0 : fn desc(&self) -> Vec<&prometheus::core::Desc> {
30 0 : self.descs.iter().collect()
31 0 : }
32 :
33 0 : fn collect(&self) -> Vec<prometheus::proto::MetricFamily> {
34 0 : let Ok(myself) = procfs::process::Process::myself() else {
35 0 : return vec![];
36 : };
37 0 : let mut mfs = Vec::with_capacity(NMETRICS);
38 0 : if let Ok(status) = myself.status() {
39 0 : if let Some(vmlck) = status.vmlck {
40 0 : self.vmlck.set(vmlck);
41 0 : mfs.extend(self.vmlck.collect())
42 0 : }
43 0 : }
44 0 : if let Ok(stat) = myself.stat() {
45 0 : let cpu_seconds = stat.utime + stat.stime;
46 0 : self.cpu_seconds_highres
47 0 : .set(cpu_seconds as f64 / *CLK_TCK_F64);
48 0 : mfs.extend(self.cpu_seconds_highres.collect());
49 0 : }
50 0 : mfs
51 0 : }
52 : }
53 :
54 : impl Collector {
55 0 : pub fn new() -> Self {
56 0 : let mut descs = Vec::new();
57 0 :
58 0 : let vmlck =
59 0 : UIntGauge::new("libmetrics_process_status_vmlck", "/proc/self/status vmlck").unwrap();
60 0 : descs.extend(
61 0 : prometheus::core::Collector::desc(&vmlck)
62 0 : .into_iter()
63 0 : .cloned(),
64 0 : );
65 0 :
66 0 : let cpu_seconds_highres = Gauge::new(
67 0 : "libmetrics_process_cpu_seconds_highres",
68 0 : "Total user and system CPU time spent in seconds.\
69 0 : Sub-second resolution, hence better than `process_cpu_seconds_total`.",
70 0 : )
71 0 : .unwrap();
72 0 : descs.extend(
73 0 : prometheus::core::Collector::desc(&cpu_seconds_highres)
74 0 : .into_iter()
75 0 : .cloned(),
76 0 : );
77 0 :
78 0 : Self {
79 0 : descs,
80 0 : vmlck,
81 0 : cpu_seconds_highres,
82 0 : }
83 0 : }
84 : }
85 :
86 : impl Default for Collector {
87 0 : fn default() -> Self {
88 0 : Self::new()
89 0 : }
90 : }
|