Files
watcheragent/WatcherAgent/src/main.rs

108 lines
3.3 KiB
Rust

/// WatcherAgent - A Rust-based system monitoring agent
/// This agent collects hardware metrics and sends them to a backend server.
/// It supports CPU, GPU, RAM, disk, and network metrics.
pub mod api;
pub mod hardware;
pub mod metrics;
pub mod models;
pub mod docker;
use std::env;
use std::error::Error;
use std::marker::Send;
use std::marker::Sync;
use std::result::Result;
use tokio::task::JoinHandle;
use bollard::Docker;
async fn flatten<T>(
handle: JoinHandle<Result<T, Box<dyn Error + Send + Sync>>>,
) -> Result<T, Box<dyn Error + Send + Sync>> {
match handle.await {
Ok(Ok(result)) => Ok(result),
Ok(Err(err)) => Err(err),
Err(_err) => Err("handling failed".into()),
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
// Initialize Docker client
let docker = Docker::connect_with_local_defaults()
.map_err(|e| format!("Failed to connect to Docker: {}", e))?;
// Get current image version
let client_version = match docker::serverclientcomm::get_client_container(&docker).await {
Ok(Some(version)) => version.image,
Ok(None) => {
eprintln!("Warning: No image version found");
"unknown".to_string()
}
Err(e) => {
eprintln!("Warning: Could not get current image version: {}", e);
"unknown".to_string()
}
};
println!("Client Version: {}", client_version);
let args: Vec<String> = env::args().collect();
// args[0] is the binary name, args[1] is the first actual argument
if args.len() < 2 {
eprintln!("Usage: {} <server-url>", args[0]);
return Err("Missing server URL argument".into());
}
let server_url = &args[1];
println!("Server URL: {:?}", server_url);
// Registration
let (server_id, ip) = match api::register_with_server(&server_url).await {
Ok((id, ip)) => (id, ip),
Err(e) => {
eprintln!("Fehler bei der Registrierung am Server: {e}");
return Err(e);
}
};
// Start background tasks
// Start server listening for commands
let listening_handle = tokio::spawn({
let docker = docker.clone();
let server_url = server_url.to_string();
async move { api::listening_to_server(&docker, &server_url).await }
});
// Start heartbeat in background
let heartbeat_handle = tokio::spawn({
let ip = ip.clone();
let server_url = server_url.to_string();
async move { api::heartbeat_loop(&server_url, &ip).await }
});
// Main metrics loop
println!("Starting metrics collection...");
let metrics_handle = tokio::spawn({
let ip = ip.clone();
let server_url = server_url.to_string();
async move {
let mut collector = metrics::Collector::new(server_id, ip);
collector.run(&server_url).await
}
});
// Wait for all tasks and check for errors
let (listening_result, heartbeat_result, metrics_result) = tokio::try_join!(
flatten(listening_handle),
flatten(heartbeat_handle),
flatten(metrics_handle)
)?;
println!(
"All tasks completed: listening={:?}, heartbeat={:?}, metrics={:?}",
listening_result, heartbeat_result, metrics_result
);
println!("All tasks completed successfully.");
Ok(())
}