[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:
Simon Wicky
2024-11-13 08:38:35 +01:00
committed by GitHub
parent 100eea8f64
commit b424c6a8ff
26 changed files with 220 additions and 107 deletions
Generated
+1
View File
@@ -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 }}'
"#;
+1
View File
@@ -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,
}
}
}
+7
View File
@@ -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> {
+1
View File
@@ -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,
}
}
}
+1
View File
@@ -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,
}
}
}
+7
View File
@@ -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> {
+1
View File
@@ -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,
}
}
}
+5
View File
@@ -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 }}'
"#;
+2 -1
View File
@@ -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
}
+1
View File
@@ -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";
+2 -2
View File
@@ -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);
}
-48
View File
@@ -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";
+51 -2
View File
@@ -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,
}
}
}
+38 -2
View File
@@ -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),
}
}
}
+1
View File
@@ -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;
+5 -18
View File
@@ -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) {
+1 -1
View File
@@ -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()),
}
}
}
+1 -1
View File
@@ -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()),
}
}
}