0ee387d983
* squashing work on using cancellation in nym crates making nym-task wasm compilable removed sending of status messages replaced TaskManager with ShutdownManager in the validator rewarder additional helpers for ShutdownManager simplified ShutdownToken by removing the name field TaskClient => ShutdownToken within all client tasks wip: remove TaskHandle * track all long-living client tasks * add task tracking for most top level tasks within nym-node * improved default builder * split up cancellation module * module documentation and unit tests * nym node fixes and naming consistency * wasm fixes * assert_eq => assert * wasm fixes and made 'run_until_shutdown' take reference instead of ownership * linux-specific fixes to IpPacketRouter * post rebasing fixes for signing monitor * add ShutdownManager constructor to build it from an external token * applying PR review suggestions
155 lines
5.4 KiB
Rust
155 lines
5.4 KiB
Rust
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use crate::report::client::{ClientStatsReport, OsInformation};
|
|
|
|
use nym_task::ShutdownToken;
|
|
use time::{OffsetDateTime, Time};
|
|
use tokio::sync::mpsc::UnboundedSender;
|
|
|
|
/// Active gateway connection statistics.
|
|
pub mod gateway_conn_statistics;
|
|
|
|
/// Nym API connection statistics.
|
|
pub mod nym_api_statistics;
|
|
|
|
/// Packet count based statistics.
|
|
pub mod packet_statistics;
|
|
|
|
pub mod connection;
|
|
|
|
/// Channel receiving generic stats events to be used by a statistics aggregator.
|
|
pub type ClientStatsReceiver = tokio::sync::mpsc::UnboundedReceiver<ClientStatsEvents>;
|
|
|
|
/// Channel allowing generic statistics events to be reported to a stats event aggregator
|
|
#[derive(Clone)]
|
|
pub struct ClientStatsSender {
|
|
stats_tx: Option<UnboundedSender<ClientStatsEvents>>,
|
|
shutdown_token: ShutdownToken,
|
|
}
|
|
|
|
impl ClientStatsSender {
|
|
/// Create a new statistics Sender
|
|
pub fn new(
|
|
stats_tx: Option<UnboundedSender<ClientStatsEvents>>,
|
|
shutdown_token: ShutdownToken,
|
|
) -> Self {
|
|
ClientStatsSender {
|
|
stats_tx,
|
|
shutdown_token,
|
|
}
|
|
}
|
|
|
|
/// Report a statistics event using the sender.
|
|
pub fn report(&self, event: ClientStatsEvents) {
|
|
if let Some(tx) = &self.stats_tx {
|
|
if let Err(err) = tx.send(event) {
|
|
if !self.shutdown_token.is_cancelled() {
|
|
log::error!("Failed to send stats event: {err}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Client Statistics events (static for now)
|
|
pub enum ClientStatsEvents {
|
|
/// Packet count events
|
|
PacketStatistics(packet_statistics::PacketStatisticsEvent),
|
|
/// Gateway Connection events
|
|
GatewayConn(gateway_conn_statistics::GatewayStatsEvent),
|
|
/// Nym API connection events
|
|
NymApi(nym_api_statistics::NymApiStatsEvent),
|
|
/// Credential events
|
|
Connection(connection::ConnectionStatsEvent),
|
|
}
|
|
|
|
/// Controls stats event handling and reporting
|
|
pub struct ClientStatsController {
|
|
//static infos
|
|
last_update_time: OffsetDateTime,
|
|
client_id: String,
|
|
client_type: String,
|
|
os_information: OsInformation,
|
|
|
|
// stats collection modules
|
|
packet_stats: packet_statistics::PacketStatisticsControl,
|
|
gateway_conn_stats: gateway_conn_statistics::GatewayStatsControl,
|
|
nym_api_stats: nym_api_statistics::NymApiStatsControl,
|
|
connection_stats: connection::ConnectionStatsControl,
|
|
}
|
|
|
|
impl ClientStatsController {
|
|
/// Creates a ClientStatsController given a client_id
|
|
pub fn new(client_id: String, client_type: String) -> Self {
|
|
ClientStatsController {
|
|
last_update_time: ClientStatsController::get_update_time(),
|
|
client_id,
|
|
client_type,
|
|
os_information: OsInformation::new(),
|
|
packet_stats: Default::default(),
|
|
gateway_conn_stats: Default::default(),
|
|
nym_api_stats: Default::default(),
|
|
connection_stats: Default::default(),
|
|
}
|
|
}
|
|
/// Returns a static ClientStatsReport that can be sent somewhere
|
|
pub fn build_report(&self) -> ClientStatsReport {
|
|
ClientStatsReport {
|
|
last_update_time: self.last_update_time,
|
|
client_id: self.client_id.clone(),
|
|
client_type: self.client_type.clone(),
|
|
os_information: self.os_information.clone(),
|
|
packet_stats: self.packet_stats.report(),
|
|
gateway_conn_stats: self.gateway_conn_stats.report(),
|
|
nym_api_stats: self.nym_api_stats.report(),
|
|
connection_stats: self.connection_stats.report(),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
/// Handle and dispatch incoming stats event
|
|
pub fn handle_event(&mut self, stats_event: ClientStatsEvents) {
|
|
match stats_event {
|
|
ClientStatsEvents::PacketStatistics(event) => self.packet_stats.handle_event(event),
|
|
ClientStatsEvents::GatewayConn(event) => self.gateway_conn_stats.handle_event(event),
|
|
ClientStatsEvents::NymApi(event) => self.nym_api_stats.handle_event(event),
|
|
ClientStatsEvents::Connection(event) => self.connection_stats.handle_event(event),
|
|
}
|
|
}
|
|
|
|
/// Reset the metrics to their initial state.
|
|
///
|
|
/// Used to periodically reset the metrics in accordance with periodic reporting strategy
|
|
pub fn reset(&mut self) {
|
|
self.nym_api_stats = Default::default();
|
|
self.gateway_conn_stats = Default::default();
|
|
self.connection_stats = Default::default();
|
|
//no periodic reset for packet stats
|
|
|
|
self.last_update_time = ClientStatsController::get_update_time();
|
|
}
|
|
|
|
/// snapshot the current state of the metrics for module that needs it
|
|
pub fn snapshot(&mut self) {
|
|
//no snapshot for gateway_conn_stats
|
|
//no snapshot for nym_api_stats
|
|
self.packet_stats.snapshot();
|
|
}
|
|
|
|
pub fn local_report(&mut self) {
|
|
self.packet_stats.local_report();
|
|
self.gateway_conn_stats.local_report();
|
|
self.nym_api_stats.local_report();
|
|
}
|
|
|
|
fn get_update_time() -> OffsetDateTime {
|
|
let now = OffsetDateTime::now_utc();
|
|
#[allow(clippy::unwrap_used)]
|
|
//Safety : 0 is always a valid number of seconds, hours and minutes comes from a valid source
|
|
let new_time = Time::from_hms(now.hour(), now.minute(), 0).unwrap();
|
|
//allows a bigger anonymity by hiding exact sending time
|
|
now.replace_time(new_time)
|
|
}
|
|
}
|