Skip to content

Commit 4cd363d

Browse files
authored
refactor: move log startup logic to lib.rs and simplify uname handling (#75)
Cleanup the main function by moving the log initialization and logging of system information to lib.rs as functions. Additionally, the get_kernel_version and get_architecture functions from the host_info module have been replaced with a SystemInfo type. This means the underlying LazyLock<HashMap> that was originally used is no longer needed, the caller can decide what the lifetime of the object should be and, therefore, we don't need to hang on to that information for the entire time fact is running. Finally, the hostname has also been added to the list of information being logged at start up.
1 parent 9083ef9 commit 4cd363d

3 files changed

Lines changed: 66 additions & 72 deletions

File tree

fact/src/host_info.rs

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::bail;
12
use log::{debug, warn};
23
use std::{
34
collections::HashMap,
@@ -147,50 +148,32 @@ pub fn get_distro() -> String {
147148
String::from("Linux")
148149
}
149150

150-
const RELEASE: &str = "release";
151-
const MACHINE: &str = "machine";
151+
pub struct SystemInfo {
152+
pub kernel: String,
153+
pub arch: String,
154+
}
152155

153-
/// Retrieve information about the kernel
154-
///
155-
/// The kernel information is retrieved by lazily calling `uname` and
156-
/// storing the information we care about in a hash map. This is not
157-
/// ideal, since the LazyLock<HashMap> will live for the entirety of
158-
/// the program's life, but the stored data is hopefully small enough
159-
/// that not calling `uname` repeatedly makes up for it.
160-
fn get_kernel_value(key: &str) -> Option<&String> {
161-
static KERNEL_DATA: LazyLock<HashMap<&str, String>> = LazyLock::new(|| {
162-
let mut map = HashMap::new();
163-
let kernel_data = unsafe {
156+
impl SystemInfo {
157+
pub fn new() -> anyhow::Result<Self> {
158+
let system_info = unsafe {
164159
let mut info = mem::zeroed();
165160
let res = uname(&mut info);
166161
if res != 0 {
167-
warn!("Failed to execute uname: {res}");
168-
return map;
162+
bail!(
163+
"Failed to execute uname: {}",
164+
std::io::Error::last_os_error()
165+
);
169166
}
170167
info
171168
};
172169

173-
let release = unsafe { CStr::from_ptr(kernel_data.release.as_ptr()).to_str() };
174-
if let Ok(release) = release {
175-
map.insert(RELEASE, release.to_owned());
176-
}
177-
let machine = unsafe { CStr::from_ptr(kernel_data.machine.as_ptr()).to_str() };
178-
if let Ok(machine) = machine {
179-
map.insert(MACHINE, machine.to_owned());
180-
}
181-
182-
map
183-
});
170+
let kernel = unsafe { CStr::from_ptr(system_info.release.as_ptr()) }
171+
.to_string_lossy()
172+
.to_string();
173+
let arch = unsafe { CStr::from_ptr(system_info.machine.as_ptr()) }
174+
.to_string_lossy()
175+
.to_string();
184176

185-
KERNEL_DATA.get(key)
186-
}
187-
188-
/// Same as `uname -r`
189-
pub fn get_kernel_version() -> &'static str {
190-
get_kernel_value(RELEASE).map_or("", |s| s.as_str())
191-
}
192-
193-
/// Same as `uname -m`
194-
pub fn get_architecture() -> &'static str {
195-
get_kernel_value(MACHINE).map_or("", |s| s.as_str())
177+
Ok(SystemInfo { kernel, arch })
178+
}
196179
}

fact/src/lib.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
use std::{io::Write, str::FromStr};
2+
13
use anyhow::Context;
24
use bpf::Bpf;
3-
use log::{debug, info};
5+
use host_info::{get_distro, get_hostname, SystemInfo};
6+
use log::{debug, info, warn, LevelFilter};
47
use metrics::exporter::Exporter;
58
use output::Output;
69
use tokio::{
@@ -13,14 +16,52 @@ pub mod config;
1316
mod event;
1417
mod grpc;
1518
mod health_check;
16-
pub mod host_info;
19+
mod host_info;
1720
mod metrics;
1821
mod output;
1922
mod pre_flight;
2023

2124
use config::FactConfig;
2225
use pre_flight::pre_flight;
2326

27+
pub fn init_log() -> anyhow::Result<()> {
28+
let log_level = std::env::var("FACT_LOGLEVEL").unwrap_or("info".to_owned());
29+
let log_level = LevelFilter::from_str(&log_level)?;
30+
env_logger::Builder::new()
31+
.filter_level(log_level)
32+
.format(move |buf, record| {
33+
write!(buf, "[{:<5} {}] ", record.level(), buf.timestamp_seconds())?;
34+
if matches!(log_level, LevelFilter::Debug | LevelFilter::Trace) {
35+
write!(
36+
buf,
37+
"({}:{}) ",
38+
record.file().unwrap_or_default(),
39+
record.line().unwrap_or_default()
40+
)?;
41+
}
42+
writeln!(buf, "{}", record.args())
43+
})
44+
.init();
45+
Ok(())
46+
}
47+
48+
mod version {
49+
include!(concat!(env!("OUT_DIR"), "/version.rs"));
50+
}
51+
52+
pub fn log_system_information() {
53+
info!("fact version: {}", version::FACT_VERSION);
54+
info!("OS: {}", get_distro());
55+
match SystemInfo::new() {
56+
Ok(sysinfo) => {
57+
info!("Kernel version: {}", sysinfo.kernel);
58+
info!("Architecture: {}", sysinfo.arch);
59+
}
60+
Err(e) => warn!("Failed to get system information: {e}"),
61+
}
62+
info!("Hostname: {}", get_hostname());
63+
}
64+
2465
pub async fn run(config: FactConfig) -> anyhow::Result<()> {
2566
let (run_tx, run_rx) = watch::channel(true);
2667
let (tx, rx) = broadcast::channel(100);

fact/src/main.rs

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,12 @@
1-
use std::io::Write;
2-
use std::str::FromStr;
3-
4-
use fact::{
5-
config::FactConfig,
6-
host_info::{get_architecture, get_distro, get_kernel_version},
7-
};
8-
use log::{info, LevelFilter};
9-
10-
mod version {
11-
include!(concat!(env!("OUT_DIR"), "/version.rs"));
12-
}
1+
use fact::config::FactConfig;
132

143
#[tokio::main]
154
async fn main() -> anyhow::Result<()> {
16-
let log_level = std::env::var("FACT_LOGLEVEL").unwrap_or("info".to_owned());
17-
let log_level = LevelFilter::from_str(&log_level)?;
18-
env_logger::Builder::new()
19-
.filter_level(log_level)
20-
.format(move |buf, record| {
21-
write!(buf, "[{:<5} {}] ", record.level(), buf.timestamp_seconds())?;
22-
if matches!(log_level, LevelFilter::Debug | LevelFilter::Trace) {
23-
write!(
24-
buf,
25-
"({}:{}) ",
26-
record.file().unwrap_or_default(),
27-
record.line().unwrap_or_default()
28-
)?;
29-
}
30-
writeln!(buf, "{}", record.args())
31-
})
32-
.init();
5+
fact::init_log()?;
336

347
// Log system information as early as possible so we have it
358
// available in case of a crash
36-
info!("fact version: {}", version::FACT_VERSION);
37-
info!("OS: {}", get_distro());
38-
info!("Kernel version: {}", get_kernel_version());
39-
info!("Architecture: {}", get_architecture());
9+
fact::log_system_information();
4010

4111
let config = FactConfig::new(&[
4212
"/etc/stackrox/fact.yml",

0 commit comments

Comments
 (0)