diff --git a/Cargo.toml b/Cargo.toml index 5514ab6..40f60c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,13 @@ authors = ["Max Inden "] edition = "2021" description = "Open Metrics client library allowing users to natively instrument applications." license = "Apache-2.0 OR MIT" -keywords = ["openmetrics", "prometheus", "metrics", "instrumentation", "monitoring"] +keywords = [ + "openmetrics", + "prometheus", + "metrics", + "instrumentation", + "monitoring", +] repository = "https://github.com/prometheus/client_rust" homepage = "https://github.com/prometheus/client_rust" documentation = "https://docs.rs/prometheus-client" @@ -15,7 +21,7 @@ default = [] protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build"] [workspace] -members = ["derive-encode"] +members = ["derive-encode", "process-collector"] [dependencies] dtoa = "1.0" @@ -35,7 +41,12 @@ quickcheck = "1" rand = "0.8.4" tide = "0.16" actix-web = "4" -tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "signal"] } +tokio = { version = "1", features = [ + "rt-multi-thread", + "net", + "macros", + "signal", +] } hyper = { version = "1.3.1", features = ["server", "http1"] } hyper-util = { version = "0.1.3", features = ["tokio"] } http-body-util = "0.1.1" diff --git a/process-collector/Cargo.toml b/process-collector/Cargo.toml new file mode 100644 index 0000000..c90952b --- /dev/null +++ b/process-collector/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "process-collector" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +procfs = "0.17.0" +prometheus-client = { path = "../" } diff --git a/process-collector/src/lib.rs b/process-collector/src/lib.rs new file mode 100644 index 0000000..1598609 --- /dev/null +++ b/process-collector/src/lib.rs @@ -0,0 +1,72 @@ +use procfs::process::Process; +use prometheus_client::{ + collector::Collector, + encoding::{DescriptorEncoder, EncodeMetric}, + metrics::counter::ConstCounter, + registry::Unit, +}; + +#[derive(Debug)] +pub struct ProcessCollector { + namespace: String, +} + +impl Collector for ProcessCollector { + fn encode(&self, mut encoder: DescriptorEncoder) -> Result<(), std::fmt::Error> { + let tps = procfs::ticks_per_second(); + // process_cpu_seconds_total Total user and system CPU time spent in seconds. + // process_max_fds Maximum number of open file descriptors. + // process_open_fds Number of open file descriptors. + // process_virtual_memory_bytes Virtual memory size in bytes. + // process_resident_memory_bytes Resident memory size in bytes. + // process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes. + // process_start_time_seconds Start time of the process since unix epoch in seconds. + // process_network_receive_bytes_total Number of bytes received by the process over the network. + // process_network_transmit_bytes_total Number of bytes sent by the process over the network. + + if let Ok(proc) = Process::myself() { + if let Ok(stat) = proc.stat() { + let cpu_time = (stat.stime + stat.utime) / tps as u64; + let counter = ConstCounter::new(cpu_time); + let metric_encoder = encoder.encode_descriptor( + "process_cpu_seconds_total", + "Total user and system CPU time spent in seconds.", + Some(&Unit::Seconds), + counter.metric_type(), + )?; + counter.encode(metric_encoder)?; + } + + if let Ok(limits) = proc.limits() { + let max_fds = match limits.max_open_files.soft_limit { + procfs::process::LimitValue::Value(v) => v, + procfs::process::LimitValue::Unlimited => 0, + }; + let counter = ConstCounter::new(max_fds); + let metric_encoder = encoder.encode_descriptor( + "process_max_fds", + "Maximum number of open file descriptors.", + None, + counter.metric_type(), + )?; + counter.encode(metric_encoder)?; + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use prometheus_client::registry::Registry; + + #[test] + fn register_process_collector() { + let mut registry = Registry::default(); + registry.register_collector(Box::new(ProcessCollector { + namespace: String::new(), + })) + } +}