This commit is contained in:
Christoffer Martinsson 2025-10-12 16:14:38 +02:00
parent d33b24318a
commit d77139b172

View File

@ -465,15 +465,21 @@ impl ServiceCollector {
let update_interval = 30; // seconds let update_interval = 30; // seconds
let service_offset = service_hash % update_interval; let service_offset = service_hash % update_interval;
if (now + service_offset) % update_interval == 0 { let should_update = (now + service_offset) % update_interval == 0;
if should_update {
tracing::debug!("Service {} updating description (throttle check passed)", service);
self.get_service_description(service).await self.get_service_description(service).await
} else { } else {
let next_update = update_interval - ((now + service_offset) % update_interval);
tracing::trace!("Service {} throttled, next update in {} seconds", service, next_update);
None // Return None to indicate no new description this cycle None // Return None to indicate no new description this cycle
} }
} }
async fn get_service_description(&self, service: &str) -> Option<Vec<String>> { async fn get_service_description(&self, service: &str) -> Option<Vec<String>> {
match service { tracing::debug!("Getting description for service: {}", service);
let result = match service {
"sshd" | "ssh" => self.get_ssh_active_users().await.map(|s| vec![s]), "sshd" | "ssh" => self.get_ssh_active_users().await.map(|s| vec![s]),
"nginx" => self.get_nginx_sites().await, "nginx" => self.get_nginx_sites().await,
"apache2" | "httpd" => self.get_web_server_connections().await.map(|s| vec![s]), "apache2" | "httpd" => self.get_web_server_connections().await.map(|s| vec![s]),
@ -481,7 +487,14 @@ impl ServiceCollector {
"postgresql" | "postgres" => self.get_postgres_connections().await.map(|s| vec![s]), "postgresql" | "postgres" => self.get_postgres_connections().await.map(|s| vec![s]),
"mysql" | "mariadb" => self.get_mysql_connections().await.map(|s| vec![s]), "mysql" | "mariadb" => self.get_mysql_connections().await.map(|s| vec![s]),
_ => None, _ => None,
};
match &result {
Some(descriptions) => tracing::info!("Service {} got {} descriptions: {:?}", service, descriptions.len(), descriptions),
None => tracing::debug!("Service {} got no description", service),
} }
result
} }
async fn get_ssh_active_users(&self) -> Option<String> { async fn get_ssh_active_users(&self) -> Option<String> {
@ -622,44 +635,70 @@ impl ServiceCollector {
} }
async fn get_nginx_sites(&self) -> Option<Vec<String>> { async fn get_nginx_sites(&self) -> Option<Vec<String>> {
tracing::debug!("Starting nginx site detection");
// For NixOS and other systems, get the actual running nginx config // For NixOS and other systems, get the actual running nginx config
let output = Command::new("nginx") let output = match Command::new("nginx")
.args(["-T"]) .args(["-T"])
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.output() .output()
.await .await
.ok()?; {
Ok(output) => output,
Err(e) => {
tracing::warn!("Failed to execute nginx -T: {}", e);
return None;
}
};
if !output.status.success() { if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
tracing::warn!("nginx -T failed with status {}: {}", output.status, stderr);
return None; return None;
} }
let config = String::from_utf8_lossy(&output.stdout); let config = String::from_utf8_lossy(&output.stdout);
tracing::debug!("Got nginx config, {} bytes", config.len());
let mut sites = Vec::new(); let mut sites = Vec::new();
let mut server_name_lines = 0;
for line in config.lines() { for line in config.lines() {
let trimmed = line.trim(); let trimmed = line.trim();
if trimmed.starts_with("server_name") { if trimmed.starts_with("server_name") {
server_name_lines += 1;
tracing::debug!("Found server_name line: {}", trimmed);
// Extract server names from "server_name example.com www.example.com;" // Extract server names from "server_name example.com www.example.com;"
if let Some(names_part) = trimmed.strip_prefix("server_name") { if let Some(names_part) = trimmed.strip_prefix("server_name") {
let names_clean = names_part.trim().trim_end_matches(';'); let names_clean = names_part.trim().trim_end_matches(';');
tracing::debug!("Extracted names part: '{}'", names_clean);
for name in names_clean.split_whitespace() { for name in names_clean.split_whitespace() {
// Skip default catch-all server names // Skip default catch-all server names
if name != "_" && !name.is_empty() && name.contains('.') && !name.starts_with('$') { if name != "_" && !name.is_empty() && name.contains('.') && !name.starts_with('$') {
tracing::debug!("Adding site: {}", name);
sites.push(name.to_string()); sites.push(name.to_string());
} else {
tracing::debug!("Skipping invalid site: {}", name);
} }
} }
} }
} }
} }
tracing::info!("Found {} server_name lines, extracted {} sites", server_name_lines, sites.len());
// Remove duplicates and limit to reasonable number // Remove duplicates and limit to reasonable number
sites.sort(); sites.sort();
sites.dedup(); sites.dedup();
sites.truncate(15); // Show max 15 sites to avoid overwhelming the UI sites.truncate(15); // Show max 15 sites to avoid overwhelming the UI
tracing::info!("Final nginx sites list: {:?}", sites);
if sites.is_empty() { if sites.is_empty() {
tracing::warn!("No nginx sites found");
None None
} else { } else {
Some(sites) Some(sites)