metrics_process/
collector.rs

1//! Raw metrics for the running process.
2//!
3//! This module contains the implementation to collect the Prometheus metrics for the
4//! running process.  This can be useful to export these metrics via custom mechanisms
5//! rather than via the [metrics] crate.
6//!
7//! Use the [`collect`] function to create a snapshot of the current metrics.
8//!
9//! To export these metrics via the [metrics] crate however it is recommended to use the
10//! [`Collector`] struct.
11//!
12//! [`Collector`]: crate::Collector
13
14#[cfg_attr(target_os = "macos", path = "implementation/macos.rs")]
15#[cfg_attr(target_os = "linux", path = "implementation/linux.rs")]
16#[cfg_attr(target_os = "windows", path = "implementation/windows.rs")]
17#[cfg_attr(target_os = "freebsd", path = "implementation/freebsd.rs")]
18#[cfg_attr(target_os = "openbsd", path = "implementation/openbsd.rs")]
19#[allow(unused_attributes)]
20#[cfg_attr(feature = "dummy", path = "implementation/dummy.rs")]
21mod implementation;
22
23#[cfg(all(
24    not(feature = "dummy"),
25    not(any(
26        target_os = "macos",
27        target_os = "linux",
28        target_os = "windows",
29        target_os = "freebsd",
30        target_os = "openbsd"
31    ))
32))]
33compile_error!(
34    "A feature \"dummy\" must be enabled to compile this crate on non supported platforms."
35);
36
37/// Creates a snapshot of the running process' [`Metrics`].
38///
39/// Creates a new instance of [`Metrics`] with the current values of the running process.
40pub use implementation::collect;
41
42/// Standard Prometheus process metrics.
43///
44/// This struct describes the standard set of Prometheus process metrics as described at
45/// <https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics>.
46///
47/// To create a populated struct for the running process use the [`collect`] function.  The
48/// `Default` impl does not populate any metrics.
49#[derive(Debug, Default, PartialEq)]
50pub struct Metrics {
51    /// Total user and system CPU time spent in seconds.
52    pub cpu_seconds_total: Option<f64>,
53    /// Number of open file descriptors.
54    pub open_fds: Option<u64>,
55    /// Maximum number of open file descriptors.
56    ///
57    /// 0 indicates 'unlimited'.
58    pub max_fds: Option<u64>,
59    /// Virtual memory size in bytes.
60    pub virtual_memory_bytes: Option<u64>,
61    /// Maximum amount of virtual memory available in bytes.
62    ///
63    /// 0 indicates 'unlimited'.
64    pub virtual_memory_max_bytes: Option<u64>,
65    /// Resident memory size in bytes.
66    pub resident_memory_bytes: Option<u64>,
67    /// Start time of the process since unix epoch in seconds.
68    pub start_time_seconds: Option<u64>,
69    /// Numberof OS threads in the process.
70    pub threads: Option<u64>,
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use assert_matches::assert_matches;
77
78    fn fibonacci(n: u64) -> u64 {
79        match n {
80            0 => 0,
81            1 => 1,
82            _ => fibonacci(n - 2) + fibonacci(n - 1),
83        }
84    }
85
86    #[cfg(any(
87        target_os = "macos",
88        target_os = "linux",
89        target_os = "windows",
90        target_os = "freebsd"
91    ))]
92    #[test]
93    fn test_collect_internal_ok() {
94        fibonacci(40);
95        let m = collect();
96        dbg!(&m);
97        assert_matches!(m.cpu_seconds_total, Some(_));
98        assert_matches!(m.open_fds, Some(_));
99        assert_matches!(m.max_fds, Some(_));
100        assert_matches!(m.virtual_memory_bytes, Some(_));
101        #[cfg(not(target_os = "windows"))]
102        assert_matches!(m.virtual_memory_max_bytes, Some(_)); // maybe 'unlimited'
103        assert_matches!(m.resident_memory_bytes, Some(_));
104        assert_matches!(m.start_time_seconds, Some(_));
105        #[cfg(not(target_os = "windows"))]
106        assert_matches!(m.threads, Some(_));
107    }
108
109    #[cfg(target_os = "openbsd")]
110    #[test]
111    fn test_collect_internal_ok_openbsd() {
112        // TODO: if more metrics is implemented for OpenBSD, merge this test into
113        // test_collect_internal_ok
114        fibonacci(40);
115        let m = collect();
116        dbg!(&m);
117        assert_matches!(m.cpu_seconds_total, Some(_));
118        assert_matches!(m.open_fds, None);
119        assert_matches!(m.max_fds, Some(_));
120        assert_matches!(m.virtual_memory_bytes, None);
121        assert_matches!(m.virtual_memory_max_bytes, None);
122        assert_matches!(m.resident_memory_bytes, Some(_));
123        assert_matches!(m.start_time_seconds, Some(_));
124        assert_matches!(m.threads, None);
125    }
126
127    #[cfg(not(target_os = "macos"))]
128    #[cfg(not(target_os = "linux"))]
129    #[cfg(not(target_os = "windows"))]
130    #[cfg(not(target_os = "freebsd"))]
131    #[cfg(not(target_os = "openbsd"))]
132    #[cfg(feature = "dummy")]
133    #[test]
134    fn test_collect_internal_ok_dummy() {
135        fibonacci(40);
136        let m = collect();
137        dbg!(&m);
138        assert_matches!(m.cpu_seconds_total, None);
139        assert_matches!(m.open_fds, None);
140        assert_matches!(m.max_fds, None);
141        assert_matches!(m.virtual_memory_bytes, None);
142        assert_matches!(m.virtual_memory_max_bytes, None);
143        assert_matches!(m.resident_memory_bytes, None);
144        assert_matches!(m.start_time_seconds, None);
145        assert_matches!(m.threads, None);
146    }
147}