Skip to content

Commit dfda475

Browse files
authored
Sub modules (#34)
* collector sub-module is not organized * tinyd is not prof. going with tinycollectd * tests pass * tinyd to tinycollectd in service file
1 parent c51279d commit dfda475

11 files changed

Lines changed: 183 additions & 167 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "tinyd"
2+
name = "tinycollectd"
33
version = "0.1.0"
44
edition = "2024"
55
description = "Everything that collectd gives you but better!"

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# tinycollectd aka tinyd
1+
# tinycollectd
22

33
A lightweight Rust-based tool to collect system metrics (CPU, uptime, disk usage, network stats, and more...) and send them as JSON over UDP at regular intervals.
44

@@ -17,15 +17,15 @@ These are the principles we follow to build better tooling:
1717
## Usage
1818

1919
```bash
20-
Usage: tinyd [OPTIONS]
20+
Usage: tinycollectd [OPTIONS]
2121

2222
Options:
2323
--output <OUTPUT>
2424
output mode (udp, stdout) [default: udp] [possible values: udp, stdout, both]
2525
--destination <DESTINATION>
2626
destination for metrics (e.g. 127.0.0.1:1555) [default: 127.0.0.1:1555]
2727
--metrics <METRICS>
28-
metrics tinyd would collect [default: All] [possible values: all, disk-usage, network, cpufreq, uptime, smart-log]
28+
metrics tinycollectd would collect [default: All] [possible values: all, disk-usage, network, cpufreq, uptime, smart-log]
2929
--services <SERVICES>
3030
list of services to pull status
3131
--collection-interval <COLLECTION_INTERVAL>

service/tinycollectd.service

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[Unit]
2-
Description=tinyd metrics collector
2+
Description=tinycollectd metrics collector
33
After=network.target
44

55
[Service]
66
Type=simple
7-
ExecStart=/usr/sbin/tinyd --metrics All
7+
ExecStart=/usr/sbin/tinycollectd --metrics All
88
Restart=on-failure
99
RestartSec=5
10-
User=tinyd
10+
User=tinycollectd
1111
Group=wheel
1212

1313
[Install]

src/collector/disk.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// src/collector/disk.rs
2+
//! Disk usage metrics.
3+
4+
use serde_json::{Value, json};
5+
use sysinfo::Disks;
6+
7+
/// Function to extract disk usage data.
8+
pub fn get_disk_usage() -> Vec<Value> {
9+
let disks = Disks::new_with_refreshed_list();
10+
11+
disks
12+
.iter()
13+
.map(|disk| {
14+
let total = disk.total_space();
15+
let available = disk.available_space();
16+
let used = total - available;
17+
let used_percent = if total > 0 {
18+
(used as f64 / total as f64) * 100.0
19+
} else {
20+
0.0
21+
};
22+
23+
json!({
24+
"mount": disk.mount_point().to_string_lossy().replace('"', "\\\""),
25+
"total_gb": total / 1_000_000_000,
26+
"used_gb": used / 1_000_000_000,
27+
"used_percent": used_percent
28+
})
29+
})
30+
.collect()
31+
}

src/collector/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// src/collector/mod.rs
2+
3+
pub mod disk;
4+
pub mod net;
5+
pub mod nvme;
6+
pub mod services;
7+
pub mod sys;
8+
9+
pub use sys::{cpu_freq_json, get_hostname, get_sysinfo, get_timestamp, uptime_json};
10+
11+
pub use disk::get_disk_usage;
12+
pub use net::get_if_data;
13+
14+
pub use services::get_service_status;
15+
16+
pub use nvme::{NvmesSmartLog, collect_smart_log, list_nvme_controllers};

src/collector/net.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// src/collector/net.rs
2+
//! Network interface metrics.
3+
4+
use serde_json::{Value, json};
5+
use sysinfo::Networks;
6+
7+
/// Function to extract interface data.
8+
pub fn get_if_data() -> Vec<Value> {
9+
let networks = Networks::new_with_refreshed_list();
10+
11+
networks
12+
.iter()
13+
.map(|(name, data)| {
14+
json!({
15+
"interface": name.replace('"', "\\\""),
16+
"rx_bytes": data.total_received(),
17+
"tx_bytes": data.total_transmitted()
18+
})
19+
})
20+
.collect()
21+
}
Lines changed: 10 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
//! Module to define behavior of sys info collection.
1+
// src/collector/nvme.rs
2+
//! NVMe SMART collection via linux_nvme_sys.
3+
24
use linux_nvme_sys::{nvme_admin_cmd, nvme_admin_opcode::nvme_admin_get_log_page, nvme_smart_log};
35
use serde::Serialize;
4-
use serde_json::{Value, json};
5-
use std::fs;
6-
use std::fs::OpenOptions;
6+
use std::fs::{self, OpenOptions};
77
use std::io;
88
use std::mem::{size_of, zeroed};
99
use std::os::unix::io::AsRawFd;
10-
use std::process::Command;
11-
use sysinfo::{Disks, Networks, System};
1210

1311
// Serialize smart log metrics
1412
#[derive(Debug, Serialize)]
@@ -40,140 +38,17 @@ pub struct NvmesSmartLog {
4038
pub warning_temp_time: Option<u64>,
4139
}
4240

43-
/// Helper function to convert a 16-byte little-endian NVMe counter into u64
41+
/// Function to convert a 16-byte little-endian NVMe counter into u64.
4442
fn le_16_to_u128(bytes: &[u8; 16]) -> u128 {
4543
u128::from_le_bytes(*bytes)
4644
}
4745

48-
/// Helper function to convert a 32-bit little-endian NVMe counter into u64
46+
/// Function to convert a 32-bit little-endian NVMe counter into u64.
4947
fn le32_to_u64(v: linux_nvme_sys::__le32) -> u64 {
5048
u32::from(v) as u64
5149
}
5250

53-
/// Function to get raw uptime.
54-
fn uptime_raw(_sys: &System) -> String {
55-
System::uptime().to_string()
56-
}
57-
58-
/// Function to get raw cpufreq.
59-
fn cpu_freq_raw(sys: &System) -> String {
60-
let cpu_freq = sys.cpus().first().map(|cpu| cpu.frequency()).unwrap_or(0);
61-
cpu_freq.to_string()
62-
}
63-
64-
/// Function to get timestamp
65-
pub fn get_timestamp() -> u64 {
66-
std::time::SystemTime::now()
67-
.duration_since(std::time::UNIX_EPOCH)
68-
.unwrap()
69-
.as_secs()
70-
}
71-
72-
/// Function to get hostname
73-
pub fn get_hostname(_sys: &System) -> String {
74-
System::host_name()
75-
.unwrap_or_else(|| "unknown".to_string())
76-
.replace('"', "\\\"")
77-
}
78-
79-
/// Function to collect system metrics as single json object.
80-
pub fn get_sysinfo(sys: &System) -> Value {
81-
json!({
82-
"timestamp": get_timestamp(),
83-
"hostname": get_hostname(sys),
84-
"uptime": uptime_raw(sys),
85-
"cpu_freq_mhz": cpu_freq_raw(sys),
86-
"disk_usage": get_disk_usage(),
87-
"network": get_if_data(),
88-
"smart_log": collect_smart_log(),
89-
})
90-
}
91-
92-
/// Function to get JSON formatted uptime.
93-
pub fn uptime_json(sys: &System) -> Value {
94-
json!({"uptime": uptime_raw(sys)})
95-
}
96-
97-
/// Function to get JSON formatted cpufreq.
98-
pub fn cpu_freq_json(sys: &System) -> Value {
99-
json!({"cpu_freq_mhz": cpu_freq_raw(sys)})
100-
}
101-
102-
/// Function to get metrics from interfaces.
103-
pub fn get_if_data() -> Vec<Value> {
104-
let networks = Networks::new_with_refreshed_list();
105-
106-
networks
107-
.iter()
108-
.map(|(name, data)| {
109-
json!({
110-
"interface": name.replace('"', "\\\""),
111-
"rx_bytes": data.total_received(),
112-
"tx_bytes": data.total_transmitted()
113-
})
114-
})
115-
.collect()
116-
}
117-
118-
/// Function to get disk usage information.
119-
pub fn get_disk_usage() -> Vec<Value> {
120-
let disks = Disks::new_with_refreshed_list();
121-
122-
disks
123-
.iter()
124-
.map(|disk| {
125-
let total = disk.total_space();
126-
let available = disk.available_space();
127-
let used = total - available;
128-
let used_percent = if total > 0 {
129-
(used as f64 / total as f64) * 100.0
130-
} else {
131-
0.0
132-
};
133-
134-
json!({
135-
"mount": disk.mount_point().to_string_lossy().replace('"', "\\\""),
136-
"total_gb": total / 1_000_000_000,
137-
"used_gb": used / 1_000_000_000,
138-
"used_percent": used_percent
139-
})
140-
})
141-
.collect()
142-
}
143-
144-
/// Function to get status of specific systemd services by name
145-
pub fn get_service_status(services: &[String]) -> Vec<Value> {
146-
let mut results = Vec::new();
147-
148-
for service in services {
149-
let status = get_service_active_status(&service);
150-
151-
let service_status = json!({
152-
"service_name": service,
153-
"status": status
154-
});
155-
156-
results.push(service_status);
157-
}
158-
159-
results
160-
}
161-
162-
/// Get the active status of a service
163-
fn get_service_active_status(service: &str) -> String {
164-
match Command::new("systemctl")
165-
.args(&["is-active", service])
166-
.output()
167-
{
168-
Ok(output) => str::from_utf8(&output.stdout)
169-
.unwrap_or("unknown")
170-
.trim()
171-
.to_string(),
172-
Err(_) => "error".to_string(),
173-
}
174-
}
175-
176-
/// Function to discover controllers exposed on the server
51+
/// Function to discover controllers exposed on the server.
17752
pub fn list_nvme_controllers() -> Vec<String> {
17853
let mut names = Vec::new();
17954

@@ -299,7 +174,7 @@ pub fn list_nvme_controllers() -> Vec<String> {
299174
// results
300175
// }
301176

302-
/// Function to extract smart log through linux-nvme-sys crate
177+
/// Function to extract smart log through linux-nvme-sys crate.
303178
fn smart_log_from_kernel(nvme_name: String, raw: &nvme_smart_log) -> NvmesSmartLog {
304179
// temp is 2 bytes, just join as u16?
305180
let temp = u16::from_le_bytes([raw.temperature[0], raw.temperature[1]]) as u64;
@@ -349,7 +224,7 @@ fn smart_log_from_kernel(nvme_name: String, raw: &nvme_smart_log) -> NvmesSmartL
349224
}
350225
}
351226

352-
/// Get the raw nvme_smart_log from a controller device, e.g. "/dev/nvme0"
227+
/// Function to extract raw nvme_smart_log from a controller.
353228
pub fn get_nvme_smart_log_raw(dev_path: &str) -> io::Result<nvme_smart_log> {
354229
let file = OpenOptions::new()
355230
.read(true)
@@ -394,7 +269,7 @@ pub fn get_nvme_smart_log_raw(dev_path: &str) -> io::Result<nvme_smart_log> {
394269
}
395270
}
396271

397-
/// Function to collect extracted smart log data
272+
/// Function to collect extracted smart log data.
398273
pub fn collect_smart_log() -> Vec<NvmesSmartLog> {
399274
let mut results = Vec::new();
400275
let ctrls = list_nvme_controllers();
@@ -412,6 +287,5 @@ pub fn collect_smart_log() -> Vec<NvmesSmartLog> {
412287
}
413288
}
414289
}
415-
416290
results
417291
}

src/collector/services.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// src/collector/services.rs
2+
//! systemd service status collection.
3+
4+
use serde_json::{Value, json};
5+
use std::process::Command;
6+
use std::str;
7+
8+
/// Function to extract status of a list of services.
9+
pub fn get_service_status(services: &[String]) -> Vec<Value> {
10+
let mut results = Vec::new();
11+
12+
for service in services {
13+
let status = get_service_active_status(service);
14+
15+
results.push(json!({
16+
"service_name": service,
17+
"status": status
18+
}));
19+
}
20+
21+
results
22+
}
23+
24+
/// Function to check whether a service is active or not.
25+
fn get_service_active_status(service: &str) -> String {
26+
match Command::new("systemctl")
27+
.args(["is-active", service])
28+
.output()
29+
{
30+
Ok(output) => str::from_utf8(&output.stdout)
31+
.unwrap_or("unknown")
32+
.trim()
33+
.to_string(),
34+
Err(_) => "error".to_string(),
35+
}
36+
}

0 commit comments

Comments
 (0)