108 lines
3.3 KiB
Rust
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(())
|
|
}
|