[Product Data] Add stats reporting configuration in client config (#5115)
* add stats_reporting_config in config and env var * fix serializazion issue * remove duplicate stats reporting config * cargo toml cleanup * more cleanup * draft of wasm sdk for stats reporting * fix wasm sdk? * again * make stats sending possible from outside the sdk * make sure stats_id from client and gateway reported ared different
This commit is contained in:
Generated
+1
@@ -4883,6 +4883,7 @@ dependencies = [
|
||||
"nym-sphinx-addressing",
|
||||
"nym-sphinx-params",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -102,5 +102,10 @@ average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
||||
[debug.cover_traffic]
|
||||
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
||||
|
||||
[debug.stats_reporting]
|
||||
enabled = {{ debug.stats_reporting.enabled }}
|
||||
provider_address = '{{ debug.stats_reporting.provider_address }}'
|
||||
reporting_interval = '{{ debug.stats_reporting.reporting_interval }}'
|
||||
|
||||
|
||||
"#;
|
||||
|
||||
@@ -81,6 +81,7 @@ impl From<Init> for OverrideConfig {
|
||||
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use clap::{Parser, Subcommand};
|
||||
use log::{error, info};
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_client::client::Recipient;
|
||||
use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use nym_config::OptionalSet;
|
||||
@@ -104,6 +105,7 @@ pub(crate) struct OverrideConfig {
|
||||
no_cover: bool,
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
stats_reporting_address: Option<Recipient>,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
@@ -149,6 +151,11 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
BaseClientConfig::with_disabled_credentials,
|
||||
args.enabled_credentials_mode.map(|b| !b),
|
||||
)
|
||||
.with_optional_env_ext(
|
||||
BaseClientConfig::with_enabled_stats_reporting_address,
|
||||
args.stats_reporting_address,
|
||||
nym_network_defaults::var_names::CLIENT_STATS_COLLECTION_PROVIDER,
|
||||
)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||
|
||||
@@ -43,6 +43,7 @@ impl From<Run> for OverrideConfig {
|
||||
no_cover: run_config.common_args.no_cover,
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ impl From<Init> for OverrideConfig {
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
outfox: false,
|
||||
stats_reporting_address: init_config.common_args.stats_reporting_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup;
|
||||
use nym_client_core::config::{GroupBy, TopologyStructure};
|
||||
use nym_config::OptionalSet;
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_sphinx::params::{PacketSize, PacketType};
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
@@ -111,6 +112,7 @@ pub(crate) struct OverrideConfig {
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
outfox: bool,
|
||||
stats_reporting_address: Option<Recipient>,
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
@@ -196,6 +198,11 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config {
|
||||
BaseClientConfig::with_disabled_credentials,
|
||||
args.enabled_credentials_mode.map(|b| !b),
|
||||
)
|
||||
.with_optional_base_env(
|
||||
BaseClientConfig::with_enabled_stats_reporting_address,
|
||||
args.stats_reporting_address,
|
||||
nym_network_defaults::var_names::CLIENT_STATS_COLLECTION_PROVIDER,
|
||||
)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
|
||||
@@ -70,6 +70,7 @@ impl From<Run> for OverrideConfig {
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
outfox: run_config.outfox,
|
||||
stats_reporting_address: run_config.common_args.stats_reporting_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,4 +108,9 @@ average_ack_delay = '{{ core.debug.acknowledgements.average_ack_delay }}'
|
||||
[core.debug.cover_traffic]
|
||||
loop_cover_traffic_average_delay = '{{ core.debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
||||
|
||||
[core.debug.stats_reporting]
|
||||
enabled = {{ core.debug.stats_reporting.enabled }}
|
||||
provider_address = '{{ core.debug.stats_reporting.provider_address }}'
|
||||
reporting_interval = '{{ core.debug.stats_reporting.reporting_interval }}'
|
||||
|
||||
"#;
|
||||
|
||||
@@ -9,6 +9,7 @@ license.workspace = true
|
||||
[dependencies]
|
||||
humantime-serde = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_with = { workspace = true, features = ["macros"] }
|
||||
thiserror.workspace = true
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
|
||||
@@ -23,4 +24,4 @@ nym-sphinx-addressing = { path = "../../nymsphinx/addressing" }
|
||||
|
||||
|
||||
[features]
|
||||
disk-persistence = ["nym-pemstore"]
|
||||
disk-persistence = ["nym-pemstore"]
|
||||
|
||||
@@ -5,6 +5,7 @@ use nym_config::defaults::NymNetworkDetails;
|
||||
use nym_sphinx_addressing::Recipient;
|
||||
use nym_sphinx_params::{PacketSize, PacketType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, DisplayFromStr};
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
@@ -61,6 +62,11 @@ const DEFAULT_MAXIMUM_REPLY_SURB_AGE: Duration = Duration::from_secs(12 * 60 * 6
|
||||
// 24 hours
|
||||
const DEFAULT_MAXIMUM_REPLY_KEY_AGE: Duration = Duration::from_secs(24 * 60 * 60);
|
||||
|
||||
// stats reporting related
|
||||
|
||||
/// Time interval between reporting statistics to the given provider if it exist
|
||||
const STATS_REPORT_INTERVAL_SECS: Duration = Duration::from_secs(300);
|
||||
|
||||
use crate::error::InvalidTrafficModeFailure;
|
||||
pub use nym_country_group::CountryGroup;
|
||||
|
||||
@@ -133,6 +139,12 @@ impl Config {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_enabled_stats_reporting_address(mut self, address: Recipient) -> Self {
|
||||
self.debug.stats_reporting.provider_address = Some(address);
|
||||
self.debug.stats_reporting.enabled = true; //since we are overriding the address, we assume the reporting should be enabled
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: this should be refactored properly
|
||||
// as of 12.09.23 the below is true (not sure how this comment will rot in the future)
|
||||
// medium_toggle:
|
||||
@@ -631,6 +643,32 @@ impl Default for ReplySurbs {
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct StatsReporting {
|
||||
/// Is stats reporting enabled
|
||||
pub enabled: bool,
|
||||
|
||||
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
||||
#[serde_as(as = "Option<DisplayFromStr>")]
|
||||
pub provider_address: Option<Recipient>,
|
||||
|
||||
/// With what frequence will statistics be sent
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub reporting_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for StatsReporting {
|
||||
fn default() -> Self {
|
||||
StatsReporting {
|
||||
enabled: true,
|
||||
provider_address: None,
|
||||
reporting_interval: STATS_REPORT_INTERVAL_SECS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct DebugConfig {
|
||||
@@ -651,6 +689,9 @@ pub struct DebugConfig {
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbs,
|
||||
|
||||
/// Defines all configuration options related to stats reporting.
|
||||
pub stats_reporting: StatsReporting,
|
||||
}
|
||||
|
||||
impl DebugConfig {
|
||||
@@ -672,6 +713,7 @@ impl Default for DebugConfig {
|
||||
acknowledgements: Default::default(),
|
||||
topology: Default::default(),
|
||||
reply_surbs: Default::default(),
|
||||
stats_reporting: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@ impl From<ConfigV5> for Config {
|
||||
maximum_reply_key_age: value.debug.reply_surbs.maximum_reply_key_age,
|
||||
surb_mix_hops: value.debug.reply_surbs.surb_mix_hops,
|
||||
},
|
||||
stats_reporting: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::{
|
||||
use log::info;
|
||||
use nym_client_core_gateways_storage::GatewayDetails;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::rngs::OsRng;
|
||||
@@ -88,6 +89,10 @@ pub struct CommonClientInitArgs {
|
||||
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub no_cover: bool,
|
||||
|
||||
/// Sets the address to report statistics
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub stats_reporting_address: Option<Recipient>,
|
||||
}
|
||||
|
||||
pub struct InitResultsWithConfig<T> {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg_attr(feature = "cli", derive(clap::Args))]
|
||||
@@ -56,4 +57,8 @@ pub struct CommonClientRunArgs {
|
||||
// has defined the conflict on that field itself
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub no_cover: bool,
|
||||
|
||||
/// Sets the address to report statistics
|
||||
#[cfg_attr(feature = "cli", clap(long, hide = true))]
|
||||
pub stats_reporting_address: Option<Recipient>,
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ use nym_sphinx::addressing::nodes::NodeIdentity;
|
||||
use nym_sphinx::params::PacketType;
|
||||
use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
|
||||
use nym_statistics_common::clients::ClientStatsSender;
|
||||
use nym_statistics_common::StatsReportingConfig;
|
||||
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
@@ -187,7 +186,6 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
|
||||
shutdown: Option<TaskClient>,
|
||||
user_agent: Option<UserAgent>,
|
||||
stats_reporting_config: Option<StatsReportingConfig>,
|
||||
|
||||
setup_method: GatewaySetup,
|
||||
}
|
||||
@@ -211,7 +209,6 @@ where
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
user_agent: None,
|
||||
stats_reporting_config: None,
|
||||
setup_method: GatewaySetup::MustLoad { gateway_id: None },
|
||||
}
|
||||
}
|
||||
@@ -255,12 +252,6 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_statistics_reporting(mut self, config: StatsReportingConfig) -> Self {
|
||||
self.stats_reporting_config = Some(config);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_stored_topology<P: AsRef<Path>>(
|
||||
mut self,
|
||||
file: P,
|
||||
@@ -598,14 +589,18 @@ where
|
||||
}
|
||||
|
||||
fn start_statistics_control(
|
||||
stats_reporting_config: Option<StatsReportingConfig>,
|
||||
config: &Config,
|
||||
user_agent: Option<UserAgent>,
|
||||
client_stats_id: String,
|
||||
input_sender: Sender<InputMessage>,
|
||||
shutdown: TaskClient,
|
||||
) -> ClientStatsSender {
|
||||
info!("Starting statistics control...");
|
||||
StatisticsControl::create_and_start_with_shutdown(
|
||||
stats_reporting_config,
|
||||
config.debug.stats_reporting,
|
||||
user_agent
|
||||
.map(|u| u.application)
|
||||
.unwrap_or("unknown".to_string()),
|
||||
client_stats_id,
|
||||
input_sender.clone(),
|
||||
shutdown.with_suffix("controller"),
|
||||
@@ -739,12 +734,14 @@ where
|
||||
self.user_agent.clone(),
|
||||
);
|
||||
|
||||
//make sure we don't accidentally get the same id as gateways are reporting
|
||||
let client_stats_id = format!(
|
||||
"{:x}",
|
||||
"stats_id_{:x}",
|
||||
sha2::Sha256::digest(self_address.identity().to_bytes())
|
||||
);
|
||||
let stats_reporter = Self::start_statistics_control(
|
||||
self.stats_reporting_config,
|
||||
self.config,
|
||||
self.user_agent.clone(),
|
||||
client_stats_id,
|
||||
input_sender.clone(),
|
||||
shutdown.fork("statistics_control"),
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use nym_client_core_config_types::StatsReporting;
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
use nym_statistics_common::{
|
||||
clients::{ClientStatsController, ClientStatsReceiver, ClientStatsSender},
|
||||
StatsReportingConfig,
|
||||
use nym_statistics_common::clients::{
|
||||
ClientStatsController, ClientStatsReceiver, ClientStatsSender,
|
||||
};
|
||||
use nym_task::connections::TransmissionLane;
|
||||
|
||||
@@ -30,8 +30,6 @@ use crate::{
|
||||
spawn_future,
|
||||
};
|
||||
|
||||
/// Time interval between reporting statistics to the given provider if it exist
|
||||
const STATS_REPORT_INTERVAL_SECS: u64 = 300;
|
||||
/// Time interval between reporting statistics locally (logging/task_client)
|
||||
const LOCAL_REPORT_INTERVAL: Duration = Duration::from_secs(2);
|
||||
/// Interval for taking snapshots of the statistics
|
||||
@@ -51,21 +49,18 @@ pub(crate) struct StatisticsControl {
|
||||
/// Channel to send stats report through the mixnet
|
||||
report_tx: InputMessageSender,
|
||||
|
||||
/// Service-provider address to send stats reports
|
||||
reporting_address: Option<Recipient>,
|
||||
/// Config for stats reporting (enabled, address, interval)
|
||||
reporting_config: StatsReporting,
|
||||
}
|
||||
|
||||
impl StatisticsControl {
|
||||
pub(crate) fn create(
|
||||
reporting_config: Option<StatsReportingConfig>,
|
||||
reporting_config: StatsReporting,
|
||||
client_type: String,
|
||||
client_stats_id: String,
|
||||
report_tx: InputMessageSender,
|
||||
) -> (Self, ClientStatsSender) {
|
||||
let (stats_tx, stats_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (reporting_address, client_type) = match reporting_config {
|
||||
Some(cfg) => (Some(cfg.reporting_address), cfg.reporting_type),
|
||||
None => (None, "".into()),
|
||||
};
|
||||
|
||||
let stats = ClientStatsController::new(client_stats_id, client_type);
|
||||
|
||||
@@ -73,8 +68,8 @@ impl StatisticsControl {
|
||||
StatisticsControl {
|
||||
stats,
|
||||
stats_rx,
|
||||
reporting_address,
|
||||
report_tx,
|
||||
reporting_config,
|
||||
},
|
||||
ClientStatsSender::new(Some(stats_tx)),
|
||||
)
|
||||
@@ -99,8 +94,8 @@ impl StatisticsControl {
|
||||
async fn run_with_shutdown(&mut self, mut task_client: nym_task::TaskClient) {
|
||||
log::debug!("Started StatisticsControl with graceful shutdown support");
|
||||
|
||||
let stats_report_interval = Duration::from_secs(STATS_REPORT_INTERVAL_SECS);
|
||||
let mut stats_report_interval = tokio::time::interval(stats_report_interval);
|
||||
let mut stats_report_interval =
|
||||
tokio::time::interval(self.reporting_config.reporting_interval);
|
||||
let mut local_report_interval = tokio::time::interval(LOCAL_REPORT_INTERVAL);
|
||||
let mut snapshot_interval = tokio::time::interval(SNAPSHOT_INTERVAL);
|
||||
|
||||
@@ -116,10 +111,10 @@ impl StatisticsControl {
|
||||
_ = snapshot_interval.tick() => {
|
||||
self.stats.snapshot();
|
||||
}
|
||||
_ = stats_report_interval.tick(), if self.reporting_address.is_some() => {
|
||||
_ = stats_report_interval.tick(), if self.reporting_config.enabled && self.reporting_config.provider_address.is_some() => {
|
||||
// SAFTEY : this branch executes only if reporting is not none, so unwrapp is fine
|
||||
#[allow(clippy::unwrap_used)]
|
||||
self.report_stats(self.reporting_address.unwrap()).await;
|
||||
self.report_stats(self.reporting_config.provider_address.unwrap()).await;
|
||||
}
|
||||
|
||||
_ = local_report_interval.tick() => {
|
||||
@@ -142,12 +137,14 @@ impl StatisticsControl {
|
||||
}
|
||||
|
||||
pub(crate) fn create_and_start_with_shutdown(
|
||||
reporting_config: Option<StatsReportingConfig>,
|
||||
reporting_config: StatsReporting,
|
||||
client_type: String,
|
||||
client_stats_id: String,
|
||||
report_tx: InputMessageSender,
|
||||
task_client: nym_task::TaskClient,
|
||||
) -> ClientStatsSender {
|
||||
let (controller, sender) = Self::create(reporting_config, client_stats_id, report_tx);
|
||||
let (controller, sender) =
|
||||
Self::create(reporting_config, client_type, client_stats_id, report_tx);
|
||||
controller.start_with_shutdown(task_client);
|
||||
sender
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
|
||||
pub const EXPLORER_API: &str = "EXPLORER_API";
|
||||
pub const EXIT_POLICY_URL: &str = "EXIT_POLICY";
|
||||
pub const NYM_VPN_API: &str = "NYM_VPN_API";
|
||||
pub const CLIENT_STATS_COLLECTION_PROVIDER: &str = "CLIENT_STATS_COLLECTION_PROVIDER";
|
||||
|
||||
pub const DKG_TIME_CONFIGURATION: &str = "DKG_TIME_CONFIGURATION";
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ impl ClientStatsSender {
|
||||
}
|
||||
|
||||
/// Report a statistics event using the sender.
|
||||
pub fn report(&mut self, event: ClientStatsEvents) {
|
||||
if let Some(tx) = self.stats_tx.as_mut() {
|
||||
pub fn report(&self, event: ClientStatsEvents) {
|
||||
if let Some(tx) = &self.stats_tx {
|
||||
if let Err(err) = tx.send(event) {
|
||||
log::error!("Failed to send stats event: {:?}", err);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#![warn(clippy::todo)]
|
||||
#![warn(clippy::dbg_macro)]
|
||||
|
||||
use nym_sphinx::addressing::Recipient;
|
||||
|
||||
/// Client specific statistics interfaces and events.
|
||||
pub mod clients;
|
||||
/// Statistics related errors.
|
||||
@@ -21,49 +19,3 @@ pub mod error;
|
||||
pub mod gateways;
|
||||
/// Statistics reporting abstractions and implementations.
|
||||
pub mod report;
|
||||
|
||||
/// Stats Reporting config to use when stats reporting is wanted
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StatsReportingConfig {
|
||||
/// Client address to report to
|
||||
pub reporting_address: Recipient,
|
||||
|
||||
/// Type of client reporting (vpn_client, authenticator, native-client)
|
||||
pub reporting_type: String,
|
||||
}
|
||||
|
||||
impl StatsReportingConfig {
|
||||
/// Create a StatsReportingConfig for a native client
|
||||
pub fn new_native(reporting_address: Recipient) -> Self {
|
||||
StatsReportingConfig {
|
||||
reporting_address,
|
||||
reporting_type: NATIVE_CLIENT.to_string(),
|
||||
}
|
||||
}
|
||||
/// Create a StatsReportingConfig for a vpn client
|
||||
pub fn new_vpn(reporting_address: Recipient) -> Self {
|
||||
StatsReportingConfig {
|
||||
reporting_address,
|
||||
reporting_type: VPN_CLIENT.to_string(),
|
||||
}
|
||||
}
|
||||
/// Create a StatsReportingConfig for a socks5 client
|
||||
pub fn new_socks5(reporting_address: Recipient) -> Self {
|
||||
StatsReportingConfig {
|
||||
reporting_address,
|
||||
reporting_type: SOCKS5_CLIENT.to_string(),
|
||||
}
|
||||
}
|
||||
/// Create a StatsReportingConfig for an unspecified client
|
||||
pub fn new_unknown(reporting_address: Recipient) -> Self {
|
||||
StatsReportingConfig {
|
||||
reporting_address,
|
||||
reporting_type: UNKNOWN.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const VPN_CLIENT: &str = "vpn_client";
|
||||
const NATIVE_CLIENT: &str = "native_client";
|
||||
const SOCKS5_CLIENT: &str = "socks5_client";
|
||||
const UNKNOWN: &str = "unknown";
|
||||
|
||||
@@ -17,7 +17,7 @@ pub use nym_client_core::config::{
|
||||
Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig,
|
||||
CoverTraffic as ConfigCoverTraffic, DebugConfig as ConfigDebug,
|
||||
GatewayConnection as ConfigGatewayConnection, ReplySurbs as ConfigReplySurbs,
|
||||
Topology as ConfigTopology, Traffic as ConfigTraffic,
|
||||
StatsReporting as ConfigStatsReporting, Topology as ConfigTopology, Traffic as ConfigTraffic,
|
||||
};
|
||||
|
||||
pub fn new_base_client_config(
|
||||
@@ -86,7 +86,7 @@ pub fn no_cover_debug_obj() -> JsValue {
|
||||
|
||||
// just a helper structure to more easily pass through the JS boundary
|
||||
#[wasm_bindgen(inspectable)]
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DebugWasm {
|
||||
/// Defines all configuration options related to traffic streams.
|
||||
@@ -106,6 +106,10 @@ pub struct DebugWasm {
|
||||
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
pub reply_surbs: ReplySurbsWasm,
|
||||
|
||||
/// Defines all configuration options related to stats reporting.
|
||||
#[wasm_bindgen(getter_with_clone)]
|
||||
pub stats_reporting: StatsReportingWasm,
|
||||
}
|
||||
|
||||
impl Default for DebugWasm {
|
||||
@@ -123,6 +127,7 @@ impl From<DebugWasm> for ConfigDebug {
|
||||
acknowledgements: debug.acknowledgements.into(),
|
||||
topology: debug.topology.into(),
|
||||
reply_surbs: debug.reply_surbs.into(),
|
||||
stats_reporting: debug.stats_reporting.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,6 +141,7 @@ impl From<ConfigDebug> for DebugWasm {
|
||||
acknowledgements: debug.acknowledgements.into(),
|
||||
topology: debug.topology.into(),
|
||||
reply_surbs: debug.reply_surbs.into(),
|
||||
stats_reporting: debug.stats_reporting.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -505,3 +511,46 @@ impl From<ConfigReplySurbs> for ReplySurbsWasm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(inspectable)]
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct StatsReportingWasm {
|
||||
/// Is stats reporting enabled
|
||||
pub enabled: bool,
|
||||
|
||||
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
||||
#[wasm_bindgen(getter_with_clone)]
|
||||
pub provider_address: Option<String>,
|
||||
|
||||
/// With what frequence will statistics be sent
|
||||
pub reporting_interval_ms: u32,
|
||||
}
|
||||
|
||||
impl Default for StatsReportingWasm {
|
||||
fn default() -> Self {
|
||||
ConfigStatsReporting::default().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StatsReportingWasm> for ConfigStatsReporting {
|
||||
fn from(stats_reporting: StatsReportingWasm) -> Self {
|
||||
ConfigStatsReporting {
|
||||
enabled: stats_reporting.enabled,
|
||||
provider_address: stats_reporting
|
||||
.provider_address
|
||||
.map(|address| address.parse().expect("Invalid provider address")),
|
||||
reporting_interval: Duration::from_millis(stats_reporting.reporting_interval_ms as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConfigStatsReporting> for StatsReportingWasm {
|
||||
fn from(stats_reporting: ConfigStatsReporting) -> Self {
|
||||
StatsReportingWasm {
|
||||
enabled: stats_reporting.enabled,
|
||||
provider_address: stats_reporting.provider_address.map(|r| r.to_string()),
|
||||
reporting_interval_ms: stats_reporting.reporting_interval.as_millis() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
use super::{
|
||||
AcknowledgementsWasm, CoverTrafficWasm, DebugWasm, GatewayConnectionWasm, ReplySurbsWasm,
|
||||
TopologyWasm, TrafficWasm,
|
||||
StatsReportingWasm, TopologyWasm, TrafficWasm,
|
||||
};
|
||||
use crate::config::ConfigDebug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tsify::Tsify;
|
||||
|
||||
// just a helper structure to more easily pass through the JS boundary
|
||||
#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
#[derive(Tsify, Debug, Clone, Serialize, Deserialize)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DebugWasmOverride {
|
||||
@@ -43,6 +43,10 @@ pub struct DebugWasmOverride {
|
||||
/// Defines all configuration options related to reply SURBs.
|
||||
#[tsify(optional)]
|
||||
pub reply_surbs: Option<ReplySurbsWasmOverride>,
|
||||
|
||||
/// Defines all configuration options related to stats reporting.
|
||||
#[tsify(optional)]
|
||||
pub stats_reporting: Option<StatsReportingWasmOverride>,
|
||||
}
|
||||
|
||||
impl From<DebugWasmOverride> for DebugWasm {
|
||||
@@ -54,6 +58,7 @@ impl From<DebugWasmOverride> for DebugWasm {
|
||||
acknowledgements: value.acknowledgements.map(Into::into).unwrap_or_default(),
|
||||
topology: value.topology.map(Into::into).unwrap_or_default(),
|
||||
reply_surbs: value.reply_surbs.map(Into::into).unwrap_or_default(),
|
||||
stats_reporting: value.stats_reporting.map(Into::into).unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,3 +371,34 @@ impl From<ReplySurbsWasmOverride> for ReplySurbsWasm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Tsify, Debug, Clone, Serialize, Deserialize)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StatsReportingWasmOverride {
|
||||
/// Is stats reporting enabled
|
||||
#[tsify(optional)]
|
||||
pub enabled: Option<bool>,
|
||||
|
||||
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
|
||||
#[tsify(optional)]
|
||||
pub provider_address: Option<Option<String>>,
|
||||
|
||||
/// With what frequence will statistics be sent
|
||||
#[tsify(optional)]
|
||||
pub reporting_interval_ms: Option<u32>,
|
||||
}
|
||||
|
||||
impl From<StatsReportingWasmOverride> for StatsReportingWasm {
|
||||
fn from(value: StatsReportingWasmOverride) -> Self {
|
||||
let def = StatsReportingWasm::default();
|
||||
|
||||
StatsReportingWasm {
|
||||
enabled: value.enabled.unwrap_or(def.enabled),
|
||||
provider_address: value.provider_address.unwrap_or(def.provider_address),
|
||||
reporting_interval_ms: value
|
||||
.reporting_interval_ms
|
||||
.unwrap_or(def.reporting_interval_ms),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ pub use nym_sphinx::{
|
||||
anonymous_replies::requests::AnonymousSenderTag,
|
||||
receiver::ReconstructedMessage,
|
||||
};
|
||||
pub use nym_statistics_common::clients::ClientStatsEvents;
|
||||
pub use nym_task::connections::TransmissionLane;
|
||||
pub use nym_topology::{provider_trait::TopologyProvider, NymTopology};
|
||||
pub use paths::StoragePaths;
|
||||
|
||||
@@ -23,7 +23,7 @@ use nym_client_core::client::key_manager::persistence::KeyStore;
|
||||
use nym_client_core::client::{
|
||||
base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend,
|
||||
};
|
||||
use nym_client_core::config::DebugConfig;
|
||||
use nym_client_core::config::{DebugConfig, StatsReporting};
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_client_core::init::helpers::current_gateways;
|
||||
use nym_client_core::init::setup_gateway;
|
||||
@@ -54,7 +54,6 @@ pub struct MixnetClientBuilder<S: MixnetClientStorage = Ephemeral> {
|
||||
custom_shutdown: Option<TaskClient>,
|
||||
force_tls: bool,
|
||||
user_agent: Option<UserAgent>,
|
||||
stats_reporting_config: Option<nym_statistics_common::StatsReportingConfig>,
|
||||
|
||||
// TODO: incorporate it properly into `MixnetClientStorage` (I will need it in wasm anyway)
|
||||
gateway_endpoint_config_path: Option<PathBuf>,
|
||||
@@ -94,7 +93,6 @@ impl MixnetClientBuilder<OnDiskPersistent> {
|
||||
custom_gateway_transceiver: None,
|
||||
force_tls: false,
|
||||
user_agent: None,
|
||||
stats_reporting_config: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -122,7 +120,6 @@ where
|
||||
custom_shutdown: None,
|
||||
force_tls: false,
|
||||
user_agent: None,
|
||||
stats_reporting_config: None,
|
||||
gateway_endpoint_config_path: None,
|
||||
storage,
|
||||
}
|
||||
@@ -141,7 +138,6 @@ where
|
||||
custom_shutdown: self.custom_shutdown,
|
||||
force_tls: self.force_tls,
|
||||
user_agent: self.user_agent,
|
||||
stats_reporting_config: self.stats_reporting_config,
|
||||
gateway_endpoint_config_path: self.gateway_endpoint_config_path,
|
||||
storage,
|
||||
}
|
||||
@@ -236,11 +232,8 @@ where
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_statistics_reporting(
|
||||
mut self,
|
||||
config: nym_statistics_common::StatsReportingConfig,
|
||||
) -> Self {
|
||||
self.stats_reporting_config = Some(config);
|
||||
pub fn with_statistics_reporting(mut self, config: StatsReporting) -> Self {
|
||||
self.config.debug_config.stats_reporting = config;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -272,7 +265,6 @@ where
|
||||
client.wait_for_gateway = self.wait_for_gateway;
|
||||
client.force_tls = self.force_tls;
|
||||
client.user_agent = self.user_agent;
|
||||
client.stats_reporting_config = self.stats_reporting_config;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
@@ -322,8 +314,6 @@ where
|
||||
custom_shutdown: Option<TaskClient>,
|
||||
|
||||
user_agent: Option<UserAgent>,
|
||||
|
||||
stats_reporting_config: Option<nym_statistics_common::StatsReportingConfig>,
|
||||
}
|
||||
|
||||
impl<S> DisconnectedMixnetClient<S>
|
||||
@@ -373,7 +363,6 @@ where
|
||||
force_tls: false,
|
||||
custom_shutdown: None,
|
||||
user_agent: None,
|
||||
stats_reporting_config: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -594,10 +583,6 @@ where
|
||||
base_builder = base_builder.with_user_agent(user_agent);
|
||||
}
|
||||
|
||||
if let Some(stats_reporting_config) = self.stats_reporting_config {
|
||||
base_builder = base_builder.with_statistics_reporting(stats_reporting_config);
|
||||
}
|
||||
|
||||
if let Some(topology_provider) = self.custom_topology_provider {
|
||||
base_builder = base_builder.with_topology_provider(topology_provider);
|
||||
}
|
||||
@@ -729,6 +714,7 @@ where
|
||||
let mut client_output = started_client.client_output.register_consumer();
|
||||
let client_state: nym_client_core::client::base_client::ClientState =
|
||||
started_client.client_state;
|
||||
let stats_events_reporter = started_client.stats_reporter;
|
||||
|
||||
let identity_keys = started_client.identity_keys.clone();
|
||||
let reconstructed_receiver = client_output.register_receiver()?;
|
||||
@@ -740,6 +726,7 @@ where
|
||||
client_output,
|
||||
client_state,
|
||||
reconstructed_receiver,
|
||||
stats_events_reporter,
|
||||
started_client.task_handle,
|
||||
None,
|
||||
))
|
||||
|
||||
@@ -13,6 +13,7 @@ use nym_client_core::client::{
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::{params::PacketType, receiver::ReconstructedMessage};
|
||||
use nym_statistics_common::clients::{ClientStatsEvents, ClientStatsSender};
|
||||
use nym_task::{
|
||||
connections::{ConnectionCommandSender, LaneQueueLengths},
|
||||
TaskHandle,
|
||||
@@ -45,6 +46,9 @@ pub struct MixnetClient {
|
||||
/// A channel for messages arriving from the mixnet after they have been reconstructed.
|
||||
pub(crate) reconstructed_receiver: ReconstructedMessagesReceiver,
|
||||
|
||||
/// A channel for sending stats event to be reported.
|
||||
pub(crate) stats_events_reporter: ClientStatsSender,
|
||||
|
||||
/// The task manager that controls all the spawned tasks that the clients uses to do it's job.
|
||||
pub(crate) task_handle: TaskHandle,
|
||||
pub(crate) packet_type: Option<PacketType>,
|
||||
@@ -62,6 +66,7 @@ impl MixnetClient {
|
||||
client_output: ClientOutput,
|
||||
client_state: ClientState,
|
||||
reconstructed_receiver: ReconstructedMessagesReceiver,
|
||||
stats_events_reporter: ClientStatsSender,
|
||||
task_handle: TaskHandle,
|
||||
packet_type: Option<PacketType>,
|
||||
) -> Self {
|
||||
@@ -72,6 +77,7 @@ impl MixnetClient {
|
||||
client_output,
|
||||
client_state,
|
||||
reconstructed_receiver,
|
||||
stats_events_reporter,
|
||||
task_handle,
|
||||
packet_type,
|
||||
_buffered: Vec::new(),
|
||||
@@ -179,6 +185,10 @@ impl MixnetClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_stats_event(&self, event: ClientStatsEvents) {
|
||||
self.stats_events_reporter.report(event);
|
||||
}
|
||||
|
||||
/// Disconnect from the mixnet. Currently it is not supported to reconnect a disconnected
|
||||
/// client.
|
||||
pub async fn disconnect(mut self) {
|
||||
|
||||
@@ -252,7 +252,7 @@ impl<'a> From<&'a ClientOpts> for ClientConfigOpts {
|
||||
id: value.client_id.as_ref().map(|v| v.to_owned()),
|
||||
nym_api: value.nym_api_url.as_ref().map(|v| v.to_owned()),
|
||||
nyxd: value.nyxd_url.as_ref().map(|v| v.to_owned()),
|
||||
debug: value.client_override.as_ref().map(|&v| v.into()),
|
||||
debug: value.client_override.as_ref().map(|v| v.clone().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ impl<'a> From<&'a MixFetchOpts> for MixFetchConfigOpts {
|
||||
id: value.client_id.as_ref().map(|v| v.to_owned()),
|
||||
nym_api: value.nym_api_url.as_ref().map(|v| v.to_owned()),
|
||||
nyxd: value.nyxd_url.as_ref().map(|v| v.to_owned()),
|
||||
debug: value.client_override.as_ref().map(|&v| v.into()),
|
||||
debug: value.client_override.as_ref().map(|v| v.clone().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user