diff --git a/Cargo.lock b/Cargo.lock index 9727854..2160e31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,11 +126,23 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hostname" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + [[package]] name = "ibtop" -version = "0.1.5" +version = "0.1.7" dependencies = [ "crossterm", + "hostname", "rand", "ratatui", "serde", @@ -531,6 +543,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 22674c6..ae1a3c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibtop" -version = "0.1.5" +version = "0.1.7" edition = "2021" authors = ["info@jannik-straube.de"] description = "Real-time terminal monitor for InfiniBand networks" @@ -17,6 +17,7 @@ crossterm = "0.27" rand = "0.9.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +hostname = "0.4" [lints.clippy] pedantic = "deny" \ No newline at end of file diff --git a/ibtop b/ibtop new file mode 100644 index 0000000..e0209f0 Binary files /dev/null and b/ibtop differ diff --git a/src/main.rs b/src/main.rs index b374a64..d29fefb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,13 @@ use std::time::{Duration, Instant}; const UI_REFRESH_INTERVAL_MS: u64 = 33; const METRICS_UPDATE_INTERVAL_MS: u64 = 250; +fn get_hostname() -> String { + hostname::get().map_or_else( + |_| "unknown".to_string(), + |h| h.to_string_lossy().into_owned(), + ) +} + fn main() -> Result<(), io::Error> { let args: Vec = env::args().collect(); let json_mode = args.contains(&String::from("--json")); @@ -41,7 +48,11 @@ fn run_json_mode() -> Result<(), io::Error> { } }; - let json_output = serde_json::to_string_pretty(&adapters)?; + let output = types::IbtopOutput { + hostname: get_hostname(), + adapters, + }; + let json_output = serde_json::to_string_pretty(&output)?; println!("{json_output}"); Ok(()) @@ -74,6 +85,7 @@ fn run_interactive_mode() -> Result<(), io::Error> { fn run_app(terminal: &mut Terminal) -> io::Result<()> { let use_fake_data = std::env::var("IBTOP_FAKE_DATA").is_ok(); let mut metrics = metrics::MetricsCollector::new(); + let hostname = get_hostname(); let ui_refresh_duration = Duration::from_millis(UI_REFRESH_INTERVAL_MS); let metrics_update_interval = Duration::from_millis(METRICS_UPDATE_INTERVAL_MS); @@ -100,7 +112,7 @@ fn run_app(terminal: &mut Terminal) -> io::Resu last_metrics_update = now; } - terminal.draw(|f| ui::draw(f, &adapters, &metrics))?; + terminal.draw(|f| ui::draw(f, &adapters, &metrics, &hostname))?; let timeout = ui_refresh_duration.saturating_sub(now.elapsed()); if event::poll(timeout)? { diff --git a/src/types.rs b/src/types.rs index c7034aa..9cc8ee6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,6 +2,12 @@ use serde::{Deserialize, Serialize}; use std::fmt::Display; use std::str::FromStr; +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct IbtopOutput { + pub(crate) hostname: String, + pub(crate) adapters: Vec, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] pub(crate) enum PortState { Active, diff --git a/src/ui.rs b/src/ui.rs index b59ae54..785ed43 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -8,7 +8,12 @@ use ratatui::{ use crate::metrics::MetricsCollector; use crate::types::AdapterInfo; -pub fn draw(frame: &mut Frame, adapters: &[AdapterInfo], metrics: &MetricsCollector) { +pub fn draw( + frame: &mut Frame, + adapters: &[AdapterInfo], + metrics: &MetricsCollector, + hostname: &str, +) { let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ @@ -18,7 +23,7 @@ pub fn draw(frame: &mut Frame, adapters: &[AdapterInfo], metrics: &MetricsCollec ]) .split(frame.size()); - draw_adapters(frame, chunks[1], adapters, metrics); + draw_adapters(frame, chunks[1], adapters, metrics, hostname); draw_help_footer(frame, chunks[2]); } @@ -33,6 +38,7 @@ fn draw_adapters( area: Rect, adapters: &[AdapterInfo], metrics: &MetricsCollector, + hostname: &str, ) { let mut rows: Vec = Vec::new(); @@ -45,7 +51,7 @@ fn draw_adapters( // Add adapter header row that spans the full width rows.push(Row::new(vec![ Cell::from("Adapter:"), - Cell::from(adapter.name.to_string()).style( + Cell::from(adapter.name.clone()).style( Style::default() .fg(Color::Green) .add_modifier(Modifier::BOLD), @@ -141,7 +147,7 @@ fn draw_adapters( .block( Block::default() .borders(Borders::ALL) - .title("ibtop - InfiniBand Monitor"), + .title(format!("ibtop - InfiniBand Monitor @ {hostname}")), ); frame.render_widget(table, area);