Skip to content

Commit 6c788e3

Browse files
committed
feat: metrics for linux
1 parent bdd6ddc commit 6c788e3

File tree

4 files changed

+97
-37
lines changed

4 files changed

+97
-37
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ default = []
2121
protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build"]
2222

2323
[workspace]
24-
members = ["derive-encode", "process-collector"]
24+
members = ["derive-encode"]
25+
exclude = ["process-collector"]
2526

2627
[dependencies]
2728
dtoa = "1.0"

process-collector/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

process-collector/src/lib.rs

Lines changed: 93 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use procfs::process::Process;
1+
use std::time::{Instant, SystemTime, UNIX_EPOCH};
2+
3+
use procfs::process::{LimitValue, Process};
24
use 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 {
1416
impl 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
}

process-collector/src/linux.rs

Whitespace-only changes.

0 commit comments

Comments
 (0)