use super::{LOG_TARGET, get_process_system_info, get_processing_accepted};
use async_trait::async_trait;
use pingap_core::{BackgroundTask, Error};
use pingap_location::LocationProvider;
use pingap_upstream::UpstreamProvider;
use std::sync::Arc;
use tracing::info;
struct PerformanceMetricsLogTask {
location_provider: Arc<dyn LocationProvider>,
upstream_provider: Arc<dyn UpstreamProvider>,
}
fn join_non_empty(items: Vec<String>) -> Option<String> {
if items.is_empty() {
None
} else {
Some(items.join(", "))
}
}
#[async_trait]
impl BackgroundTask for PerformanceMetricsLogTask {
async fn execute(&self, _count: u32) -> Result<bool, Error> {
let locations_stats_vec = self
.location_provider
.stats()
.into_iter()
.filter(|(_, stats)| stats.processing != 0)
.map(|(name, stats)| {
format!("{name}:{}/{}", stats.processing, stats.accepted)
})
.collect::<Vec<_>>();
let locations_stats = join_non_empty(locations_stats_vec);
let upstream_stats = self.upstream_provider.get_all_stats();
let system_info = get_process_system_info();
let (processing, accepted) = get_processing_accepted();
let upstreams_healthy_status = self
.upstream_provider
.healthy_status()
.iter()
.map(|(name, status)| {
format!("{name}:{}/{}", status.healthy, status.total)
})
.collect::<Vec<String>>()
.join(", ");
info!(
target: LOG_TARGET,
threads = system_info.threads, locations_stats, upstreams_healthy_status, upstream_stats = ?upstream_stats, accepted, processing, used_memory = system_info.memory, fd_count = system_info.fd_count, tcp_count = system_info.tcp_count, tcp6_count = system_info.tcp6_count, );
Ok(true)
}
}
pub fn new_performance_metrics_log_service(
location_provider: Arc<dyn LocationProvider>,
upstream_provider: Arc<dyn UpstreamProvider>,
) -> Box<dyn BackgroundTask> {
Box::new(PerformanceMetricsLogTask {
location_provider,
upstream_provider,
})
}