Skip to content

Commit 3f544fd

Browse files
committed
Split SystemInformation into modules, add logging
Fixes #6
1 parent a9eb02b commit 3f544fd

File tree

8 files changed

+363
-215
lines changed

8 files changed

+363
-215
lines changed

src/main.rs

Lines changed: 10 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
mod system_information;
22

33
use clap::Parser;
4-
use local_ip_address::list_afinet_netifas;
5-
use std::collections::{HashMap, HashSet};
64
use std::path::PathBuf;
7-
use sysinfo::{Disks, System};
85

9-
use crate::system_information::{SystemInformation, SystemNetworkInfo};
10-
use hickory_resolver::system_conf::read_system_conf;
11-
use hickory_resolver::Resolver;
12-
use std::net::IpAddr;
13-
use std::time::{Duration, Instant};
6+
use crate::system_information::SystemInformation;
7+
use std::time::Instant;
148

159
/// Collects and prints helpful debugging information about the environment that it is running in.
1610
#[derive(clap::Parser)]
@@ -36,161 +30,23 @@ fn main() {
3630

3731
let mut next_run = Instant::now();
3832
loop {
39-
std::thread::sleep(next_run.saturating_duration_since(Instant::now()));
40-
41-
tracing::info!("starting run");
42-
43-
// Please note that we use "new_all" to ensure that all list of
44-
// components, network interfaces, disks and users are already
45-
// filled!
46-
let sys = System::new_all();
47-
48-
let disks = Disks::new_with_refreshed_list();
49-
let disks = disks
50-
.into_iter()
51-
.map(system_information::Disk::from)
52-
.collect();
53-
54-
let system_network_information = get_network_info();
55-
56-
let current_uid = users::get_current_uid();
57-
let current_gid = users::get_current_gid();
58-
let current_user = users::get_user_by_uid(current_uid).unwrap();
59-
60-
let system_information = SystemInformation {
61-
cpu_count: sys.cpus().len(),
62-
physical_core_count: sys.physical_core_count(),
63-
64-
total_memory: sys.total_memory(),
65-
free_memory: sys.free_memory(),
66-
available_memory: sys.available_memory(),
67-
used_memory: sys.used_memory(),
68-
69-
total_swap: sys.total_swap(),
70-
free_swap: sys.free_swap(),
71-
used_swap: sys.used_swap(),
72-
73-
total_memory_cgroup: sys.cgroup_limits().map(|limit| limit.total_memory),
74-
free_memory_cgroup: sys.cgroup_limits().map(|limit| limit.free_memory),
75-
free_swap_cgroup: sys.cgroup_limits().map(|limit| limit.free_swap),
76-
77-
system_name: System::name(),
78-
kernel_version: System::kernel_version(),
79-
os_version: System::long_os_version(),
80-
host_name: System::host_name(),
81-
cpu_arch: System::cpu_arch(),
82-
83-
disks,
84-
85-
network_information: system_network_information,
33+
let next_run_sleep = next_run.saturating_duration_since(Instant::now());
34+
if !next_run_sleep.is_zero() {
35+
tracing::info!(?next_run, "scheduling next run...");
36+
}
37+
std::thread::sleep(next_run_sleep);
8638

87-
// Adding current user, UID, and GID info
88-
current_user: current_user.name().to_str().unwrap().to_string(),
89-
current_uid,
90-
current_gid,
91-
};
39+
let system_information = SystemInformation::collect();
9240

9341
let serialized = serde_json::to_string_pretty(&system_information).unwrap();
94-
println!("{}", serialized);
42+
// println!("{serialized}");
9543
if let Some(output_path) = &opts.output {
9644
std::fs::write(output_path, &serialized).unwrap();
9745
}
9846

99-
// TODO:
100-
// Current time
101-
// SElinux/AppArmor
102-
// Maybe env variables (may contain secrets)
103-
// dmesg/syslog?
104-
// capabilities?
105-
// downward API
106-
// Somehow get the custom resources logged?
107-
108-
// Things left out for now because it doesn't seem too useful:
109-
// - Running processes
110-
// - Uptime/boot time
111-
// - Load average
112-
// - Network utilization
113-
// - Users/Groups
114-
11547
match opts.loop_interval {
116-
Some(interval) => {
117-
next_run += interval;
118-
tracing::info!(?next_run, "run completed, scheduling next...");
119-
}
48+
Some(interval) => next_run += interval,
12049
None => break,
12150
}
12251
}
12352
}
124-
125-
fn get_network_info() -> SystemNetworkInfo {
126-
/*
127-
let resolver = Resolver::from_system_conf()
128-
.map_err(|e| e.to_string())
129-
.unwrap();
130-
*/
131-
let (resolver_config, mut resolver_opts) = read_system_conf().unwrap();
132-
resolver_opts.timeout = Duration::from_secs(5);
133-
let resolver = Resolver::new(resolver_config, resolver_opts).unwrap();
134-
135-
let interfaces = match list_afinet_netifas() {
136-
Ok(netifs) => {
137-
let mut interface_map = std::collections::HashMap::new();
138-
139-
// Iterate over the network interfaces and group them by name
140-
// An interface may appear multiple times if it has multiple IP addresses (e.g. IPv4 and IPv6)
141-
for (name, ip_addr) in netifs {
142-
interface_map
143-
.entry(name)
144-
.or_insert_with(Vec::new)
145-
.push(ip_addr);
146-
}
147-
interface_map
148-
}
149-
Err(_) => HashMap::new(),
150-
};
151-
152-
let mut ip_set: HashSet<IpAddr> = HashSet::new();
153-
for (_, ip_addrs) in interfaces.iter() {
154-
for ip_addr in ip_addrs {
155-
ip_set.insert(*ip_addr);
156-
}
157-
}
158-
159-
let mut reverse_lookups = HashMap::new();
160-
for ip in ip_set {
161-
if let Ok(result) = resolver.reverse_lookup(ip) {
162-
for ptr_record in result {
163-
let hostname = ptr_record.to_utf8();
164-
reverse_lookups
165-
.entry(ip)
166-
.or_insert_with(Vec::new)
167-
.push(hostname);
168-
}
169-
}
170-
}
171-
172-
let mut hostname_set: HashSet<String> = HashSet::new();
173-
for (_, hostnames) in reverse_lookups.iter() {
174-
for hostname in hostnames {
175-
hostname_set.insert(hostname.clone());
176-
}
177-
}
178-
179-
let mut forward_lookups = HashMap::new();
180-
for hostname in hostname_set {
181-
if let Ok(result) = resolver.lookup_ip(hostname.clone()) {
182-
for ip_addr in result {
183-
forward_lookups
184-
.entry(hostname.clone())
185-
.or_insert_with(Vec::new)
186-
.push(ip_addr);
187-
}
188-
}
189-
}
190-
191-
SystemNetworkInfo {
192-
network_interfaces: interfaces,
193-
reverse_lookups,
194-
forward_lookups,
195-
}
196-
}

