mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Add the beginnings of internal stats keeping for lqosd and a not-advertised /api/stats page to view.
This commit is contained in:
parent
bbbe1e5b83
commit
b1091a94aa
@ -130,6 +130,9 @@ pub enum BusRequest {
|
|||||||
target: String,
|
target: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Obtain the lqosd statistics
|
||||||
|
GetLqosStats,
|
||||||
|
|
||||||
/// If running on Equinix (the `equinix_test` feature is enabled),
|
/// If running on Equinix (the `equinix_test` feature is enabled),
|
||||||
/// display a "run bandwidht test" link.
|
/// display a "run bandwidht test" link.
|
||||||
#[cfg(feature = "equinix_tests")]
|
#[cfg(feature = "equinix_tests")]
|
||||||
|
@ -74,4 +74,12 @@ pub enum BusResponse {
|
|||||||
|
|
||||||
/// Named nodes from network.json
|
/// Named nodes from network.json
|
||||||
NodeNames(Vec<(usize, String)>),
|
NodeNames(Vec<(usize, String)>),
|
||||||
|
|
||||||
|
/// Statistics from lqosd
|
||||||
|
LqosdStats{
|
||||||
|
/// Number of bus requests handled
|
||||||
|
bus_requests: u64,
|
||||||
|
/// Us to poll hosts
|
||||||
|
time_to_poll_hosts: u64,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{auth_guard::AuthGuard, cache_control::NoCache};
|
use crate::{auth_guard::AuthGuard, cache_control::NoCache};
|
||||||
use default_net::get_interfaces;
|
use default_net::get_interfaces;
|
||||||
use lqos_bus::{bus_request, BusRequest};
|
use lqos_bus::{bus_request, BusRequest, BusResponse};
|
||||||
use lqos_config::{EtcLqos, LibreQoSConfig, Tunables};
|
use lqos_config::{EtcLqos, LibreQoSConfig, Tunables};
|
||||||
use rocket::{fs::NamedFile, serde::json::Json};
|
use rocket::{fs::NamedFile, serde::{json::Json, Serialize}};
|
||||||
|
|
||||||
// Note that NoCache can be replaced with a cache option
|
// Note that NoCache can be replaced with a cache option
|
||||||
// once the design work is complete.
|
// once the design work is complete.
|
||||||
@ -76,3 +76,23 @@ pub async fn update_lqos_tuning(
|
|||||||
|
|
||||||
Json("OK".to_string())
|
Json("OK".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone, Default)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
pub struct LqosStats {
|
||||||
|
pub bus_requests_since_start: u64,
|
||||||
|
pub time_to_poll_hosts_us: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/api/stats")]
|
||||||
|
pub async fn stats() -> NoCache<Json<LqosStats>> {
|
||||||
|
for msg in bus_request(vec![BusRequest::GetLqosStats]).await.unwrap() {
|
||||||
|
if let BusResponse::LqosdStats { bus_requests, time_to_poll_hosts } = msg {
|
||||||
|
return NoCache::new(Json(LqosStats {
|
||||||
|
bus_requests_since_start: bus_requests,
|
||||||
|
time_to_poll_hosts_us: time_to_poll_hosts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NoCache::new(Json(LqosStats::default()))
|
||||||
|
}
|
@ -82,6 +82,7 @@ fn rocket() -> _ {
|
|||||||
network_tree::network_tree_summary,
|
network_tree::network_tree_summary,
|
||||||
network_tree::node_names,
|
network_tree::node_names,
|
||||||
network_tree::funnel_for_queue,
|
network_tree::funnel_for_queue,
|
||||||
|
config_control::stats,
|
||||||
// Supporting files
|
// Supporting files
|
||||||
static_pages::bootsrap_css,
|
static_pages::bootsrap_css,
|
||||||
static_pages::plotly_js,
|
static_pages::plotly_js,
|
||||||
|
@ -3,9 +3,8 @@ use lqos_bus::BusResponse;
|
|||||||
|
|
||||||
pub fn get_raw_circuit_data(circuit_id: &str) -> BusResponse {
|
pub fn get_raw_circuit_data(circuit_id: &str) -> BusResponse {
|
||||||
still_watching(circuit_id);
|
still_watching(circuit_id);
|
||||||
let reader = CIRCUIT_TO_QUEUE.read().unwrap();
|
if let Some(circuit) = CIRCUIT_TO_QUEUE.get(circuit_id) {
|
||||||
if let Some(circuit) = reader.get(circuit_id) {
|
if let Ok(json) = serde_json::to_string(circuit.value()) {
|
||||||
if let Ok(json) = serde_json::to_string(circuit) {
|
|
||||||
BusResponse::RawQueueData(json)
|
BusResponse::RawQueueData(json)
|
||||||
} else {
|
} else {
|
||||||
BusResponse::RawQueueData(String::new())
|
BusResponse::RawQueueData(String::new())
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
|
use dashmap::DashMap;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::queue_store::QueueStore;
|
use crate::queue_store::QueueStore;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::RwLock;
|
|
||||||
|
|
||||||
pub(crate) static CIRCUIT_TO_QUEUE: Lazy<RwLock<HashMap<String, QueueStore>>> =
|
pub(crate) static CIRCUIT_TO_QUEUE: Lazy<DashMap<String, QueueStore>> =
|
||||||
Lazy::new(|| RwLock::new(HashMap::new()));
|
Lazy::new(DashMap::new);
|
||||||
|
@ -48,13 +48,12 @@ fn track_queues() {
|
|||||||
|
|
||||||
if let Ok(download) = download {
|
if let Ok(download) = download {
|
||||||
if let Ok(upload) = upload {
|
if let Ok(upload) = upload {
|
||||||
let mut mapping = CIRCUIT_TO_QUEUE.write().unwrap();
|
if let Some(mut circuit) = CIRCUIT_TO_QUEUE.get_mut(circuit_id) {
|
||||||
if let Some(circuit) = mapping.get_mut(circuit_id) {
|
|
||||||
circuit.update(&download[0], &upload[0]);
|
circuit.update(&download[0], &upload[0]);
|
||||||
} else {
|
} else {
|
||||||
// It's new: insert it
|
// It's new: insert it
|
||||||
if !download.is_empty() && !upload.is_empty() {
|
if !download.is_empty() && !upload.is_empty() {
|
||||||
mapping.insert(
|
CIRCUIT_TO_QUEUE.insert(
|
||||||
circuit_id.to_string(),
|
circuit_id.to_string(),
|
||||||
QueueStore::new(download[0].clone(), upload[0].clone()),
|
QueueStore::new(download[0].clone(), upload[0].clone()),
|
||||||
);
|
);
|
||||||
|
@ -24,7 +24,9 @@ use signal_hook::{
|
|||||||
consts::{SIGHUP, SIGINT, SIGTERM},
|
consts::{SIGHUP, SIGINT, SIGTERM},
|
||||||
iterator::Signals,
|
iterator::Signals,
|
||||||
};
|
};
|
||||||
|
use stats::{BUS_REQUESTS, TIME_TO_POLL_HOSTS};
|
||||||
use tokio::join;
|
use tokio::join;
|
||||||
|
mod stats;
|
||||||
|
|
||||||
// Use JemAllocator only on supported platforms
|
// Use JemAllocator only on supported platforms
|
||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
@ -120,6 +122,7 @@ fn handle_bus_requests(
|
|||||||
) {
|
) {
|
||||||
for req in requests.iter() {
|
for req in requests.iter() {
|
||||||
//println!("Request: {:?}", req);
|
//println!("Request: {:?}", req);
|
||||||
|
BUS_REQUESTS.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
responses.push(match req {
|
responses.push(match req {
|
||||||
BusRequest::Ping => lqos_bus::BusResponse::Ack,
|
BusRequest::Ping => lqos_bus::BusResponse::Ack,
|
||||||
BusRequest::GetCurrentThroughput => {
|
BusRequest::GetCurrentThroughput => {
|
||||||
@ -173,6 +176,12 @@ fn handle_bus_requests(
|
|||||||
BusRequest::GetFunnel { target: parent } => {
|
BusRequest::GetFunnel { target: parent } => {
|
||||||
shaped_devices_tracker::get_funnel(parent)
|
shaped_devices_tracker::get_funnel(parent)
|
||||||
}
|
}
|
||||||
|
BusRequest::GetLqosStats => {
|
||||||
|
BusResponse::LqosdStats {
|
||||||
|
bus_requests: BUS_REQUESTS.load(std::sync::atomic::Ordering::Relaxed),
|
||||||
|
time_to_poll_hosts: TIME_TO_POLL_HOSTS.load(std::sync::atomic::Ordering::Relaxed),
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
src/rust/lqosd/src/stats.rs
Normal file
4
src/rust/lqosd/src/stats.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
use std::sync::atomic::AtomicU64;
|
||||||
|
|
||||||
|
pub static BUS_REQUESTS: AtomicU64 = AtomicU64::new(0);
|
||||||
|
pub static TIME_TO_POLL_HOSTS: AtomicU64 = AtomicU64::new(0);
|
@ -2,7 +2,7 @@ mod throughput_entry;
|
|||||||
mod tracking_data;
|
mod tracking_data;
|
||||||
use crate::{
|
use crate::{
|
||||||
shaped_devices_tracker::NETWORK_JSON,
|
shaped_devices_tracker::NETWORK_JSON,
|
||||||
throughput_tracker::tracking_data::ThroughputTracker,
|
throughput_tracker::tracking_data::ThroughputTracker, stats::TIME_TO_POLL_HOSTS,
|
||||||
};
|
};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use lqos_bus::{BusResponse, IpStats, TcHandle, XdpPpingResult};
|
use lqos_bus::{BusResponse, IpStats, TcHandle, XdpPpingResult};
|
||||||
@ -23,6 +23,7 @@ pub fn spawn_throughput_monitor() {
|
|||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
periodic(interval_ms, "Throughput Monitor", &mut || {
|
periodic(interval_ms, "Throughput Monitor", &mut || {
|
||||||
|
let start = std::time::Instant::now();
|
||||||
{
|
{
|
||||||
let net_json = NETWORK_JSON.read().unwrap();
|
let net_json = NETWORK_JSON.read().unwrap();
|
||||||
net_json.zero_throughput_and_rtt();
|
net_json.zero_throughput_and_rtt();
|
||||||
@ -32,6 +33,8 @@ pub fn spawn_throughput_monitor() {
|
|||||||
THROUGHPUT_TRACKER.apply_rtt_data();
|
THROUGHPUT_TRACKER.apply_rtt_data();
|
||||||
THROUGHPUT_TRACKER.update_totals();
|
THROUGHPUT_TRACKER.update_totals();
|
||||||
THROUGHPUT_TRACKER.next_cycle();
|
THROUGHPUT_TRACKER.next_cycle();
|
||||||
|
let duration_ms = start.elapsed().as_micros();
|
||||||
|
TIME_TO_POLL_HOSTS.store(duration_ms as u64, std::sync::atomic::Ordering::Relaxed);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user