# Socktop Connector Library The `socktop_connector` library provides a high-level interface for connecting to socktop agents programmatically. ## Overview The connector library allows you to: - **Build custom monitoring tools** - Create your own dashboards and UIs - **Integrate with existing systems** - Add socktop metrics to your applications - **Automate monitoring** - Script-based system checks and alerts - **WASM support** - Use in browser-based applications ## Installation Add to your `Cargo.toml`: ```toml [dependencies] socktop_connector = "1.50" tokio = { version = "1", features = ["full"] } ``` ## Quick Start ### Basic Connection ```rust use socktop_connector::{connect_to_socktop_agent, AgentRequest, AgentResponse}; #[tokio::main] async fn main() -> Result<(), Box> { // Connect to agent let mut connector = connect_to_socktop_agent("ws://localhost:3000/ws").await?; // Request metrics if let Ok(AgentResponse::Metrics(metrics)) = connector.request(AgentRequest::Metrics).await { println!("Hostname: {}", metrics.hostname); println!("CPU Usage: {:.1}%", metrics.cpu_total); println!("Memory: {:.1} GB / {:.1} GB", metrics.mem_used as f64 / 1_000_000_000.0, metrics.mem_total as f64 / 1_000_000_000.0); } Ok(()) } ``` ### With TLS ```rust use socktop_connector::connect_to_socktop_agent_with_tls; #[tokio::main] async fn main() -> Result<(), Box> { let connector = connect_to_socktop_agent_with_tls( "wss://secure-host:3000/ws", "/path/to/ca.pem", false // Enable hostname verification ).await?; // Use connector... Ok(()) } ``` ## Request Types The connector supports several request types: ### Metrics Request Get comprehensive system metrics: ```rust use socktop_connector::{AgentRequest, AgentResponse}; match connector.request(AgentRequest::Metrics).await { Ok(AgentResponse::Metrics(metrics)) => { println!("CPU Total: {:.1}%", metrics.cpu_total); // Per-core usage for (i, usage) in metrics.cpu_per_core.iter().enumerate() { println!("Core {}: {:.1}%", i, usage); } // CPU temperature if let Some(temp) = metrics.cpu_temp_c { println!("CPU Temperature: {:.1}°C", temp); } // Memory println!("Memory Used: {} bytes", metrics.mem_used); println!("Memory Total: {} bytes", metrics.mem_total); // Swap println!("Swap Used: {} bytes", metrics.swap_used); println!("Swap Total: {} bytes", metrics.swap_total); // Network interfaces for net in &metrics.networks { println!("Interface {}: ↓{} ↑{}", net.name, net.received, net.transmitted); } // GPU information if let Some(gpus) = &metrics.gpus { for gpu in gpus { if let Some(name) = &gpu.name { println!("GPU: {}", name); println!(" Utilization: {:.1}%", gpu.utilization.unwrap_or(0.0)); if let Some(temp) = gpu.temp { println!(" Temperature: {:.1}°C", temp); } } } } } Err(e) => eprintln!("Error: {}", e), _ => unreachable!(), } ``` ### Process Request Get process information: ```rust match connector.request(AgentRequest::Processes).await { Ok(AgentResponse::Processes(processes)) => { println!("Total processes: {}", processes.process_count); for proc in &processes.top_processes { println!("PID {}: {} - CPU: {:.1}%, Mem: {} MB", proc.pid, proc.name, proc.cpu_usage, proc.mem_bytes / 1_000_000); } } Err(e) => eprintln!("Error: {}", e), _ => unreachable!(), } ``` ### Disk Request Get disk information: ```rust match connector.request(AgentRequest::Disks).await { Ok(AgentResponse::Disks(disks)) => { for disk in disks { let used = disk.total - disk.available; let used_gb = used as f64 / 1_000_000_000.0; let total_gb = disk.total as f64 / 1_000_000_000.0; let percent = (used as f64 / disk.total as f64) * 100.0; println!("Disk {}: {:.1} GB / {:.1} GB ({:.1}%)", disk.name, used_gb, total_gb, percent); } } Err(e) => eprintln!("Error: {}", e), _ => unreachable!(), } ``` ## Continuous Monitoring Monitor metrics in a loop: ```rust use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() -> Result<(), Box> { let mut connector = connect_to_socktop_agent("ws://localhost:3000/ws").await?; loop { match connector.request(AgentRequest::Metrics).await { Ok(AgentResponse::Metrics(metrics)) => { println!("CPU: {:.1}%, Memory: {:.1}%", metrics.cpu_total, (metrics.mem_used as f64 / metrics.mem_total as f64) * 100.0 ); } Err(e) => { eprintln!("Connection error: {}", e); break; } _ => unreachable!(), } sleep(Duration::from_secs(2)).await; } Ok(()) } ``` ## Advanced Usage ### Custom Configuration ```rust use socktop_connector::{ConnectorConfig, SocktopConnector}; let config = ConnectorConfig { url: "ws://server:3000/ws".to_string(), token: Some("secret-token".to_string()), ca_cert_path: Some("/path/to/ca.pem".to_string()), verify_tls: true, }; let connector = SocktopConnector::connect_with_config(config).await?; ``` ### Error Handling ```rust use socktop_connector::{ConnectorError, Result}; async fn monitor() -> Result<()> { let mut connector = connect_to_socktop_agent("ws://server:3000/ws").await?; match connector.request(AgentRequest::Metrics).await { Ok(response) => { // Handle response Ok(()) } Err(ConnectorError::ConnectionClosed) => { eprintln!("Connection closed, attempting reconnect..."); Err(ConnectorError::ConnectionClosed) } Err(e) => { eprintln!("Error: {}", e); Err(e) } } } ``` ## WASM Support The connector supports WebAssembly for browser usage: ```toml [dependencies] socktop_connector = { version = "1.50", features = ["wasm"] } ``` ```rust use socktop_connector::connect_to_socktop_agent; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub async fn monitor_system(url: String) -> Result { let mut connector = connect_to_socktop_agent(&url) .await .map_err(|e| JsValue::from_str(&e.to_string()))?; match connector.request(AgentRequest::Metrics).await { Ok(AgentResponse::Metrics(metrics)) => { Ok(JsValue::from_str(&format!("CPU: {:.1}%", metrics.cpu_total))) } Err(e) => Err(JsValue::from_str(&e.to_string())), _ => Err(JsValue::from_str("Unexpected response")), } } ``` ## Building Custom Applications ### Example: Simple Dashboard ```rust use socktop_connector::*; use tokio::time::{interval, Duration}; #[tokio::main] async fn main() -> Result<(), Box> { let servers = vec![ ("web", "ws://web.example.com:3000/ws"), ("db", "ws://db.example.com:3000/ws"), ("cache", "ws://cache.example.com:3000/ws"), ]; let mut connectors = Vec::new(); for (name, url) in servers { match connect_to_socktop_agent(url).await { Ok(conn) => connectors.push((name, conn)), Err(e) => eprintln!("Failed to connect to {}: {}", name, e), } } let mut tick = interval(Duration::from_secs(2)); loop { tick.tick().await; for (name, connector) in &mut connectors { if let Ok(AgentResponse::Metrics(m)) = connector.request(AgentRequest::Metrics).await { println!("[{}] CPU: {:.1}%, Mem: {:.1}%", name, m.cpu_total, (m.mem_used as f64 / m.mem_total as f64) * 100.0 ); } } println!("---"); } } ``` ### Example: Alert System ```rust use socktop_connector::*; async fn check_alerts(mut connector: SocktopConnector) -> Result<(), Box> { match connector.request(AgentRequest::Metrics).await { Ok(AgentResponse::Metrics(metrics)) => { // CPU alert if metrics.cpu_total > 90.0 { eprintln!("ALERT: CPU usage at {:.1}%", metrics.cpu_total); } // Memory alert let mem_percent = (metrics.mem_used as f64 / metrics.mem_total as f64) * 100.0; if mem_percent > 90.0 { eprintln!("ALERT: Memory usage at {:.1}%", mem_percent); } // Disk alert if let Ok(AgentResponse::Disks(disks)) = connector.request(AgentRequest::Disks).await { for disk in disks { let used_percent = ((disk.total - disk.available) as f64 / disk.total as f64) * 100.0; if used_percent > 90.0 { eprintln!("ALERT: Disk {} at {:.1}%", disk.name, used_percent); } } } } Err(e) => eprintln!("Error fetching metrics: {}", e), _ => {} } Ok(()) } ``` ## Data Types Key types provided by the library: - `Metrics` - System metrics (CPU, memory, network, GPU, etc.) - `ProcessMetricsResponse` - Process information - `DiskInfo` - Disk usage information - `NetworkInfo` - Network interface statistics - `GpuInfo` - GPU metrics - `JournalEntry` - Systemd journal entries - `AgentRequest` - Request types - `AgentResponse` - Response types See the [crate documentation](https://docs.rs/socktop_connector) for complete API reference. ## Performance Considerations The connector is lightweight and efficient: - **Protocol Buffers** - Efficient binary serialization - **Gzip compression** - Reduced bandwidth usage - **Async I/O** - Non-blocking operations - **Connection reuse** - Single WebSocket for multiple requests Typical resource usage: - **Memory**: ~1-5 MB per connection - **CPU**: < 0.1% during idle - **Bandwidth**: ~1-5 KB per metrics request ## Troubleshooting ### Connection Errors ```rust match connect_to_socktop_agent(url).await { Err(ConnectorError::ConnectionFailed(e)) => { eprintln!("Connection failed: {}", e); // Retry logic here } Err(ConnectorError::InvalidUrl) => { eprintln!("Invalid URL format"); } Err(e) => eprintln!("Other error: {}", e), Ok(conn) => { /* Success */ } } ``` ### TLS Errors ```rust // Disable TLS verification for testing (not recommended) use socktop_connector::{ConnectorConfig, SocktopConnector}; let config = ConnectorConfig { url: "wss://server:3000/ws".to_string(), verify_tls: false, ..Default::default() }; ``` ## Examples Repository More examples available in the socktop repository: - `examples/simple_monitor.rs` - Basic monitoring - `examples/multi_server.rs` - Monitor multiple servers - `examples/alert_system.rs` - Threshold-based alerts - `examples/wasm_demo/` - Browser-based monitoring ## API Reference Full API documentation: [docs.rs/socktop_connector](https://docs.rs/socktop_connector) ## Next Steps - [Agent Direct Integration](./agent-integration.md) - Embed agent in your app - [General Usage](../usage/general.md) - Using the TUI client - [Configuration](../usage/configuration.md) - Configuration options