Add ARK game servers to systemd service monitoring

This commit is contained in:
Christoffer Martinsson 2025-10-19 19:23:51 +02:00
parent ca160c9627
commit f67779be9d

View File

@ -67,8 +67,11 @@ impl SystemdCollector {
Ok(services) => {
state.monitored_services = services;
state.last_discovery_time = Some(Instant::now());
debug!("Auto-discovered {} services to monitor: {:?}",
state.monitored_services.len(), state.monitored_services);
debug!(
"Auto-discovered {} services to monitor: {:?}",
state.monitored_services.len(),
state.monitored_services
);
}
Err(e) => {
debug!("Failed to discover services, using cached list: {}", e);
@ -96,7 +99,10 @@ impl SystemdCollector {
if needs_refresh {
// Only check nginx sites if nginx service is active
if state.monitored_services.iter().any(|s| s.contains("nginx")) {
debug!("Refreshing nginx site latency metrics (interval: {}s)", state.nginx_check_interval_seconds);
debug!(
"Refreshing nginx site latency metrics (interval: {}s)",
state.nginx_check_interval_seconds
);
let fresh_metrics = self.get_nginx_sites();
state.nginx_site_metrics = fresh_metrics;
state.last_nginx_check_time = Some(Instant::now());
@ -176,6 +182,8 @@ impl SystemdCollector {
"haasp",
// Backup services
"backup",
// Game servers
"ark",
];
for line in output_str.lines() {
@ -188,7 +196,10 @@ impl SystemdCollector {
let mut is_excluded = false;
for excluded in &excluded_services {
if service_name.contains(excluded) {
debug!("EXCLUDING service '{}' because it matches pattern '{}'", service_name, excluded);
debug!(
"EXCLUDING service '{}' because it matches pattern '{}'",
service_name, excluded
);
is_excluded = true;
break;
}
@ -202,7 +213,10 @@ impl SystemdCollector {
// Check if this service matches our interesting patterns
for pattern in &interesting_services {
if service_name.contains(pattern) || pattern.contains(service_name) {
debug!("INCLUDING service '{}' because it matches pattern '{}'", service_name, pattern);
debug!(
"INCLUDING service '{}' because it matches pattern '{}'",
service_name, pattern
);
services.push(service_name.to_string());
break;
}
@ -214,7 +228,8 @@ impl SystemdCollector {
if !services.iter().any(|s| s.contains("ssh")) {
for line in output_str.lines() {
let fields: Vec<&str> = line.split_whitespace().collect();
if fields.len() >= 4 && (fields[0] == "sshd.service" || fields[0] == "ssh.service") {
if fields.len() >= 4 && (fields[0] == "sshd.service" || fields[0] == "ssh.service")
{
let service_name = fields[0].trim_end_matches(".service");
services.push(service_name.to_string());
break;
@ -276,7 +291,6 @@ impl SystemdCollector {
None
}
/// Get service disk usage by examining service working directory
fn get_service_disk_usage(&self, service: &str) -> Option<f32> {
// Try to get working directory from systemctl
@ -303,10 +317,16 @@ impl SystemdCollector {
s if s.contains("docker") => vec!["/var/lib/docker", "/var/lib/docker/containers"],
// Web services and applications
s if s.contains("gitea") => vec!["/var/lib/gitea", "/opt/gitea", "/home/git", "/data/gitea"],
s if s.contains("gitea") => {
vec!["/var/lib/gitea", "/opt/gitea", "/home/git", "/data/gitea"]
}
s if s.contains("nginx") => vec!["/var/log/nginx", "/var/www", "/usr/share/nginx"],
s if s.contains("apache") || s.contains("httpd") => vec!["/var/log/apache2", "/var/www", "/etc/apache2"],
s if s.contains("immich") => vec!["/var/lib/immich", "/opt/immich", "/usr/src/app/upload"],
s if s.contains("apache") || s.contains("httpd") => {
vec!["/var/log/apache2", "/var/www", "/etc/apache2"]
}
s if s.contains("immich") => {
vec!["/var/lib/immich", "/opt/immich", "/usr/src/app/upload"]
}
s if s.contains("nextcloud") => vec!["/var/www/nextcloud", "/var/nextcloud"],
s if s.contains("owncloud") => vec!["/var/www/owncloud", "/var/owncloud"],
s if s.contains("plex") => vec!["/var/lib/plexmediaserver", "/opt/plex"],
@ -321,7 +341,9 @@ impl SystemdCollector {
s if s.contains("mysql") => vec!["/var/lib/mysql"],
s if s.contains("mariadb") => vec!["/var/lib/mysql", "/var/lib/mariadb"],
s if s.contains("redis") => vec!["/var/lib/redis", "/var/redis"],
s if s.contains("mongodb") || s.contains("mongo") => vec!["/var/lib/mongodb", "/var/lib/mongo"],
s if s.contains("mongodb") || s.contains("mongo") => {
vec!["/var/lib/mongodb", "/var/lib/mongo"]
}
// Message queues and communication
s if s.contains("mosquitto") => vec!["/var/lib/mosquitto", "/etc/mosquitto"],
@ -329,7 +351,9 @@ impl SystemdCollector {
s if s.contains("ssh") => vec!["/var/log/auth.log", "/etc/ssh"],
// Download and sync services
s if s.contains("transmission") => vec!["/var/lib/transmission-daemon", "/var/transmission"],
s if s.contains("transmission") => {
vec!["/var/lib/transmission-daemon", "/var/transmission"]
}
s if s.contains("syncthing") => vec!["/var/lib/syncthing", "/home/syncthing"],
// System services - check logs and config
@ -365,14 +389,9 @@ impl SystemdCollector {
None
}
/// Get directory size in GB with permission-aware logging
fn get_directory_size(&self, dir: &str) -> Option<f32> {
let output = Command::new("du")
.arg("-sb")
.arg(dir)
.output()
.ok()?;
let output = Command::new("du").arg("-sb").arg(dir).output().ok()?;
if !output.status.success() {
// Log permission errors for debugging but don't spam logs
@ -449,9 +468,13 @@ impl SystemdCollector {
// Try service-specific known directories
let service_dirs = match service {
s if s.contains("docker") => vec!["/var/lib/docker", "/var/lib/docker/containers"],
s if s.contains("gitea") => vec!["/var/lib/gitea", "/opt/gitea", "/home/git", "/data/gitea"],
s if s.contains("gitea") => {
vec!["/var/lib/gitea", "/opt/gitea", "/home/git", "/data/gitea"]
}
s if s.contains("nginx") => vec!["/var/log/nginx", "/var/www", "/usr/share/nginx"],
s if s.contains("immich") => vec!["/var/lib/immich", "/opt/immich", "/usr/src/app/upload"],
s if s.contains("immich") => {
vec!["/var/lib/immich", "/opt/immich", "/usr/src/app/upload"]
}
s if s.contains("postgres") => vec!["/var/lib/postgresql", "/var/lib/postgres"],
s if s.contains("mysql") => vec!["/var/lib/mysql"],
s if s.contains("redis") => vec!["/var/lib/redis", "/var/redis"],
@ -626,9 +649,10 @@ impl SystemdCollector {
if let Ok(link) = std::fs::read_link(entry.path()) {
if let Some(path_str) = link.to_str() {
// Skip special files, focus on regular files
if !path_str.starts_with("/dev/") &&
!path_str.starts_with("/proc/") &&
!path_str.starts_with("[") {
if !path_str.starts_with("/dev/")
&& !path_str.starts_with("/proc/")
&& !path_str.starts_with("[")
{
if let Ok(metadata) = std::fs::metadata(&link) {
total_size += metadata.len();
found_any = true;
@ -656,7 +680,7 @@ impl SystemdCollector {
// Database services typically have significant disk usage
s if s.contains("mysql") || s.contains("postgres") || s.contains("redis") => {
(memory_mb / 100.0).max(0.1) // Estimate based on memory
},
}
// Web services and applications
s if s.contains("nginx") || s.contains("apache") => 0.05, // ~50MB for configs/logs
s if s.contains("gitea") => (memory_mb / 50.0).max(0.5), // Code repositories
@ -669,8 +693,6 @@ impl SystemdCollector {
Some(estimated_gb)
}
}
#[async_trait]
@ -750,8 +772,11 @@ impl Collector for SystemdCollector {
}
let collection_time = start_time.elapsed();
debug!("Systemd collection completed in {:?} with {} individual service metrics",
collection_time, metrics.len());
debug!(
"Systemd collection completed in {:?} with {} individual service metrics",
collection_time,
metrics.len()
);
Ok(metrics)
}
@ -863,8 +888,8 @@ impl SystemdCollector {
/// Check site latency using HTTP GET requests
fn check_site_latency(&self, url: &str) -> Result<f32, Box<dyn std::error::Error>> {
use std::time::Instant;
use std::time::Duration;
use std::time::Instant;
let start = Instant::now();
@ -883,7 +908,12 @@ impl SystemdCollector {
if response.status().is_success() || response.status().is_redirection() {
Ok(latency)
} else {
Err(format!("HTTP request failed for {} with status: {}", url, response.status()).into())
Err(format!(
"HTTP request failed for {} with status: {}",
url,
response.status()
)
.into())
}
}
@ -1045,7 +1075,11 @@ impl SystemdCollector {
if let Some(names_part) = trimmed.strip_prefix("server_name") {
let names_clean = names_part.trim().trim_end_matches(';');
for name in names_clean.split_whitespace() {
if name != "_" && !name.is_empty() && name.contains('.') && !name.starts_with('$') {
if name != "_"
&& !name.is_empty()
&& name.contains('.')
&& !name.starts_with('$')
{
server_names.push(name.to_string());
debug!("Found server_name in block: {}", name);
}