Skip to content

Commit

Permalink
feat: metrics for linux
Browse files Browse the repository at this point in the history
  • Loading branch information
gmurayama committed Oct 22, 2024
1 parent bdd6ddc commit 6c788e3
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 37 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ default = []
protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build"]

[workspace]
members = ["derive-encode", "process-collector"]
members = ["derive-encode"]
exclude = ["process-collector"]

[dependencies]
dtoa = "1.0"
Expand Down
2 changes: 2 additions & 0 deletions process-collector/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
129 changes: 93 additions & 36 deletions process-collector/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use procfs::process::Process;
use std::time::{Instant, SystemTime, UNIX_EPOCH};

use procfs::process::{LimitValue, Process};
use prometheus_client::{
collector::Collector,
encoding::{DescriptorEncoder, EncodeMetric},
metrics::counter::ConstCounter,
metrics::{counter::ConstCounter, gauge::ConstGauge},
registry::Unit,
};

Expand All @@ -14,45 +16,100 @@ pub struct ProcessCollector {
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)?;
// TODO: handle errors
let proc = match Process::myself() {
Ok(proc) => proc,
Err(_) => {
return Ok(());
}

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)?;
};
let stat = match proc.stat() {
Ok(stat) => stat,
Err(_) => {
return Ok(());
}
};

let cpu_time = (stat.stime + stat.utime) / tps;
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_open_files = limits.max_open_files;
let max_fds = match max_open_files.soft_limit {
LimitValue::Unlimited => match max_open_files.hard_limit {
LimitValue::Unlimited => 0,
LimitValue::Value(hard) => hard,
},
LimitValue::Value(soft) => soft,
};
let gauge = ConstGauge::new(max_fds as i64);
let metric_encoder = encoder.encode_descriptor(
"process_max_fds",
"Maximum number of open file descriptors.",
None,
gauge.metric_type(),
)?;
gauge.encode(metric_encoder)?;

let max_address_space = limits.max_address_space;
let max_virtual_memory = match max_address_space.soft_limit {
LimitValue::Unlimited => match max_address_space.hard_limit {
LimitValue::Unlimited => 0,
LimitValue::Value(hard) => hard,
},
LimitValue::Value(soft) => soft,
};
let gauge = ConstGauge::new(max_fds as i64);
let metric_encoder = encoder.encode_descriptor(
"process_virtual_memory_max_bytes",
"Maximum amount of virtual memory available in bytes.",
None,
gauge.metric_type(),
)?;
gauge.encode(metric_encoder)?;
}

let vm_bytes = ConstGauge::new(stat.vsize as i64);
let vme = encoder.encode_descriptor(
"process_virtual_memory_bytes",
"Virtual memory size in bytes",
Some(&Unit::Bytes),
vm_bytes.metric_type(),
)?;
vm_bytes.encode(vme)?;

// TODO: add rss_bytes (fix self.page_size)
//
// let rss_bytes = ConstGauge::new((stat.rss * self.page_size) as i64);
// let rsse = encoder.encode_descriptor(
// "process_resident_memory_bytes",
// "Resident memory size in bytes.",
// Some(&Unit::Bytes),
// rss_bytes.metric_type(),
// )?;
// rss_bytes.encode(rsse)?;

let start_time_from_epoch = SystemTime::now()
.duration_since(UNIX_EPOCH)
// TODO: remove expect
.expect("process start time");
let start_time = ConstGauge::new(start_time_from_epoch.as_secs_f64());
let start_time_metric = encoder.encode_descriptor(
"process_start_time_seconds",
"Start time of the process since unix epoch in seconds.",
Some(&Unit::Seconds),
start_time.metric_type(),
)?;
start_time.encode(start_time_metric)?;

Ok(())
}
}
Expand Down
Empty file added process-collector/src/linux.rs
Empty file.

0 comments on commit 6c788e3

Please sign in to comment.