src/system_information.rs

Lines changed: 0 additions & 61 deletions
This file was deleted.

src/system_information/disk.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use serde::Serialize;
2+
3+
#[derive(Debug, Serialize)]
4+
pub struct Disk {
5+
pub name: String,
6+
pub mount_point: String,
7+
pub total_space: u64,
8+
pub available_space: u64,
9+
}
10+
11+
impl Disk {
12+
#[tracing::instrument(name = "Disk::collect_all")]
13+
pub fn collect_all() -> Vec<Self> {
14+
let disks = sysinfo::Disks::new_with_refreshed_list();
15+
if disks.into_iter().next().is_none() {
16+
tracing::info!("no disks found");
17+
}
18+
disks.into_iter().map(Self::from).collect()
19+
}
20+
}
21+
22+
impl From<&sysinfo::Disk> for Disk {
23+
fn from(sysinfo_disk: &sysinfo::Disk) -> Self {
24+
let disk = Disk {
25+
name: sysinfo_disk.name().to_string_lossy().into_owned(),
26+
mount_point: sysinfo_disk.mount_point().to_string_lossy().into_owned(),
27+
total_space: sysinfo_disk.total_space(),
28+
available_space: sysinfo_disk.available_space(),
29+
};
30+
tracing::info!(
31+
disk.mount_point,
32+
disk.name,
33+
disk.space.total = disk.total_space,
34+
disk.space.available = disk.available_space,
35+
"found disk"
36+
);
37+
disk
38+
}
39+
}

src/system_information/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use serde::Serialize;
2+
3+
pub mod disk;
4+
pub mod network;
5+
pub mod os;
6+
pub mod resources;
7+
pub mod user;
8+
9+
#[derive(Debug, Serialize)]
10+
pub struct SystemInformation {
11+
pub resources: resources::Resources,
12+
pub os: os::OperatingSystem,
13+
pub current_user: user::User,
14+
pub disks: Vec<disk::Disk>,
15+
pub network: network::SystemNetworkInfo,
16+
// TODO:
17+
// Current time
18+
// SElinux/AppArmor
19+
// Maybe env variables (may contain secrets)
20+
// dmesg/syslog?
21+
// capabilities?
22+
// downward API
23+
// Somehow get the custom resources logged?
24+
25+
// Things left out for now because it doesn't seem too useful:
26+
// - Running processes
27+
// - Uptime/boot time
28+
// - Load average
29+
// - Network utilization
30+
// - Users/Groups
31+
}
32+
33+
impl SystemInformation {
34+
#[tracing::instrument(name = "SystemInformation::collect")]
35+
pub fn collect() -> Self {
36+
tracing::info!("Starting data collection");
37+
let info = Self {
38+
resources: resources::Resources::collect(),
39+
os: os::OperatingSystem::collect(),
40+
current_user: user::User::collect_current(),
41+
disks: disk::Disk::collect_all(),
42+
network: network::SystemNetworkInfo::collect(),
43+
};
44+
tracing::info!("Data collection finished");
45+
info
46+
}
47+
}

0 commit comments

Comments
 (0)