From 0ad88b620c715a9abcdbe5ad29528069716779b7 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 09:56:04 +0000 Subject: [PATCH 1/9] refactor: [#1228] move type from tracker-core to main lib This is the frist step in a bigger refactor. We will move statistics out of the tracker-core package into new packages. Statistics are not related to the tracker-core or enven handled there. That logic belongs to upper layers. --- packages/tracker-core/src/statistics/mod.rs | 1 - .../tracker-core/src/statistics/services.rs | 55 ------------------- src/core/statistics/services.rs | 27 ++++++--- .../apis/v1/context/stats/resources.rs | 5 +- .../apis/v1/context/stats/responses.rs | 2 +- 5 files changed, 24 insertions(+), 66 deletions(-) delete mode 100644 packages/tracker-core/src/statistics/services.rs diff --git a/packages/tracker-core/src/statistics/mod.rs b/packages/tracker-core/src/statistics/mod.rs index 2ffbc0c8f..7517bab6e 100644 --- a/packages/tracker-core/src/statistics/mod.rs +++ b/packages/tracker-core/src/statistics/mod.rs @@ -28,5 +28,4 @@ pub mod event; pub mod keeper; pub mod metrics; pub mod repository; -pub mod services; pub mod setup; diff --git a/packages/tracker-core/src/statistics/services.rs b/packages/tracker-core/src/statistics/services.rs deleted file mode 100644 index 196c6b340..000000000 --- a/packages/tracker-core/src/statistics/services.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Statistics services. -//! -//! It includes: -//! -//! - A [`factory`](crate::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. -//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::core::statistics::metrics::Metrics). -//! -//! Tracker metrics are collected using a Publisher-Subscribe pattern. -//! -//! The factory function builds two structs: -//! -//! - An statistics event [`Sender`](crate::core::statistics::event::sender::Sender) -//! - An statistics [`Repository`] -//! -//! ```text -//! let (stats_event_sender, stats_repository) = factory(tracker_usage_statistics); -//! ``` -//! -//! The statistics repository is responsible for storing the metrics in memory. -//! The statistics event sender allows sending events related to metrics. -//! There is an event listener that is receiving all the events and processing them with an event handler. -//! Then, the event handler updates the metrics depending on the received event. -//! -//! For example, if you send the event [`Event::Udp4Connect`](crate::core::statistics::event::Event::Udp4Connect): -//! -//! ```text -//! let result = event_sender.send_event(Event::Udp4Connect).await; -//! ``` -//! -//! Eventually the counter for UDP connections from IPv4 peers will be increased. -//! -//! ```rust,no_run -//! pub struct Metrics { -//! // ... -//! pub udp4_connections_handled: u64, // This will be incremented -//! // ... -//! } -//! ``` -use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; - -use crate::statistics::metrics::Metrics; - -/// All the metrics collected by the tracker. -#[derive(Debug, PartialEq)] -pub struct TrackerMetrics { - /// Domain level metrics. - /// - /// General metrics for all torrents (number of seeders, leechers, etcetera) - pub torrents_metrics: TorrentsMetrics, - - /// Application level metrics. Usage statistics/metrics. - /// - /// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera) - pub protocol_metrics: Metrics, -} diff --git a/src/core/statistics/services.rs b/src/core/statistics/services.rs index a4bcc411e..514f126f9 100644 --- a/src/core/statistics/services.rs +++ b/src/core/statistics/services.rs @@ -2,14 +2,14 @@ //! //! It includes: //! -//! - A [`factory`](bittorrent_tracker_core::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. -//! - A [`get_metrics`] service to get the tracker [`metrics`](bittorrent_tracker_core::statistics::metrics::Metrics). +//! - A [`factory`](crate::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. +//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::core::statistics::metrics::Metrics). //! //! Tracker metrics are collected using a Publisher-Subscribe pattern. //! //! The factory function builds two structs: //! -//! - An statistics event [`Sender`](bittorrent_tracker_core::statistics::event::sender::Sender) +//! - An statistics event [`Sender`](crate::core::statistics::event::sender::Sender) //! - An statistics [`Repository`] //! //! ```text @@ -21,7 +21,7 @@ //! There is an event listener that is receiving all the events and processing them with an event handler. //! Then, the event handler updates the metrics depending on the received event. //! -//! For example, if you send the event [`Event::Udp4Connect`](bittorrent_tracker_core::statistics::event::Event::Udp4Connect): +//! For example, if you send the event [`Event::Udp4Connect`](crate::core::statistics::event::Event::Udp4Connect): //! //! ```text //! let result = event_sender.send_event(Event::Udp4Connect).await; @@ -40,12 +40,26 @@ use std::sync::Arc; use bittorrent_tracker_core::statistics::metrics::Metrics; use bittorrent_tracker_core::statistics::repository::Repository; -use bittorrent_tracker_core::statistics::services::TrackerMetrics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use tokio::sync::RwLock; +use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use crate::servers::udp::server::banning::BanService; +/// All the metrics collected by the tracker. +#[derive(Debug, PartialEq)] +pub struct TrackerMetrics { + /// Domain level metrics. + /// + /// General metrics for all torrents (number of seeders, leechers, etcetera) + pub torrents_metrics: TorrentsMetrics, + + /// Application level metrics. Usage statistics/metrics. + /// + /// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera) + pub protocol_metrics: Metrics, +} + /// It returns all the [`TrackerMetrics`] pub async fn get_metrics( in_memory_torrent_repository: Arc, @@ -96,7 +110,6 @@ pub async fn get_metrics( mod tests { use std::sync::Arc; - use bittorrent_tracker_core::statistics::services::TrackerMetrics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::{self, statistics}; use tokio::sync::RwLock; @@ -104,7 +117,7 @@ mod tests { use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_test_helpers::configuration; - use crate::core::statistics::services::get_metrics; + use crate::core::statistics::services::{get_metrics, TrackerMetrics}; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; diff --git a/src/servers/apis/v1/context/stats/resources.rs b/src/servers/apis/v1/context/stats/resources.rs index d4a0ec7ec..7b2242d40 100644 --- a/src/servers/apis/v1/context/stats/resources.rs +++ b/src/servers/apis/v1/context/stats/resources.rs @@ -1,8 +1,9 @@ //! API resources for the [`stats`](crate::servers::apis::v1::context::stats) //! API context. -use bittorrent_tracker_core::statistics::services::TrackerMetrics; use serde::{Deserialize, Serialize}; +use crate::core::statistics::services::TrackerMetrics; + /// It contains all the statistics generated by the tracker. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] pub struct Stats { @@ -118,10 +119,10 @@ impl From for Stats { #[cfg(test)] mod tests { use bittorrent_tracker_core::statistics::metrics::Metrics; - use bittorrent_tracker_core::statistics::services::TrackerMetrics; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use super::Stats; + use crate::core::statistics::services::TrackerMetrics; #[test] fn stats_resource_should_be_converted_from_tracker_metrics() { diff --git a/src/servers/apis/v1/context/stats/responses.rs b/src/servers/apis/v1/context/stats/responses.rs index fc74b5f8d..6fda43f8c 100644 --- a/src/servers/apis/v1/context/stats/responses.rs +++ b/src/servers/apis/v1/context/stats/responses.rs @@ -1,9 +1,9 @@ //! API responses for the [`stats`](crate::servers::apis::v1::context::stats) //! API context. use axum::response::{IntoResponse, Json, Response}; -use bittorrent_tracker_core::statistics::services::TrackerMetrics; use super::resources::Stats; +use crate::core::statistics::services::TrackerMetrics; /// `200` response that contains the [`Stats`] resource as json. #[must_use] From 9318842a2745921e3dc4a05ed1f9b632768aaf7d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 10:23:30 +0000 Subject: [PATCH 2/9] refactor: [#1228] move statistics back from tracker-core to main lib The statistics are only used at the higher levels: UDP and HTTP tracker. We will move them to new packages. --- Cargo.lock | 1 - packages/tracker-core/Cargo.toml | 1 - packages/tracker-core/src/lib.rs | 3 +- packages/tracker-core/src/statistics/mod.rs | 31 ------------ src/bootstrap/app.rs | 4 +- src/container.rs | 5 +- src/core/statistics/mod.rs | 1 - src/lib.rs | 2 +- src/{core => packages}/mod.rs | 0 .../packages}/statistics/event/handler.rs | 10 ++-- .../packages}/statistics/event/listener.rs | 2 +- .../packages}/statistics/event/mod.rs | 0 .../packages}/statistics/event/sender.rs | 4 +- .../src => src/packages}/statistics/keeper.rs | 6 +-- .../packages}/statistics/metrics.rs | 0 src/packages/statistics/mod.rs | 6 +++ .../packages}/statistics/repository.rs | 0 src/{core => packages}/statistics/services.rs | 18 +++---- .../src => src/packages}/statistics/setup.rs | 6 +-- src/servers/apis/v1/context/stats/handlers.rs | 5 +- .../apis/v1/context/stats/resources.rs | 7 +-- .../apis/v1/context/stats/responses.rs | 2 +- src/servers/http/v1/handlers/announce.rs | 10 ++-- src/servers/http/v1/handlers/scrape.rs | 7 ++- src/servers/http/v1/services/announce.rs | 17 ++++--- src/servers/http/v1/services/scrape.rs | 22 +++++---- src/servers/udp/handlers.rs | 47 +++++++++++-------- src/servers/udp/server/launcher.rs | 3 +- src/servers/udp/server/processor.rs | 5 +- tests/servers/http/environment.rs | 3 +- tests/servers/udp/environment.rs | 3 +- 31 files changed, 118 insertions(+), 113 deletions(-) delete mode 100644 packages/tracker-core/src/statistics/mod.rs delete mode 100644 src/core/statistics/mod.rs rename src/{core => packages}/mod.rs (100%) rename {packages/tracker-core/src => src/packages}/statistics/event/handler.rs (96%) rename {packages/tracker-core/src => src/packages}/statistics/event/listener.rs (83%) rename {packages/tracker-core/src => src/packages}/statistics/event/mod.rs (100%) rename {packages/tracker-core/src => src/packages}/statistics/event/sender.rs (82%) rename {packages/tracker-core/src => src/packages}/statistics/keeper.rs (92%) rename {packages/tracker-core/src => src/packages}/statistics/metrics.rs (100%) create mode 100644 src/packages/statistics/mod.rs rename {packages/tracker-core/src => src/packages}/statistics/repository.rs (100%) rename src/{core => packages}/statistics/services.rs (90%) rename {packages/tracker-core/src => src/packages}/statistics/setup.rs (82%) diff --git a/Cargo.lock b/Cargo.lock index bbf225018..d868f7452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,7 +600,6 @@ dependencies = [ "bittorrent-primitives", "chrono", "derive_more", - "futures", "local-ip-address", "mockall", "r2d2", diff --git a/packages/tracker-core/Cargo.toml b/packages/tracker-core/Cargo.toml index b38f7c90f..7b5b1f2c2 100644 --- a/packages/tracker-core/Cargo.toml +++ b/packages/tracker-core/Cargo.toml @@ -20,7 +20,6 @@ bittorrent-http-protocol = { version = "3.0.0-develop", path = "../http-protocol bittorrent-primitives = "0.1.0" chrono = { version = "0", default-features = false, features = ["clock"] } derive_more = { version = "1", features = ["as_ref", "constructor", "from"] } -futures = "0" r2d2 = "0" r2d2_mysql = "25" r2d2_sqlite = { version = "0", features = ["bundled"] } diff --git a/packages/tracker-core/src/lib.rs b/packages/tracker-core/src/lib.rs index 2fb2d936d..ec4371322 100644 --- a/packages/tracker-core/src/lib.rs +++ b/packages/tracker-core/src/lib.rs @@ -346,7 +346,7 @@ //! //! Services are domain services on top of the core tracker domain. Right now there are two types of service: //! -//! - For statistics: [`crate::core::statistics::services`] +//! - For statistics: [`crate::packages::statistics::services`] //! - For torrents: [`crate::core::torrent::services`] //! //! Services usually format the data inside the tracker to make it easier to consume by other parts. @@ -442,7 +442,6 @@ pub mod authentication; pub mod databases; pub mod error; pub mod scrape_handler; -pub mod statistics; pub mod torrent; pub mod whitelist; diff --git a/packages/tracker-core/src/statistics/mod.rs b/packages/tracker-core/src/statistics/mod.rs deleted file mode 100644 index 7517bab6e..000000000 --- a/packages/tracker-core/src/statistics/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! Structs to collect and keep tracker metrics. -//! -//! The tracker collects metrics such as: -//! -//! - Number of connections handled -//! - Number of `announce` requests handled -//! - Number of `scrape` request handled -//! -//! These metrics are collected for each connection type: UDP and HTTP and -//! also for each IP version used by the peers: IPv4 and IPv6. -//! -//! > Notice: that UDP tracker have an specific `connection` request. For the -//! > `HTTP` metrics the counter counts one connection for each `announce` or -//! > `scrape` request. -//! -//! The data is collected by using an `event-sender -> event listener` model. -//! -//! The tracker uses a [`Sender`](crate::core::statistics::event::sender::Sender) -//! instance to send an event. -//! -//! The [`statistics::keeper::Keeper`](crate::core::statistics::keeper::Keeper) listens to new -//! events and uses the [`statistics::repository::Repository`](crate::core::statistics::repository::Repository) to -//! upgrade and store metrics. -//! -//! See the [`statistics::event::Event`](crate::core::statistics::event::Event) enum to check -//! which events are available. -pub mod event; -pub mod keeper; -pub mod metrics; -pub mod repository; -pub mod setup; diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index f7506800e..7313b2808 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -20,13 +20,13 @@ use bittorrent_tracker_core::authentication::key::repository::persisted::Databas use bittorrent_tracker_core::authentication::service; use bittorrent_tracker_core::databases::setup::initialize_database; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_tracker_core::statistics; use bittorrent_tracker_core::torrent::manager::TorrentsManager; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use bittorrent_tracker_core::whitelist::setup::initialize_whitelist_manager; +use packages::statistics; use tokio::sync::RwLock; use torrust_tracker_clock::static_time; use torrust_tracker_configuration::validator::Validator; @@ -34,12 +34,12 @@ use torrust_tracker_configuration::Configuration; use tracing::instrument; use super::config::initialize_configuration; -use crate::bootstrap; use crate::container::AppContainer; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; use crate::shared::crypto::ephemeral_instance_keys; use crate::shared::crypto::keys::{self, Keeper as _}; +use crate::{bootstrap, packages}; /// It loads the configuration from the environment and builds app container. /// diff --git a/src/container.rs b/src/container.rs index cae2d07ce..965dbfa2a 100644 --- a/src/container.rs +++ b/src/container.rs @@ -5,16 +5,17 @@ use bittorrent_tracker_core::authentication::handler::KeysHandler; use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::databases::Database; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_tracker_core::statistics::event::sender::Sender; -use bittorrent_tracker_core::statistics::repository::Repository; use bittorrent_tracker_core::torrent::manager::TorrentsManager; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist; use bittorrent_tracker_core::whitelist::manager::WhitelistManager; +use packages::statistics::event::sender::Sender; +use packages::statistics::repository::Repository; use tokio::sync::RwLock; use torrust_tracker_configuration::{Core, HttpApi, HttpTracker, UdpTracker}; +use crate::packages; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { diff --git a/src/core/statistics/mod.rs b/src/core/statistics/mod.rs deleted file mode 100644 index 4e379ae78..000000000 --- a/src/core/statistics/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod services; diff --git a/src/lib.rs b/src/lib.rs index 212430605..b9ab402ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -494,7 +494,7 @@ pub mod app; pub mod bootstrap; pub mod console; pub mod container; -pub mod core; +pub mod packages; pub mod servers; pub mod shared; diff --git a/src/core/mod.rs b/src/packages/mod.rs similarity index 100% rename from src/core/mod.rs rename to src/packages/mod.rs diff --git a/packages/tracker-core/src/statistics/event/handler.rs b/src/packages/statistics/event/handler.rs similarity index 96% rename from packages/tracker-core/src/statistics/event/handler.rs rename to src/packages/statistics/event/handler.rs index 93ac05dde..99339041a 100644 --- a/packages/tracker-core/src/statistics/event/handler.rs +++ b/src/packages/statistics/event/handler.rs @@ -1,5 +1,5 @@ -use crate::statistics::event::{Event, UdpResponseKind}; -use crate::statistics::repository::Repository; +use crate::packages::statistics::event::{Event, UdpResponseKind}; +use crate::packages::statistics::repository::Repository; pub async fn handle_event(event: Event, stats_repository: &Repository) { match event { @@ -102,9 +102,9 @@ pub async fn handle_event(event: Event, stats_repository: &Repository) { #[cfg(test)] mod tests { - use crate::statistics::event::handler::handle_event; - use crate::statistics::event::Event; - use crate::statistics::repository::Repository; + use crate::packages::statistics::event::handler::handle_event; + use crate::packages::statistics::event::Event; + use crate::packages::statistics::repository::Repository; #[tokio::test] async fn should_increase_the_tcp4_announces_counter_when_it_receives_a_tcp4_announce_event() { diff --git a/packages/tracker-core/src/statistics/event/listener.rs b/src/packages/statistics/event/listener.rs similarity index 83% rename from packages/tracker-core/src/statistics/event/listener.rs rename to src/packages/statistics/event/listener.rs index f1a2e25de..009784fba 100644 --- a/packages/tracker-core/src/statistics/event/listener.rs +++ b/src/packages/statistics/event/listener.rs @@ -2,7 +2,7 @@ use tokio::sync::mpsc; use super::handler::handle_event; use super::Event; -use crate::statistics::repository::Repository; +use crate::packages::statistics::repository::Repository; pub async fn dispatch_events(mut receiver: mpsc::Receiver, stats_repository: Repository) { while let Some(event) = receiver.recv().await { diff --git a/packages/tracker-core/src/statistics/event/mod.rs b/src/packages/statistics/event/mod.rs similarity index 100% rename from packages/tracker-core/src/statistics/event/mod.rs rename to src/packages/statistics/event/mod.rs diff --git a/packages/tracker-core/src/statistics/event/sender.rs b/src/packages/statistics/event/sender.rs similarity index 82% rename from packages/tracker-core/src/statistics/event/sender.rs rename to src/packages/statistics/event/sender.rs index 1b663b5d1..b9b989053 100644 --- a/packages/tracker-core/src/statistics/event/sender.rs +++ b/src/packages/statistics/event/sender.rs @@ -13,10 +13,10 @@ pub trait Sender: Sync + Send { fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>>; } -/// An [`statistics::EventSender`](crate::core::statistics::event::sender::Sender) implementation. +/// An [`statistics::EventSender`](crate::packages::statistics::event::sender::Sender) implementation. /// /// It uses a channel sender to send the statistic events. The channel is created by a -/// [`statistics::Keeper`](crate::core::statistics::keeper::Keeper) +/// [`statistics::Keeper`](crate::packages::statistics::keeper::Keeper) #[allow(clippy::module_name_repetitions)] pub struct ChannelSender { pub(crate) sender: mpsc::Sender, diff --git a/packages/tracker-core/src/statistics/keeper.rs b/src/packages/statistics/keeper.rs similarity index 92% rename from packages/tracker-core/src/statistics/keeper.rs rename to src/packages/statistics/keeper.rs index a3d4542f7..493e61cb2 100644 --- a/packages/tracker-core/src/statistics/keeper.rs +++ b/src/packages/statistics/keeper.rs @@ -51,9 +51,9 @@ impl Keeper { #[cfg(test)] mod tests { - use crate::statistics::event::Event; - use crate::statistics::keeper::Keeper; - use crate::statistics::metrics::Metrics; + use crate::packages::statistics::event::Event; + use crate::packages::statistics::keeper::Keeper; + use crate::packages::statistics::metrics::Metrics; #[tokio::test] async fn should_contain_the_tracker_statistics() { diff --git a/packages/tracker-core/src/statistics/metrics.rs b/src/packages/statistics/metrics.rs similarity index 100% rename from packages/tracker-core/src/statistics/metrics.rs rename to src/packages/statistics/metrics.rs diff --git a/src/packages/statistics/mod.rs b/src/packages/statistics/mod.rs new file mode 100644 index 000000000..939a41061 --- /dev/null +++ b/src/packages/statistics/mod.rs @@ -0,0 +1,6 @@ +pub mod event; +pub mod keeper; +pub mod metrics; +pub mod repository; +pub mod services; +pub mod setup; diff --git a/packages/tracker-core/src/statistics/repository.rs b/src/packages/statistics/repository.rs similarity index 100% rename from packages/tracker-core/src/statistics/repository.rs rename to src/packages/statistics/repository.rs diff --git a/src/core/statistics/services.rs b/src/packages/statistics/services.rs similarity index 90% rename from src/core/statistics/services.rs rename to src/packages/statistics/services.rs index 514f126f9..444ba533c 100644 --- a/src/core/statistics/services.rs +++ b/src/packages/statistics/services.rs @@ -2,14 +2,14 @@ //! //! It includes: //! -//! - A [`factory`](crate::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. -//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::core::statistics::metrics::Metrics). +//! - A [`factory`](crate::packages::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. +//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::packages::statistics::metrics::Metrics). //! //! Tracker metrics are collected using a Publisher-Subscribe pattern. //! //! The factory function builds two structs: //! -//! - An statistics event [`Sender`](crate::core::statistics::event::sender::Sender) +//! - An statistics event [`Sender`](crate::packages::statistics::event::sender::Sender) //! - An statistics [`Repository`] //! //! ```text @@ -21,7 +21,7 @@ //! There is an event listener that is receiving all the events and processing them with an event handler. //! Then, the event handler updates the metrics depending on the received event. //! -//! For example, if you send the event [`Event::Udp4Connect`](crate::core::statistics::event::Event::Udp4Connect): +//! For example, if you send the event [`Event::Udp4Connect`](crate::packages::statistics::event::Event::Udp4Connect): //! //! ```text //! let result = event_sender.send_event(Event::Udp4Connect).await; @@ -38,12 +38,13 @@ //! ``` use std::sync::Arc; -use bittorrent_tracker_core::statistics::metrics::Metrics; -use bittorrent_tracker_core::statistics::repository::Repository; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::statistics::metrics::Metrics; +use packages::statistics::repository::Repository; use tokio::sync::RwLock; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; +use crate::packages; use crate::servers::udp::server::banning::BanService; /// All the metrics collected by the tracker. @@ -111,13 +112,14 @@ mod tests { use std::sync::Arc; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use bittorrent_tracker_core::{self, statistics}; + use bittorrent_tracker_core::{self}; use tokio::sync::RwLock; use torrust_tracker_configuration::Configuration; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_test_helpers::configuration; - use crate::core::statistics::services::{get_metrics, TrackerMetrics}; + use crate::packages::statistics; + use crate::packages::statistics::services::{get_metrics, TrackerMetrics}; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; diff --git a/packages/tracker-core/src/statistics/setup.rs b/src/packages/statistics/setup.rs similarity index 82% rename from packages/tracker-core/src/statistics/setup.rs rename to src/packages/statistics/setup.rs index 701392176..2a187dcf0 100644 --- a/packages/tracker-core/src/statistics/setup.rs +++ b/src/packages/statistics/setup.rs @@ -1,14 +1,14 @@ //! Setup for the tracker statistics. //! //! The [`factory`] function builds the structs needed for handling the tracker metrics. -use crate::statistics; +use crate::packages::statistics; /// It builds the structs needed for handling the tracker metrics. /// /// It returns: /// -/// - An statistics event [`Sender`](crate::core::statistics::event::sender::Sender) that allows you to send events related to statistics. -/// - An statistics [`Repository`](crate::core::statistics::repository::Repository) which is an in-memory repository for the tracker metrics. +/// - An statistics event [`Sender`](crate::packages::statistics::event::sender::Sender) that allows you to send events related to statistics. +/// - An statistics [`Repository`](crate::packages::statistics::repository::Repository) which is an in-memory repository for the tracker metrics. /// /// When the input argument `tracker_usage_statistics`is false the setup does not run the event listeners, consequently the statistics /// events are sent are received but not dispatched to the handler. diff --git a/src/servers/apis/v1/context/stats/handlers.rs b/src/servers/apis/v1/context/stats/handlers.rs index b4ead78ea..ffd4f1787 100644 --- a/src/servers/apis/v1/context/stats/handlers.rs +++ b/src/servers/apis/v1/context/stats/handlers.rs @@ -5,13 +5,14 @@ use std::sync::Arc; use axum::extract::State; use axum::response::Response; use axum_extra::extract::Query; -use bittorrent_tracker_core::statistics::repository::Repository; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::statistics::repository::Repository; use serde::Deserialize; use tokio::sync::RwLock; use super::responses::{metrics_response, stats_response}; -use crate::core::statistics::services::get_metrics; +use crate::packages; +use crate::packages::statistics::services::get_metrics; use crate::servers::udp::server::banning::BanService; #[derive(Deserialize, Debug, Default)] diff --git a/src/servers/apis/v1/context/stats/resources.rs b/src/servers/apis/v1/context/stats/resources.rs index 7b2242d40..5900e293a 100644 --- a/src/servers/apis/v1/context/stats/resources.rs +++ b/src/servers/apis/v1/context/stats/resources.rs @@ -2,7 +2,7 @@ //! API context. use serde::{Deserialize, Serialize}; -use crate::core::statistics::services::TrackerMetrics; +use crate::packages::statistics::services::TrackerMetrics; /// It contains all the statistics generated by the tracker. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -118,11 +118,12 @@ impl From for Stats { #[cfg(test)] mod tests { - use bittorrent_tracker_core::statistics::metrics::Metrics; + use packages::statistics::metrics::Metrics; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use super::Stats; - use crate::core::statistics::services::TrackerMetrics; + use crate::packages::statistics::services::TrackerMetrics; + use crate::packages::{self}; #[test] fn stats_resource_should_be_converted_from_tracker_metrics() { diff --git a/src/servers/apis/v1/context/stats/responses.rs b/src/servers/apis/v1/context/stats/responses.rs index 6fda43f8c..e3b45a66b 100644 --- a/src/servers/apis/v1/context/stats/responses.rs +++ b/src/servers/apis/v1/context/stats/responses.rs @@ -3,7 +3,7 @@ use axum::response::{IntoResponse, Json, Response}; use super::resources::Stats; -use crate::core::statistics::services::TrackerMetrics; +use crate::packages::statistics::services::TrackerMetrics; /// `200` response that contains the [`Stats`] resource as json. #[must_use] diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 40462c31d..d3225ee29 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -19,9 +19,9 @@ use bittorrent_http_protocol::v1::services::peer_ip_resolver::ClientIpSources; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; -use bittorrent_tracker_core::statistics::event::sender::Sender; use bittorrent_tracker_core::whitelist; use hyper::StatusCode; +use packages::statistics::event::sender::Sender; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::AnnounceData; @@ -33,7 +33,7 @@ use crate::servers::http::v1::extractors::authentication_key::Extract as Extract use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; use crate::servers::http::v1::handlers::common::auth; use crate::servers::http::v1::services::{self}; -use crate::CurrentClock; +use crate::{packages, CurrentClock}; /// It handles the `announce` request when the HTTP tracker does not require /// authentication (no PATH `key` parameter required). @@ -256,15 +256,17 @@ mod tests { use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::core_tests::sample_info_hash; use bittorrent_tracker_core::databases::setup::initialize_database; - use bittorrent_tracker_core::statistics; - use bittorrent_tracker_core::statistics::event::sender::Sender; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; + use packages::statistics; + use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; + use crate::packages; + struct CoreTrackerServices { pub core_config: Arc, pub announce_handler: Arc, diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index 1b9196e25..141cf4c45 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -15,11 +15,12 @@ use bittorrent_http_protocol::v1::services::peer_ip_resolver::{self, ClientIpSou use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_tracker_core::statistics::event::sender::Sender; use hyper::StatusCode; +use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::ScrapeData; +use crate::packages; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; use crate::servers::http::v1::extractors::scrape_request::ExtractRequest; @@ -174,13 +175,15 @@ mod tests { use bittorrent_tracker_core::authentication::key::repository::in_memory::InMemoryKeyRepository; use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; - use bittorrent_tracker_core::statistics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; + use packages::statistics; use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; + use crate::packages; + struct CoreTrackerServices { pub core_config: Arc, pub scrape_handler: Arc, diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 9e74ab8a5..61bbd93c6 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -12,11 +12,13 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; -use bittorrent_tracker_core::statistics; -use bittorrent_tracker_core::statistics::event::sender::Sender; +use packages::statistics; +use packages::statistics::event::sender::Sender; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; +use crate::packages; + /// The HTTP tracker `announce` service. /// /// The service sends an statistics event that increments: @@ -61,10 +63,10 @@ mod tests { use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::databases::setup::initialize_database; - use bittorrent_tracker_core::statistics; - use bittorrent_tracker_core::statistics::event::sender::Sender; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; + use packages::statistics; + use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; @@ -122,11 +124,13 @@ mod tests { } } - use bittorrent_tracker_core::statistics::event::Event; use futures::future::BoxFuture; use mockall::mock; + use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; + use crate::packages; + mock! { StatsEventSender {} impl Sender for StatsEventSender { @@ -142,16 +146,17 @@ mod tests { use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; use bittorrent_tracker_core::core_tests::sample_info_hash; use bittorrent_tracker_core::databases::setup::initialize_database; - use bittorrent_tracker_core::statistics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use mockall::predicate::eq; + use packages::statistics; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_test_helpers::configuration; use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; + use crate::packages; use crate::servers::http::v1::services::announce::invoke; use crate::servers::http::v1::services::announce::tests::{ initialize_core_tracker_services, sample_peer, MockStatsEventSender, diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index 59a7d34c7..1ac42ff10 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -12,10 +12,12 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_tracker_core::statistics::event::sender::Sender; -use bittorrent_tracker_core::statistics::{self}; +use packages::statistics::event::sender::Sender; +use packages::statistics::{self}; use torrust_tracker_primitives::core::ScrapeData; +use crate::packages; + /// The HTTP tracker `scrape` service. /// /// The service sends an statistics event that increments: @@ -80,18 +82,20 @@ mod tests { use bittorrent_tracker_core::core_tests::sample_info_hash; use bittorrent_tracker_core::databases::setup::initialize_database; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; - use bittorrent_tracker_core::statistics::event::sender::Sender; - use bittorrent_tracker_core::statistics::event::Event; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use futures::future::BoxFuture; use mockall::mock; + use packages::statistics::event::sender::Sender; + use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; + use crate::packages; + fn initialize_announce_and_scrape_handlers_for_public_tracker() -> (Arc, Arc) { let config = configuration::ephemeral_public(); @@ -150,11 +154,12 @@ mod tests { use std::sync::Arc; use bittorrent_tracker_core::announce_handler::PeersWanted; - use bittorrent_tracker_core::statistics; use mockall::predicate::eq; + use packages::statistics; use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; + use crate::packages; use crate::servers::http::v1::services::scrape::invoke; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, initialize_scrape_handler, sample_info_hash, @@ -163,7 +168,7 @@ mod tests { #[tokio::test] async fn it_should_return_the_scrape_data_for_a_torrent() { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let (announce_handler, scrape_handler) = initialize_announce_and_scrape_handlers_for_public_tracker(); @@ -235,10 +240,11 @@ mod tests { use std::sync::Arc; use bittorrent_tracker_core::announce_handler::PeersWanted; - use bittorrent_tracker_core::statistics; use mockall::predicate::eq; + use packages::statistics; use torrust_tracker_primitives::core::ScrapeData; + use crate::packages; use crate::servers::http::v1::services::scrape::fake; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, sample_info_hash, sample_info_hashes, sample_peer, @@ -247,7 +253,7 @@ mod tests { #[tokio::test] async fn it_should_always_return_the_zeroed_scrape_data_for_a_torrent() { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let (announce_handler, _scrape_handler) = initialize_announce_and_scrape_handlers_for_public_tracker(); diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 84b2f1db2..9f2562713 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -13,8 +13,8 @@ use aquatic_udp_protocol::{ use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use bittorrent_tracker_core::statistics::event::sender::Sender; -use bittorrent_tracker_core::{statistics, whitelist}; +use bittorrent_tracker_core::whitelist; +use packages::statistics::event::sender::Sender; use torrust_tracker_clock::clock::Time as _; use torrust_tracker_configuration::Core; use tracing::{instrument, Level}; @@ -24,10 +24,11 @@ use zerocopy::network_endian::I32; use super::connection_cookie::{check, make}; use super::RawRequest; use crate::container::UdpTrackerContainer; +use crate::packages::statistics; use crate::servers::udp::error::Error; use crate::servers::udp::{peer_builder, UDP_TRACKER_LOG_TARGET}; use crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS; -use crate::CurrentClock; +use crate::{packages, CurrentClock}; #[derive(Debug, Clone, PartialEq)] pub(super) struct CookieTimeValues { @@ -471,15 +472,15 @@ mod tests { use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::databases::setup::initialize_database; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; - use bittorrent_tracker_core::statistics::event::sender::Sender; - use bittorrent_tracker_core::statistics::event::Event; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; + use bittorrent_tracker_core::whitelist; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; - use bittorrent_tracker_core::{statistics, whitelist}; use futures::future::BoxFuture; use mockall::mock; + use packages::statistics::event::sender::Sender; + use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::{Configuration, Core}; @@ -487,7 +488,8 @@ mod tests { use torrust_tracker_test_helpers::configuration; use super::gen_remote_fingerprint; - use crate::CurrentClock; + use crate::packages::statistics; + use crate::{packages, CurrentClock}; struct CoreTrackerServices { pub core_config: Arc, @@ -649,10 +651,11 @@ mod tests { use std::sync::Arc; use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, Response, TransactionId}; - use bittorrent_tracker_core::statistics; use mockall::predicate::eq; + use packages::statistics; use super::{sample_ipv4_socket_address, sample_ipv6_remote_addr}; + use crate::packages; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_connect; use crate::servers::udp::handlers::tests::{ @@ -668,7 +671,7 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_the_same_transaction_id_as_the_connect_request() { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let request = ConnectRequest { @@ -688,7 +691,7 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_a_new_connection_id() { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let request = ConnectRequest { @@ -708,7 +711,7 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_a_new_connection_id_ipv6() { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let request = ConnectRequest { @@ -854,10 +857,11 @@ mod tests { }; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use bittorrent_tracker_core::{statistics, whitelist}; + use bittorrent_tracker_core::whitelist; use mockall::predicate::eq; use torrust_tracker_configuration::Core; + use crate::packages::{self, statistics}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ @@ -1013,7 +1017,7 @@ mod tests { announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); @@ -1155,10 +1159,11 @@ mod tests { }; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use bittorrent_tracker_core::{statistics, whitelist}; + use bittorrent_tracker_core::whitelist; use mockall::predicate::eq; use torrust_tracker_configuration::Core; + use crate::packages::{self, statistics}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ @@ -1318,7 +1323,7 @@ mod tests { announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { - let (stats_event_sender, _stats_repository) = bittorrent_tracker_core::statistics::setup::factory(false); + let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); @@ -1404,13 +1409,14 @@ mod tests { use aquatic_udp_protocol::{InfoHash as AquaticInfoHash, PeerId as AquaticPeerId}; use bittorrent_tracker_core::announce_handler::AnnounceHandler; use bittorrent_tracker_core::databases::setup::initialize_database; - use bittorrent_tracker_core::statistics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use mockall::predicate::eq; + use packages::statistics; + use crate::packages; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_announce; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; @@ -1505,10 +1511,11 @@ mod tests { TransactionId, }; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; - use bittorrent_tracker_core::statistics; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; + use packages::statistics; use super::{gen_remote_fingerprint, TorrentPeerBuilder}; + use crate::packages; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ @@ -1747,10 +1754,11 @@ mod tests { use std::future; use std::sync::Arc; - use bittorrent_tracker_core::statistics; use mockall::predicate::eq; + use packages::statistics; use super::sample_scrape_request; + use crate::packages; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, @@ -1788,10 +1796,11 @@ mod tests { use std::future; use std::sync::Arc; - use bittorrent_tracker_core::statistics; use mockall::predicate::eq; + use packages::statistics; use super::sample_scrape_request; + use crate::packages; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index bbf2718ff..24872771a 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use std::time::Duration; use bittorrent_tracker_client::udp::client::check; -use bittorrent_tracker_core::statistics; use derive_more::Constructor; use futures_util::StreamExt; +use packages::statistics; use tokio::select; use tokio::sync::oneshot; use tokio::time::interval; @@ -14,6 +14,7 @@ use tracing::instrument; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; use crate::container::UdpTrackerContainer; +use crate::packages; use crate::servers::logging::STARTED_ON; use crate::servers::registar::ServiceHealthCheckJob; use crate::servers::signals::{shutdown_signal_with_message, Halted}; diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index db444a04c..8a1ca64e3 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -4,13 +4,14 @@ use std::sync::Arc; use std::time::Duration; use aquatic_udp_protocol::Response; -use bittorrent_tracker_core::statistics; -use bittorrent_tracker_core::statistics::event::UdpResponseKind; +use packages::statistics; +use packages::statistics::event::UdpResponseKind; use tokio::time::Instant; use tracing::{instrument, Level}; use super::bound_socket::BoundSocket; use crate::container::UdpTrackerContainer; +use crate::packages; use crate::servers::udp::handlers::CookieTimeValues; use crate::servers::udp::{handlers, RawRequest}; diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index c91be1544..2828982f7 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -3,14 +3,15 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::authentication::handler::KeysHandler; use bittorrent_tracker_core::databases::Database; -use bittorrent_tracker_core::statistics::repository::Repository; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::whitelist::manager::WhitelistManager; use futures::executor::block_on; +use packages::statistics::repository::Repository; use torrust_tracker_configuration::Configuration; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::container::HttpTrackerContainer; +use torrust_tracker_lib::packages; use torrust_tracker_lib::servers::http::server::{HttpServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_primitives::peer; diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index 1483e1e5f..8e2e31f07 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -3,11 +3,12 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::databases::Database; -use bittorrent_tracker_core::statistics::repository::Repository; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::statistics::repository::Repository; use torrust_tracker_configuration::{Configuration, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::container::UdpTrackerContainer; +use torrust_tracker_lib::packages; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_lib::servers::udp::server::spawner::Spawner; use torrust_tracker_lib::servers::udp::server::states::{Running, Stopped}; From f99534a89194cbe91bbe6ddac52dfa69ec5a6f7e Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 11:01:33 +0000 Subject: [PATCH 3/9] refactor: [#1228] split statistics mod into UDO and HTTP statistics --- src/packages/http_tracker_core/mod.rs | 1 + .../statistics/event/handler.rs | 123 +++++++++++++ .../statistics/event/listener.rs | 11 ++ .../http_tracker_core/statistics/event/mod.rs | 21 +++ .../statistics/event/sender.rs | 29 +++ .../http_tracker_core/statistics/keeper.rs | 77 ++++++++ .../http_tracker_core/statistics/metrics.rs | 30 +++ .../http_tracker_core/statistics/mod.rs | 6 + .../statistics/repository.rs | 66 +++++++ .../http_tracker_core/statistics/services.rs | 104 +++++++++++ .../http_tracker_core/statistics/setup.rs | 54 ++++++ src/packages/mod.rs | 5 + src/packages/udp_tracker_core/mod.rs | 1 + .../statistics/event/handler.rs | 154 ++++++++++++++++ .../statistics/event/listener.rs | 11 ++ .../udp_tracker_core/statistics/event/mod.rs | 47 +++++ .../statistics/event/sender.rs | 29 +++ .../udp_tracker_core/statistics/keeper.rs | 77 ++++++++ .../udp_tracker_core/statistics/metrics.rs | 67 +++++++ .../udp_tracker_core/statistics/mod.rs | 6 + .../udp_tracker_core/statistics/repository.rs | 173 ++++++++++++++++++ .../udp_tracker_core/statistics/services.rs | 146 +++++++++++++++ .../udp_tracker_core/statistics/setup.rs | 54 ++++++ 23 files changed, 1292 insertions(+) create mode 100644 src/packages/http_tracker_core/mod.rs create mode 100644 src/packages/http_tracker_core/statistics/event/handler.rs create mode 100644 src/packages/http_tracker_core/statistics/event/listener.rs create mode 100644 src/packages/http_tracker_core/statistics/event/mod.rs create mode 100644 src/packages/http_tracker_core/statistics/event/sender.rs create mode 100644 src/packages/http_tracker_core/statistics/keeper.rs create mode 100644 src/packages/http_tracker_core/statistics/metrics.rs create mode 100644 src/packages/http_tracker_core/statistics/mod.rs create mode 100644 src/packages/http_tracker_core/statistics/repository.rs create mode 100644 src/packages/http_tracker_core/statistics/services.rs create mode 100644 src/packages/http_tracker_core/statistics/setup.rs create mode 100644 src/packages/udp_tracker_core/mod.rs create mode 100644 src/packages/udp_tracker_core/statistics/event/handler.rs create mode 100644 src/packages/udp_tracker_core/statistics/event/listener.rs create mode 100644 src/packages/udp_tracker_core/statistics/event/mod.rs create mode 100644 src/packages/udp_tracker_core/statistics/event/sender.rs create mode 100644 src/packages/udp_tracker_core/statistics/keeper.rs create mode 100644 src/packages/udp_tracker_core/statistics/metrics.rs create mode 100644 src/packages/udp_tracker_core/statistics/mod.rs create mode 100644 src/packages/udp_tracker_core/statistics/repository.rs create mode 100644 src/packages/udp_tracker_core/statistics/services.rs create mode 100644 src/packages/udp_tracker_core/statistics/setup.rs diff --git a/src/packages/http_tracker_core/mod.rs b/src/packages/http_tracker_core/mod.rs new file mode 100644 index 000000000..3449ec7b4 --- /dev/null +++ b/src/packages/http_tracker_core/mod.rs @@ -0,0 +1 @@ +pub mod statistics; diff --git a/src/packages/http_tracker_core/statistics/event/handler.rs b/src/packages/http_tracker_core/statistics/event/handler.rs new file mode 100644 index 000000000..caaf5d375 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/event/handler.rs @@ -0,0 +1,123 @@ +use crate::packages::http_tracker_core::statistics::event::Event; +use crate::packages::http_tracker_core::statistics::repository::Repository; + +pub async fn handle_event(event: Event, stats_repository: &Repository) { + match event { + // TCP4 + Event::Tcp4Announce => { + stats_repository.increase_tcp4_announces().await; + stats_repository.increase_tcp4_connections().await; + } + Event::Tcp4Scrape => { + stats_repository.increase_tcp4_scrapes().await; + stats_repository.increase_tcp4_connections().await; + } + + // TCP6 + Event::Tcp6Announce => { + stats_repository.increase_tcp6_announces().await; + stats_repository.increase_tcp6_connections().await; + } + Event::Tcp6Scrape => { + stats_repository.increase_tcp6_scrapes().await; + stats_repository.increase_tcp6_connections().await; + } + } + + tracing::debug!("stats: {:?}", stats_repository.get_stats().await); +} + +#[cfg(test)] +mod tests { + use crate::packages::http_tracker_core::statistics::event::handler::handle_event; + use crate::packages::http_tracker_core::statistics::event::Event; + use crate::packages::http_tracker_core::statistics::repository::Repository; + + #[tokio::test] + async fn should_increase_the_tcp4_announces_counter_when_it_receives_a_tcp4_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp4Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp4_announces_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp4_connections_counter_when_it_receives_a_tcp4_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp4Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp4_connections_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp4_scrapes_counter_when_it_receives_a_tcp4_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp4Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp4_scrapes_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp4_connections_counter_when_it_receives_a_tcp4_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp4Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp4_connections_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp6_announces_counter_when_it_receives_a_tcp6_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp6Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp6_announces_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp6_connections_counter_when_it_receives_a_tcp6_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp6Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp6_connections_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp6_scrapes_counter_when_it_receives_a_tcp6_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp6Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp6_scrapes_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_tcp6_connections_counter_when_it_receives_a_tcp6_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Tcp6Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.tcp6_connections_handled, 1); + } +} diff --git a/src/packages/http_tracker_core/statistics/event/listener.rs b/src/packages/http_tracker_core/statistics/event/listener.rs new file mode 100644 index 000000000..ed574a36b --- /dev/null +++ b/src/packages/http_tracker_core/statistics/event/listener.rs @@ -0,0 +1,11 @@ +use tokio::sync::mpsc; + +use super::handler::handle_event; +use super::Event; +use crate::packages::http_tracker_core::statistics::repository::Repository; + +pub async fn dispatch_events(mut receiver: mpsc::Receiver, stats_repository: Repository) { + while let Some(event) = receiver.recv().await { + handle_event(event, &stats_repository).await; + } +} diff --git a/src/packages/http_tracker_core/statistics/event/mod.rs b/src/packages/http_tracker_core/statistics/event/mod.rs new file mode 100644 index 000000000..e25148666 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/event/mod.rs @@ -0,0 +1,21 @@ +pub mod handler; +pub mod listener; +pub mod sender; + +/// An statistics event. It is used to collect tracker metrics. +/// +/// - `Tcp` prefix means the event was triggered by the HTTP tracker +/// - `Udp` prefix means the event was triggered by the UDP tracker +/// - `4` or `6` prefixes means the IP version used by the peer +/// - Finally the event suffix is the type of request: `announce`, `scrape` or `connection` +/// +/// > NOTE: HTTP trackers do not use `connection` requests. +#[derive(Debug, PartialEq, Eq)] +pub enum Event { + // code-review: consider one single event for request type with data: Event::Announce { scheme: HTTPorUDP, ip_version: V4orV6 } + // Attributes are enums too. + Tcp4Announce, + Tcp4Scrape, + Tcp6Announce, + Tcp6Scrape, +} diff --git a/src/packages/http_tracker_core/statistics/event/sender.rs b/src/packages/http_tracker_core/statistics/event/sender.rs new file mode 100644 index 000000000..279d50962 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/event/sender.rs @@ -0,0 +1,29 @@ +use futures::future::BoxFuture; +use futures::FutureExt; +#[cfg(test)] +use mockall::{automock, predicate::str}; +use tokio::sync::mpsc; +use tokio::sync::mpsc::error::SendError; + +use super::Event; + +/// A trait to allow sending statistics events +#[cfg_attr(test, automock)] +pub trait Sender: Sync + Send { + fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>>; +} + +/// An [`statistics::EventSender`](crate::packages::http_tracker_core::statistics::event::sender::Sender) implementation. +/// +/// It uses a channel sender to send the statistic events. The channel is created by a +/// [`statistics::Keeper`](crate::packages::http_tracker_core::statistics::keeper::Keeper) +#[allow(clippy::module_name_repetitions)] +pub struct ChannelSender { + pub(crate) sender: mpsc::Sender, +} + +impl Sender for ChannelSender { + fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>> { + async move { Some(self.sender.send(event).await) }.boxed() + } +} diff --git a/src/packages/http_tracker_core/statistics/keeper.rs b/src/packages/http_tracker_core/statistics/keeper.rs new file mode 100644 index 000000000..01ae5e6b3 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/keeper.rs @@ -0,0 +1,77 @@ +use tokio::sync::mpsc; + +use super::event::listener::dispatch_events; +use super::event::sender::{ChannelSender, Sender}; +use super::event::Event; +use super::repository::Repository; + +const CHANNEL_BUFFER_SIZE: usize = 65_535; + +/// The service responsible for keeping tracker metrics (listening to statistics events and handle them). +/// +/// It actively listen to new statistics events. When it receives a new event +/// it accordingly increases the counters. +pub struct Keeper { + pub repository: Repository, +} + +impl Default for Keeper { + fn default() -> Self { + Self::new() + } +} + +impl Keeper { + #[must_use] + pub fn new() -> Self { + Self { + repository: Repository::new(), + } + } + + #[must_use] + pub fn new_active_instance() -> (Box, Repository) { + let mut stats_tracker = Self::new(); + + let stats_event_sender = stats_tracker.run_event_listener(); + + (stats_event_sender, stats_tracker.repository) + } + + pub fn run_event_listener(&mut self) -> Box { + let (sender, receiver) = mpsc::channel::(CHANNEL_BUFFER_SIZE); + + let stats_repository = self.repository.clone(); + + tokio::spawn(async move { dispatch_events(receiver, stats_repository).await }); + + Box::new(ChannelSender { sender }) + } +} + +#[cfg(test)] +mod tests { + use crate::packages::http_tracker_core::statistics::event::Event; + use crate::packages::http_tracker_core::statistics::keeper::Keeper; + use crate::packages::http_tracker_core::statistics::metrics::Metrics; + + #[tokio::test] + async fn should_contain_the_tracker_statistics() { + let stats_tracker = Keeper::new(); + + let stats = stats_tracker.repository.get_stats().await; + + assert_eq!(stats.tcp4_announces_handled, Metrics::default().tcp4_announces_handled); + } + + #[tokio::test] + async fn should_create_an_event_sender_to_send_statistical_events() { + let mut stats_tracker = Keeper::new(); + + let event_sender = stats_tracker.run_event_listener(); + + let result = event_sender.send_event(Event::Tcp4Announce).await; + + assert!(result.is_some()); + } +} diff --git a/src/packages/http_tracker_core/statistics/metrics.rs b/src/packages/http_tracker_core/statistics/metrics.rs new file mode 100644 index 000000000..ae4db9704 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/metrics.rs @@ -0,0 +1,30 @@ +/// Metrics collected by the tracker. +/// +/// - Number of connections handled +/// - Number of `announce` requests handled +/// - Number of `scrape` request handled +/// +/// These metrics are collected for each connection type: UDP and HTTP +/// and also for each IP version used by the peers: IPv4 and IPv6. +#[derive(Debug, PartialEq, Default)] +pub struct Metrics { + /// Total number of TCP (HTTP tracker) connections from IPv4 peers. + /// Since the HTTP tracker spec does not require a handshake, this metric + /// increases for every HTTP request. + pub tcp4_connections_handled: u64, + + /// Total number of TCP (HTTP tracker) `announce` requests from IPv4 peers. + pub tcp4_announces_handled: u64, + + /// Total number of TCP (HTTP tracker) `scrape` requests from IPv4 peers. + pub tcp4_scrapes_handled: u64, + + /// Total number of TCP (HTTP tracker) connections from IPv6 peers. + pub tcp6_connections_handled: u64, + + /// Total number of TCP (HTTP tracker) `announce` requests from IPv6 peers. + pub tcp6_announces_handled: u64, + + /// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers. + pub tcp6_scrapes_handled: u64, +} diff --git a/src/packages/http_tracker_core/statistics/mod.rs b/src/packages/http_tracker_core/statistics/mod.rs new file mode 100644 index 000000000..939a41061 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/mod.rs @@ -0,0 +1,6 @@ +pub mod event; +pub mod keeper; +pub mod metrics; +pub mod repository; +pub mod services; +pub mod setup; diff --git a/src/packages/http_tracker_core/statistics/repository.rs b/src/packages/http_tracker_core/statistics/repository.rs new file mode 100644 index 000000000..41f048e29 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/repository.rs @@ -0,0 +1,66 @@ +use std::sync::Arc; + +use tokio::sync::{RwLock, RwLockReadGuard}; + +use super::metrics::Metrics; + +/// A repository for the tracker metrics. +#[derive(Clone)] +pub struct Repository { + pub stats: Arc>, +} + +impl Default for Repository { + fn default() -> Self { + Self::new() + } +} + +impl Repository { + #[must_use] + pub fn new() -> Self { + Self { + stats: Arc::new(RwLock::new(Metrics::default())), + } + } + + pub async fn get_stats(&self) -> RwLockReadGuard<'_, Metrics> { + self.stats.read().await + } + + pub async fn increase_tcp4_announces(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp4_announces_handled += 1; + drop(stats_lock); + } + + pub async fn increase_tcp4_connections(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp4_connections_handled += 1; + drop(stats_lock); + } + + pub async fn increase_tcp4_scrapes(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp4_scrapes_handled += 1; + drop(stats_lock); + } + + pub async fn increase_tcp6_announces(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp6_announces_handled += 1; + drop(stats_lock); + } + + pub async fn increase_tcp6_connections(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp6_connections_handled += 1; + drop(stats_lock); + } + + pub async fn increase_tcp6_scrapes(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.tcp6_scrapes_handled += 1; + drop(stats_lock); + } +} diff --git a/src/packages/http_tracker_core/statistics/services.rs b/src/packages/http_tracker_core/statistics/services.rs new file mode 100644 index 000000000..11e3a70c4 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/services.rs @@ -0,0 +1,104 @@ +//! Statistics services. +//! +//! It includes: +//! +//! - A [`factory`](crate::packages::http_tracker_core::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. +//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::packages::http_tracker_core::statistics::metrics::Metrics). +//! +//! Tracker metrics are collected using a Publisher-Subscribe pattern. +//! +//! The factory function builds two structs: +//! +//! - An statistics event [`Sender`](crate::packages::http_tracker_core::statistics::event::sender::Sender) +//! - An statistics [`Repository`] +//! +//! ```text +//! let (stats_event_sender, stats_repository) = factory(tracker_usage_statistics); +//! ``` +//! +//! The statistics repository is responsible for storing the metrics in memory. +//! The statistics event sender allows sending events related to metrics. +//! There is an event listener that is receiving all the events and processing them with an event handler. +//! Then, the event handler updates the metrics depending on the received event. +use std::sync::Arc; + +use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::http_tracker_core::statistics::metrics::Metrics; +use packages::http_tracker_core::statistics::repository::Repository; +use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + +use crate::packages; + +/// All the metrics collected by the tracker. +#[derive(Debug, PartialEq)] +pub struct TrackerMetrics { + /// Domain level metrics. + /// + /// General metrics for all torrents (number of seeders, leechers, etcetera) + pub torrents_metrics: TorrentsMetrics, + + /// Application level metrics. Usage statistics/metrics. + /// + /// Metrics about how the tracker is been used (number of number of http scrape requests, etcetera) + pub protocol_metrics: Metrics, +} + +/// It returns all the [`TrackerMetrics`] +pub async fn get_metrics( + in_memory_torrent_repository: Arc, + stats_repository: Arc, +) -> TrackerMetrics { + let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics(); + let stats = stats_repository.get_stats().await; + + TrackerMetrics { + torrents_metrics, + protocol_metrics: Metrics { + // TCPv4 + tcp4_connections_handled: stats.tcp4_connections_handled, + tcp4_announces_handled: stats.tcp4_announces_handled, + tcp4_scrapes_handled: stats.tcp4_scrapes_handled, + // TCPv6 + tcp6_connections_handled: stats.tcp6_connections_handled, + tcp6_announces_handled: stats.tcp6_announces_handled, + tcp6_scrapes_handled: stats.tcp6_scrapes_handled, + }, + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; + use bittorrent_tracker_core::{self}; + use torrust_tracker_configuration::Configuration; + use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + use torrust_tracker_test_helpers::configuration; + + use crate::packages::http_tracker_core::statistics; + use crate::packages::http_tracker_core::statistics::services::{get_metrics, TrackerMetrics}; + + pub fn tracker_configuration() -> Configuration { + configuration::ephemeral() + } + + #[tokio::test] + async fn the_statistics_service_should_return_the_tracker_metrics() { + let config = tracker_configuration(); + + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_repository = Arc::new(stats_repository); + + let tracker_metrics = get_metrics(in_memory_torrent_repository.clone(), stats_repository.clone()).await; + + assert_eq!( + tracker_metrics, + TrackerMetrics { + torrents_metrics: TorrentsMetrics::default(), + protocol_metrics: statistics::metrics::Metrics::default(), + } + ); + } +} diff --git a/src/packages/http_tracker_core/statistics/setup.rs b/src/packages/http_tracker_core/statistics/setup.rs new file mode 100644 index 000000000..009f157d5 --- /dev/null +++ b/src/packages/http_tracker_core/statistics/setup.rs @@ -0,0 +1,54 @@ +//! Setup for the tracker statistics. +//! +//! The [`factory`] function builds the structs needed for handling the tracker metrics. +use crate::packages::http_tracker_core::statistics; + +/// It builds the structs needed for handling the tracker metrics. +/// +/// It returns: +/// +/// - An statistics event [`Sender`](crate::packages::http_tracker_core::statistics::event::sender::Sender) that allows you to send events related to statistics. +/// - An statistics [`Repository`](crate::packages::http_tracker_core::statistics::repository::Repository) which is an in-memory repository for the tracker metrics. +/// +/// When the input argument `tracker_usage_statistics`is false the setup does not run the event listeners, consequently the statistics +/// events are sent are received but not dispatched to the handler. +#[must_use] +pub fn factory( + tracker_usage_statistics: bool, +) -> ( + Option>, + statistics::repository::Repository, +) { + let mut stats_event_sender = None; + + let mut stats_tracker = statistics::keeper::Keeper::new(); + + if tracker_usage_statistics { + stats_event_sender = Some(stats_tracker.run_event_listener()); + } + + (stats_event_sender, stats_tracker.repository) +} + +#[cfg(test)] +mod test { + use super::factory; + + #[tokio::test] + async fn should_not_send_any_event_when_statistics_are_disabled() { + let tracker_usage_statistics = false; + + let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); + + assert!(stats_event_sender.is_none()); + } + + #[tokio::test] + async fn should_send_events_when_statistics_are_enabled() { + let tracker_usage_statistics = true; + + let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); + + assert!(stats_event_sender.is_some()); + } +} diff --git a/src/packages/mod.rs b/src/packages/mod.rs index 3449ec7b4..9e0bbec90 100644 --- a/src/packages/mod.rs +++ b/src/packages/mod.rs @@ -1 +1,6 @@ +//! This module contains logic pending to be extracted into workspace packages. +//! +//! It will be moved to the directory `packages`. +pub mod http_tracker_core; pub mod statistics; +pub mod udp_tracker_core; diff --git a/src/packages/udp_tracker_core/mod.rs b/src/packages/udp_tracker_core/mod.rs new file mode 100644 index 000000000..3449ec7b4 --- /dev/null +++ b/src/packages/udp_tracker_core/mod.rs @@ -0,0 +1 @@ +pub mod statistics; diff --git a/src/packages/udp_tracker_core/statistics/event/handler.rs b/src/packages/udp_tracker_core/statistics/event/handler.rs new file mode 100644 index 000000000..d696951d3 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/event/handler.rs @@ -0,0 +1,154 @@ +use crate::packages::udp_tracker_core::statistics::event::{Event, UdpResponseKind}; +use crate::packages::udp_tracker_core::statistics::repository::Repository; + +pub async fn handle_event(event: Event, stats_repository: &Repository) { + match event { + // UDP + Event::UdpRequestAborted => { + stats_repository.increase_udp_requests_aborted().await; + } + Event::UdpRequestBanned => { + stats_repository.increase_udp_requests_banned().await; + } + + // UDP4 + Event::Udp4Request => { + stats_repository.increase_udp4_requests().await; + } + Event::Udp4Connect => { + stats_repository.increase_udp4_connections().await; + } + Event::Udp4Announce => { + stats_repository.increase_udp4_announces().await; + } + Event::Udp4Scrape => { + stats_repository.increase_udp4_scrapes().await; + } + Event::Udp4Response { + kind, + req_processing_time, + } => { + stats_repository.increase_udp4_responses().await; + + match kind { + UdpResponseKind::Connect => { + stats_repository + .recalculate_udp_avg_connect_processing_time_ns(req_processing_time) + .await; + } + UdpResponseKind::Announce => { + stats_repository + .recalculate_udp_avg_announce_processing_time_ns(req_processing_time) + .await; + } + UdpResponseKind::Scrape => { + stats_repository + .recalculate_udp_avg_scrape_processing_time_ns(req_processing_time) + .await; + } + UdpResponseKind::Error => {} + } + } + Event::Udp4Error => { + stats_repository.increase_udp4_errors().await; + } + + // UDP6 + Event::Udp6Request => { + stats_repository.increase_udp6_requests().await; + } + Event::Udp6Connect => { + stats_repository.increase_udp6_connections().await; + } + Event::Udp6Announce => { + stats_repository.increase_udp6_announces().await; + } + Event::Udp6Scrape => { + stats_repository.increase_udp6_scrapes().await; + } + Event::Udp6Response { + kind: _, + req_processing_time: _, + } => { + stats_repository.increase_udp6_responses().await; + } + Event::Udp6Error => { + stats_repository.increase_udp6_errors().await; + } + } + + tracing::debug!("stats: {:?}", stats_repository.get_stats().await); +} + +#[cfg(test)] +mod tests { + use crate::packages::udp_tracker_core::statistics::event::handler::handle_event; + use crate::packages::udp_tracker_core::statistics::event::Event; + use crate::packages::udp_tracker_core::statistics::repository::Repository; + + #[tokio::test] + async fn should_increase_the_udp4_connections_counter_when_it_receives_a_udp4_connect_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp4Connect, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp4_connections_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_udp4_announces_counter_when_it_receives_a_udp4_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp4Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp4_announces_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_udp4_scrapes_counter_when_it_receives_a_udp4_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp4Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp4_scrapes_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_udp6_connections_counter_when_it_receives_a_udp6_connect_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp6Connect, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp6_connections_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_udp6_announces_counter_when_it_receives_a_udp6_announce_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp6Announce, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp6_announces_handled, 1); + } + + #[tokio::test] + async fn should_increase_the_udp6_scrapes_counter_when_it_receives_a_udp6_scrape_event() { + let stats_repository = Repository::new(); + + handle_event(Event::Udp6Scrape, &stats_repository).await; + + let stats = stats_repository.get_stats().await; + + assert_eq!(stats.udp6_scrapes_handled, 1); + } +} diff --git a/src/packages/udp_tracker_core/statistics/event/listener.rs b/src/packages/udp_tracker_core/statistics/event/listener.rs new file mode 100644 index 000000000..6a84fbaa5 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/event/listener.rs @@ -0,0 +1,11 @@ +use tokio::sync::mpsc; + +use super::handler::handle_event; +use super::Event; +use crate::packages::udp_tracker_core::statistics::repository::Repository; + +pub async fn dispatch_events(mut receiver: mpsc::Receiver, stats_repository: Repository) { + while let Some(event) = receiver.recv().await { + handle_event(event, &stats_repository).await; + } +} diff --git a/src/packages/udp_tracker_core/statistics/event/mod.rs b/src/packages/udp_tracker_core/statistics/event/mod.rs new file mode 100644 index 000000000..6a5343933 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/event/mod.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +pub mod handler; +pub mod listener; +pub mod sender; + +/// An statistics event. It is used to collect tracker metrics. +/// +/// - `Tcp` prefix means the event was triggered by the HTTP tracker +/// - `Udp` prefix means the event was triggered by the UDP tracker +/// - `4` or `6` prefixes means the IP version used by the peer +/// - Finally the event suffix is the type of request: `announce`, `scrape` or `connection` +/// +/// > NOTE: HTTP trackers do not use `connection` requests. +#[derive(Debug, PartialEq, Eq)] +pub enum Event { + // code-review: consider one single event for request type with data: Event::Announce { scheme: HTTPorUDP, ip_version: V4orV6 } + // Attributes are enums too. + UdpRequestAborted, + UdpRequestBanned, + Udp4Request, + Udp4Connect, + Udp4Announce, + Udp4Scrape, + Udp4Response { + kind: UdpResponseKind, + req_processing_time: Duration, + }, + Udp4Error, + Udp6Request, + Udp6Connect, + Udp6Announce, + Udp6Scrape, + Udp6Response { + kind: UdpResponseKind, + req_processing_time: Duration, + }, + Udp6Error, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum UdpResponseKind { + Connect, + Announce, + Scrape, + Error, +} diff --git a/src/packages/udp_tracker_core/statistics/event/sender.rs b/src/packages/udp_tracker_core/statistics/event/sender.rs new file mode 100644 index 000000000..68e197eca --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/event/sender.rs @@ -0,0 +1,29 @@ +use futures::future::BoxFuture; +use futures::FutureExt; +#[cfg(test)] +use mockall::{automock, predicate::str}; +use tokio::sync::mpsc; +use tokio::sync::mpsc::error::SendError; + +use super::Event; + +/// A trait to allow sending statistics events +#[cfg_attr(test, automock)] +pub trait Sender: Sync + Send { + fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>>; +} + +/// An [`statistics::EventSender`](crate::packages::udp_tracker_core::statistics::event::sender::Sender) implementation. +/// +/// It uses a channel sender to send the statistic events. The channel is created by a +/// [`statistics::Keeper`](crate::packages::udp_tracker_core::statistics::keeper::Keeper) +#[allow(clippy::module_name_repetitions)] +pub struct ChannelSender { + pub(crate) sender: mpsc::Sender, +} + +impl Sender for ChannelSender { + fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>> { + async move { Some(self.sender.send(event).await) }.boxed() + } +} diff --git a/src/packages/udp_tracker_core/statistics/keeper.rs b/src/packages/udp_tracker_core/statistics/keeper.rs new file mode 100644 index 000000000..9bd290145 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/keeper.rs @@ -0,0 +1,77 @@ +use tokio::sync::mpsc; + +use super::event::listener::dispatch_events; +use super::event::sender::{ChannelSender, Sender}; +use super::event::Event; +use super::repository::Repository; + +const CHANNEL_BUFFER_SIZE: usize = 65_535; + +/// The service responsible for keeping tracker metrics (listening to statistics events and handle them). +/// +/// It actively listen to new statistics events. When it receives a new event +/// it accordingly increases the counters. +pub struct Keeper { + pub repository: Repository, +} + +impl Default for Keeper { + fn default() -> Self { + Self::new() + } +} + +impl Keeper { + #[must_use] + pub fn new() -> Self { + Self { + repository: Repository::new(), + } + } + + #[must_use] + pub fn new_active_instance() -> (Box, Repository) { + let mut stats_tracker = Self::new(); + + let stats_event_sender = stats_tracker.run_event_listener(); + + (stats_event_sender, stats_tracker.repository) + } + + pub fn run_event_listener(&mut self) -> Box { + let (sender, receiver) = mpsc::channel::(CHANNEL_BUFFER_SIZE); + + let stats_repository = self.repository.clone(); + + tokio::spawn(async move { dispatch_events(receiver, stats_repository).await }); + + Box::new(ChannelSender { sender }) + } +} + +#[cfg(test)] +mod tests { + use crate::packages::udp_tracker_core::statistics::event::Event; + use crate::packages::udp_tracker_core::statistics::keeper::Keeper; + use crate::packages::udp_tracker_core::statistics::metrics::Metrics; + + #[tokio::test] + async fn should_contain_the_tracker_statistics() { + let stats_tracker = Keeper::new(); + + let stats = stats_tracker.repository.get_stats().await; + + assert_eq!(stats.udp4_announces_handled, Metrics::default().udp4_announces_handled); + } + + #[tokio::test] + async fn should_create_an_event_sender_to_send_statistical_events() { + let mut stats_tracker = Keeper::new(); + + let event_sender = stats_tracker.run_event_listener(); + + let result = event_sender.send_event(Event::Udp4Connect).await; + + assert!(result.is_some()); + } +} diff --git a/src/packages/udp_tracker_core/statistics/metrics.rs b/src/packages/udp_tracker_core/statistics/metrics.rs new file mode 100644 index 000000000..23357aab6 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/metrics.rs @@ -0,0 +1,67 @@ +/// Metrics collected by the tracker. +/// +/// - Number of connections handled +/// - Number of `announce` requests handled +/// - Number of `scrape` request handled +/// +/// These metrics are collected for each connection type: UDP and HTTP +/// and also for each IP version used by the peers: IPv4 and IPv6. +#[derive(Debug, PartialEq, Default)] +pub struct Metrics { + // UDP + /// Total number of UDP (UDP tracker) requests aborted. + pub udp_requests_aborted: u64, + + /// Total number of UDP (UDP tracker) requests banned. + pub udp_requests_banned: u64, + + /// Total number of banned IPs. + pub udp_banned_ips_total: u64, + + /// Average rounded time spent processing UDP connect requests. + pub udp_avg_connect_processing_time_ns: u64, + + /// Average rounded time spent processing UDP announce requests. + pub udp_avg_announce_processing_time_ns: u64, + + /// Average rounded time spent processing UDP scrape requests. + pub udp_avg_scrape_processing_time_ns: u64, + + // UDPv4 + /// Total number of UDP (UDP tracker) requests from IPv4 peers. + pub udp4_requests: u64, + + /// Total number of UDP (UDP tracker) connections from IPv4 peers. + pub udp4_connections_handled: u64, + + /// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers. + pub udp4_announces_handled: u64, + + /// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers. + pub udp4_scrapes_handled: u64, + + /// Total number of UDP (UDP tracker) responses from IPv4 peers. + pub udp4_responses: u64, + + /// Total number of UDP (UDP tracker) `error` requests from IPv4 peers. + pub udp4_errors_handled: u64, + + // UDPv6 + /// Total number of UDP (UDP tracker) requests from IPv6 peers. + pub udp6_requests: u64, + + /// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers. + pub udp6_connections_handled: u64, + + /// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers. + pub udp6_announces_handled: u64, + + /// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers. + pub udp6_scrapes_handled: u64, + + /// Total number of UDP (UDP tracker) responses from IPv6 peers. + pub udp6_responses: u64, + + /// Total number of UDP (UDP tracker) `error` requests from IPv6 peers. + pub udp6_errors_handled: u64, +} diff --git a/src/packages/udp_tracker_core/statistics/mod.rs b/src/packages/udp_tracker_core/statistics/mod.rs new file mode 100644 index 000000000..939a41061 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/mod.rs @@ -0,0 +1,6 @@ +pub mod event; +pub mod keeper; +pub mod metrics; +pub mod repository; +pub mod services; +pub mod setup; diff --git a/src/packages/udp_tracker_core/statistics/repository.rs b/src/packages/udp_tracker_core/statistics/repository.rs new file mode 100644 index 000000000..22e793036 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/repository.rs @@ -0,0 +1,173 @@ +use std::sync::Arc; +use std::time::Duration; + +use tokio::sync::{RwLock, RwLockReadGuard}; + +use super::metrics::Metrics; + +/// A repository for the tracker metrics. +#[derive(Clone)] +pub struct Repository { + pub stats: Arc>, +} + +impl Default for Repository { + fn default() -> Self { + Self::new() + } +} + +impl Repository { + #[must_use] + pub fn new() -> Self { + Self { + stats: Arc::new(RwLock::new(Metrics::default())), + } + } + + pub async fn get_stats(&self) -> RwLockReadGuard<'_, Metrics> { + self.stats.read().await + } + + pub async fn increase_udp_requests_aborted(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp_requests_aborted += 1; + drop(stats_lock); + } + + pub async fn increase_udp_requests_banned(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp_requests_banned += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_requests(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_requests += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_connections(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_connections_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_announces(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_announces_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_scrapes(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_scrapes_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_responses(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_responses += 1; + drop(stats_lock); + } + + pub async fn increase_udp4_errors(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp4_errors_handled += 1; + drop(stats_lock); + } + + #[allow(clippy::cast_precision_loss)] + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + pub async fn recalculate_udp_avg_connect_processing_time_ns(&self, req_processing_time: Duration) { + let mut stats_lock = self.stats.write().await; + + let req_processing_time = req_processing_time.as_nanos() as f64; + let udp_connections_handled = (stats_lock.udp4_connections_handled + stats_lock.udp6_connections_handled) as f64; + + let previous_avg = stats_lock.udp_avg_connect_processing_time_ns; + + // Moving average: https://en.wikipedia.org/wiki/Moving_average + let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_connections_handled; + + stats_lock.udp_avg_connect_processing_time_ns = new_avg.ceil() as u64; + + drop(stats_lock); + } + + #[allow(clippy::cast_precision_loss)] + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + pub async fn recalculate_udp_avg_announce_processing_time_ns(&self, req_processing_time: Duration) { + let mut stats_lock = self.stats.write().await; + + let req_processing_time = req_processing_time.as_nanos() as f64; + + let udp_announces_handled = (stats_lock.udp4_announces_handled + stats_lock.udp6_announces_handled) as f64; + + let previous_avg = stats_lock.udp_avg_announce_processing_time_ns; + + // Moving average: https://en.wikipedia.org/wiki/Moving_average + let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_announces_handled; + + stats_lock.udp_avg_announce_processing_time_ns = new_avg.ceil() as u64; + + drop(stats_lock); + } + + #[allow(clippy::cast_precision_loss)] + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + pub async fn recalculate_udp_avg_scrape_processing_time_ns(&self, req_processing_time: Duration) { + let mut stats_lock = self.stats.write().await; + + let req_processing_time = req_processing_time.as_nanos() as f64; + let udp_scrapes_handled = (stats_lock.udp4_scrapes_handled + stats_lock.udp6_scrapes_handled) as f64; + + let previous_avg = stats_lock.udp_avg_scrape_processing_time_ns; + + // Moving average: https://en.wikipedia.org/wiki/Moving_average + let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_scrapes_handled; + + stats_lock.udp_avg_scrape_processing_time_ns = new_avg.ceil() as u64; + + drop(stats_lock); + } + + pub async fn increase_udp6_requests(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_requests += 1; + drop(stats_lock); + } + + pub async fn increase_udp6_connections(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_connections_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp6_announces(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_announces_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp6_scrapes(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_scrapes_handled += 1; + drop(stats_lock); + } + + pub async fn increase_udp6_responses(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_responses += 1; + drop(stats_lock); + } + + pub async fn increase_udp6_errors(&self) { + let mut stats_lock = self.stats.write().await; + stats_lock.udp6_errors_handled += 1; + drop(stats_lock); + } +} diff --git a/src/packages/udp_tracker_core/statistics/services.rs b/src/packages/udp_tracker_core/statistics/services.rs new file mode 100644 index 000000000..85ca08e54 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/services.rs @@ -0,0 +1,146 @@ +//! Statistics services. +//! +//! It includes: +//! +//! - A [`factory`](crate::packages::udp_tracker_core::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. +//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::packages::udp_tracker_core::statistics::metrics::Metrics). +//! +//! Tracker metrics are collected using a Publisher-Subscribe pattern. +//! +//! The factory function builds two structs: +//! +//! - An statistics event [`Sender`](crate::packages::udp_tracker_core::statistics::event::sender::Sender) +//! - An statistics [`Repository`] +//! +//! ```text +//! let (stats_event_sender, stats_repository) = factory(tracker_usage_statistics); +//! ``` +//! +//! The statistics repository is responsible for storing the metrics in memory. +//! The statistics event sender allows sending events related to metrics. +//! There is an event listener that is receiving all the events and processing them with an event handler. +//! Then, the event handler updates the metrics depending on the received event. +//! +//! For example, if you send the event [`Event::Udp4Connect`](crate::packages::udp_tracker_core::statistics::event::Event::Udp4Connect): +//! +//! ```text +//! let result = event_sender.send_event(Event::Udp4Connect).await; +//! ``` +//! +//! Eventually the counter for UDP connections from IPv4 peers will be increased. +//! +//! ```rust,no_run +//! pub struct Metrics { +//! // ... +//! pub udp4_connections_handled: u64, // This will be incremented +//! // ... +//! } +//! ``` +use std::sync::Arc; + +use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::udp_tracker_core::statistics::metrics::Metrics; +use packages::udp_tracker_core::statistics::repository::Repository; +use tokio::sync::RwLock; +use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + +use crate::packages; +use crate::servers::udp::server::banning::BanService; + +/// All the metrics collected by the tracker. +#[derive(Debug, PartialEq)] +pub struct TrackerMetrics { + /// Domain level metrics. + /// + /// General metrics for all torrents (number of seeders, leechers, etcetera) + pub torrents_metrics: TorrentsMetrics, + + /// Application level metrics. Usage statistics/metrics. + /// + /// Metrics about how the tracker is been used (number of udp announce requests, etcetera) + pub protocol_metrics: Metrics, +} + +/// It returns all the [`TrackerMetrics`] +pub async fn get_metrics( + in_memory_torrent_repository: Arc, + ban_service: Arc>, + stats_repository: Arc, +) -> TrackerMetrics { + let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics(); + let stats = stats_repository.get_stats().await; + let udp_banned_ips_total = ban_service.read().await.get_banned_ips_total(); + + TrackerMetrics { + torrents_metrics, + protocol_metrics: Metrics { + // UDP + udp_requests_aborted: stats.udp_requests_aborted, + udp_requests_banned: stats.udp_requests_banned, + udp_banned_ips_total: udp_banned_ips_total as u64, + udp_avg_connect_processing_time_ns: stats.udp_avg_connect_processing_time_ns, + udp_avg_announce_processing_time_ns: stats.udp_avg_announce_processing_time_ns, + udp_avg_scrape_processing_time_ns: stats.udp_avg_scrape_processing_time_ns, + // UDPv4 + udp4_requests: stats.udp4_requests, + udp4_connections_handled: stats.udp4_connections_handled, + udp4_announces_handled: stats.udp4_announces_handled, + udp4_scrapes_handled: stats.udp4_scrapes_handled, + udp4_responses: stats.udp4_responses, + udp4_errors_handled: stats.udp4_errors_handled, + // UDPv6 + udp6_requests: stats.udp6_requests, + udp6_connections_handled: stats.udp6_connections_handled, + udp6_announces_handled: stats.udp6_announces_handled, + udp6_scrapes_handled: stats.udp6_scrapes_handled, + udp6_responses: stats.udp6_responses, + udp6_errors_handled: stats.udp6_errors_handled, + }, + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; + use bittorrent_tracker_core::{self}; + use tokio::sync::RwLock; + use torrust_tracker_configuration::Configuration; + use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + use torrust_tracker_test_helpers::configuration; + + use crate::packages::udp_tracker_core::statistics; + use crate::packages::udp_tracker_core::statistics::services::{get_metrics, TrackerMetrics}; + use crate::servers::udp::server::banning::BanService; + use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; + + pub fn tracker_configuration() -> Configuration { + configuration::ephemeral() + } + + #[tokio::test] + async fn the_statistics_service_should_return_the_tracker_metrics() { + let config = tracker_configuration(); + + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_repository = Arc::new(stats_repository); + let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); + + let tracker_metrics = get_metrics( + in_memory_torrent_repository.clone(), + ban_service.clone(), + stats_repository.clone(), + ) + .await; + + assert_eq!( + tracker_metrics, + TrackerMetrics { + torrents_metrics: TorrentsMetrics::default(), + protocol_metrics: statistics::metrics::Metrics::default(), + } + ); + } +} diff --git a/src/packages/udp_tracker_core/statistics/setup.rs b/src/packages/udp_tracker_core/statistics/setup.rs new file mode 100644 index 000000000..c85c715a2 --- /dev/null +++ b/src/packages/udp_tracker_core/statistics/setup.rs @@ -0,0 +1,54 @@ +//! Setup for the tracker statistics. +//! +//! The [`factory`] function builds the structs needed for handling the tracker metrics. +use crate::packages::udp_tracker_core::statistics; + +/// It builds the structs needed for handling the tracker metrics. +/// +/// It returns: +/// +/// - An statistics event [`Sender`](crate::packages::udp_tracker_core::statistics::event::sender::Sender) that allows you to send events related to statistics. +/// - An statistics [`Repository`](crate::packages::udp_tracker_core::statistics::repository::Repository) which is an in-memory repository for the tracker metrics. +/// +/// When the input argument `tracker_usage_statistics`is false the setup does not run the event listeners, consequently the statistics +/// events are sent are received but not dispatched to the handler. +#[must_use] +pub fn factory( + tracker_usage_statistics: bool, +) -> ( + Option>, + statistics::repository::Repository, +) { + let mut stats_event_sender = None; + + let mut stats_tracker = statistics::keeper::Keeper::new(); + + if tracker_usage_statistics { + stats_event_sender = Some(stats_tracker.run_event_listener()); + } + + (stats_event_sender, stats_tracker.repository) +} + +#[cfg(test)] +mod test { + use super::factory; + + #[tokio::test] + async fn should_not_send_any_event_when_statistics_are_disabled() { + let tracker_usage_statistics = false; + + let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); + + assert!(stats_event_sender.is_none()); + } + + #[tokio::test] + async fn should_send_events_when_statistics_are_enabled() { + let tracker_usage_statistics = true; + + let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); + + assert!(stats_event_sender.is_some()); + } +} From 700c912dd8ae50ca17595d11d0051fe4d74979f7 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 11:13:26 +0000 Subject: [PATCH 4/9] docs: update tracker core docs Statistics are not in the package anymore. --- packages/tracker-core/src/lib.rs | 54 -------------------------------- 1 file changed, 54 deletions(-) diff --git a/packages/tracker-core/src/lib.rs b/packages/tracker-core/src/lib.rs index ec4371322..68bc48552 100644 --- a/packages/tracker-core/src/lib.rs +++ b/packages/tracker-core/src/lib.rs @@ -370,60 +370,6 @@ //! To learn more about tracker authentication, refer to the following modules : //! //! - [`authentication`] module. -//! - [`core`](crate::core) module. -//! - [`http`](crate::servers::http) module. -//! -//! # Statistics -//! -//! The `Tracker` keeps metrics for some events: -//! -//! ```rust,no_run -//! pub struct Metrics { -//! // IP version 4 -//! -//! // HTTP tracker -//! pub tcp4_connections_handled: u64, -//! pub tcp4_announces_handled: u64, -//! pub tcp4_scrapes_handled: u64, -//! -//! // UDP tracker -//! pub udp4_connections_handled: u64, -//! pub udp4_announces_handled: u64, -//! pub udp4_scrapes_handled: u64, -//! -//! // IP version 6 -//! -//! // HTTP tracker -//! pub tcp6_connections_handled: u64, -//! pub tcp6_announces_handled: u64, -//! pub tcp6_scrapes_handled: u64, -//! -//! // UDP tracker -//! pub udp6_connections_handled: u64, -//! pub udp6_announces_handled: u64, -//! pub udp6_scrapes_handled: u64, -//! } -//! ``` -//! -//! The metrics maintained by the `Tracker` are: -//! -//! - `connections_handled`: number of connections handled by the tracker -//! - `announces_handled`: number of `announce` requests handled by the tracker -//! - `scrapes_handled`: number of `scrape` handled requests by the tracker -//! -//! > **NOTICE**: as the HTTP tracker does not have an specific `connection` request like the UDP tracker, `connections_handled` are -//! > increased on every `announce` and `scrape` requests. -//! -//! The tracker exposes an event sender API that allows the tracker users to send events. When a higher application service handles a -//! `connection` , `announce` or `scrape` requests, it notifies the `Tracker` by sending statistics events. -//! -//! For example, the HTTP tracker would send an event like the following when it handles an `announce` request received from a peer using IP version 4. -//! -//! ```text -//! stats_event_sender.send_stats_event(statistics::event::Event::Tcp4Announce).await -//! ``` -//! -//! Refer to [`statistics`] module for more information about statistics. //! //! # Persistence //! From 39cbeda28e0928a7e655152b191ee81647eca520 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 11:30:19 +0000 Subject: [PATCH 5/9] refactor: [#1228] add new UDP and HTTP stats services to AppContainer --- src/bootstrap/app.rs | 19 +++++++++++++++++++ src/container.rs | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index 7313b2808..550eb44f3 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -35,6 +35,7 @@ use tracing::instrument; use super::config::initialize_configuration; use crate::container::AppContainer; +use crate::packages::{http_tracker_core, udp_tracker_core}; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; use crate::shared::crypto::ephemeral_instance_keys; @@ -90,9 +91,23 @@ pub fn initialize_global_services(configuration: &Configuration) { #[instrument(skip())] pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let core_config = Arc::new(configuration.core.clone()); + let (stats_event_sender, stats_repository) = statistics::setup::factory(configuration.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); let stats_repository = Arc::new(stats_repository); + + // HTTP stats + let (http_stats_event_sender, http_stats_repository) = + http_tracker_core::statistics::setup::factory(configuration.core.tracker_usage_statistics); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + let http_stats_repository = Arc::new(http_stats_repository); + + // UDP stats + let (udp_stats_event_sender, udp_stats_repository) = + udp_tracker_core::statistics::setup::factory(configuration.core.tracker_usage_statistics); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let udp_stats_repository = Arc::new(udp_stats_repository); + let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); let database = initialize_database(configuration); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); @@ -134,7 +149,11 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { whitelist_authorization, ban_service, stats_event_sender, + http_stats_event_sender, + udp_stats_event_sender, stats_repository, + http_stats_repository, + udp_stats_repository, whitelist_manager, in_memory_torrent_repository, db_torrent_repository, diff --git a/src/container.rs b/src/container.rs index 965dbfa2a..f1996decb 100644 --- a/src/container.rs +++ b/src/container.rs @@ -15,7 +15,7 @@ use packages::statistics::repository::Repository; use tokio::sync::RwLock; use torrust_tracker_configuration::{Core, HttpApi, HttpTracker, UdpTracker}; -use crate::packages; +use crate::packages::{self, http_tracker_core, udp_tracker_core}; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { @@ -28,7 +28,11 @@ pub struct AppContainer { pub whitelist_authorization: Arc, pub ban_service: Arc>, pub stats_event_sender: Arc>>, + pub http_stats_event_sender: Arc>>, + pub udp_stats_event_sender: Arc>>, pub stats_repository: Arc, + pub http_stats_repository: Arc, + pub udp_stats_repository: Arc, pub whitelist_manager: Arc, pub in_memory_torrent_repository: Arc, pub db_torrent_repository: Arc, From 5f08b2ed509d3787c926bf55b5f58c85227af543 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 13:41:43 +0000 Subject: [PATCH 6/9] refactor: [#1228] start using the http tracker stats Stats have been splited into HTTP and UDP stats. Parallel change, step 1: 1. [x] Start using HTTP Tracker Core Stats 2. [ ] Start using UDP Tracker Core Stats 3. [ ] Get metrics from HTTP and UDP Tracker Core Stats 4. [ ] Remove deprecate unified HTTP and UDP stats. --- src/container.rs | 2 + src/servers/http/v1/handlers/announce.rs | 68 +++++++++---- src/servers/http/v1/handlers/scrape.rs | 80 +++++++++++---- src/servers/http/v1/routes.rs | 4 + src/servers/http/v1/services/announce.rs | 97 +++++++++++++++--- src/servers/http/v1/services/scrape.rs | 123 ++++++++++++++++++++--- tests/servers/http/environment.rs | 1 + 7 files changed, 306 insertions(+), 69 deletions(-) diff --git a/src/container.rs b/src/container.rs index f1996decb..71c60a517 100644 --- a/src/container.rs +++ b/src/container.rs @@ -71,6 +71,7 @@ pub struct HttpTrackerContainer { pub scrape_handler: Arc, pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, + pub http_stats_event_sender: Arc>>, pub authentication_service: Arc, } @@ -84,6 +85,7 @@ impl HttpTrackerContainer { scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), + http_stats_event_sender: app_container.http_stats_event_sender.clone(), authentication_service: app_container.authentication_service.clone(), } } diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index d3225ee29..594a11ea1 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -28,6 +28,7 @@ use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; use super::common::auth::map_auth_error_to_error_response; +use crate::packages::http_tracker_core; use crate::servers::http::v1::extractors::announce_request::ExtractRequest; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; @@ -46,6 +47,7 @@ pub async fn handle_without_key( Arc, Arc, Arc>>, + Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, @@ -58,6 +60,7 @@ pub async fn handle_without_key( &state.2, &state.3, &state.4, + &state.5, &announce_request, &client_ip_sources, None, @@ -76,6 +79,7 @@ pub async fn handle_with_key( Arc, Arc, Arc>>, + Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, @@ -89,6 +93,7 @@ pub async fn handle_with_key( &state.2, &state.3, &state.4, + &state.5, &announce_request, &client_ip_sources, Some(key), @@ -107,6 +112,7 @@ async fn handle( authentication_service: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, maybe_key: Option, @@ -117,6 +123,7 @@ async fn handle( authentication_service, whitelist_authorization, opt_stats_event_sender, + opt_http_stats_event_sender, announce_request, client_ip_sources, maybe_key, @@ -142,6 +149,7 @@ async fn handle_announce( authentication_service: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, maybe_key: Option, @@ -181,6 +189,7 @@ async fn handle_announce( let announce_data = services::announce::invoke( announce_handler.clone(), opt_stats_event_sender.clone(), + opt_http_stats_event_sender.clone(), announce_request.info_hash, &mut peer, &peers_wanted, @@ -265,7 +274,7 @@ mod tests { use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; - use crate::packages; + use crate::packages::{self, http_tracker_core}; struct CoreTrackerServices { pub core_config: Arc, @@ -275,23 +284,27 @@ mod tests { pub authentication_service: Arc, } - fn initialize_private_tracker() -> CoreTrackerServices { + struct CoreHttpTrackerServices { + pub http_stats_event_sender: Arc>>, + } + + fn initialize_private_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_private()) } - fn initialize_listed_tracker() -> CoreTrackerServices { + fn initialize_listed_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_listed()) } - fn initialize_tracker_on_reverse_proxy() -> CoreTrackerServices { + fn initialize_tracker_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_with_reverse_proxy()) } - fn initialize_tracker_not_on_reverse_proxy() -> CoreTrackerServices { + fn initialize_tracker_not_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_without_reverse_proxy()) } - fn initialize_core_tracker_services(config: &Configuration) -> CoreTrackerServices { + fn initialize_core_tracker_services(config: &Configuration) -> (CoreTrackerServices, CoreHttpTrackerServices) { let core_config = Arc::new(config.core.clone()); let database = initialize_database(config); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); @@ -300,21 +313,31 @@ mod tests { let authentication_service = Arc::new(AuthenticationService::new(&config.core, &in_memory_key_repository)); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); let announce_handler = Arc::new(AnnounceHandler::new( &config.core, &in_memory_torrent_repository, &db_torrent_repository, )); - CoreTrackerServices { - core_config, - announce_handler, - stats_event_sender, - whitelist_authorization, - authentication_service, - } + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_event_sender = Arc::new(stats_event_sender); + + // HTTP stats + let (http_stats_event_sender, http_stats_repository) = + http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + let _http_stats_repository = Arc::new(http_stats_repository); + + ( + CoreTrackerServices { + core_config, + announce_handler, + stats_event_sender, + whitelist_authorization, + authentication_service, + }, + CoreHttpTrackerServices { http_stats_event_sender }, + ) } fn sample_announce_request() -> Announce { @@ -357,7 +380,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_missing() { - let core_tracker_services = initialize_private_tracker(); + let (core_tracker_services, http_core_tracker_services) = initialize_private_tracker(); let maybe_key = None; @@ -367,6 +390,7 @@ mod tests { &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), maybe_key, @@ -382,7 +406,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_invalid() { - let core_tracker_services = initialize_private_tracker(); + let (core_tracker_services, http_core_tracker_services) = initialize_private_tracker(); let unregistered_key = authentication::Key::from_str("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(); @@ -394,6 +418,7 @@ mod tests { &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), maybe_key, @@ -413,7 +438,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_announced_torrent_is_not_whitelisted() { - let core_tracker_services = initialize_listed_tracker(); + let (core_tracker_services, http_core_tracker_services) = initialize_listed_tracker(); let announce_request = sample_announce_request(); @@ -423,6 +448,7 @@ mod tests { &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &http_core_tracker_services.http_stats_event_sender, &announce_request, &sample_client_ip_sources(), None, @@ -450,7 +476,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_right_most_x_forwarded_for_header_ip_is_not_available() { - let core_tracker_services = initialize_tracker_on_reverse_proxy(); + let (core_tracker_services, http_core_tracker_services) = initialize_tracker_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -463,6 +489,7 @@ mod tests { &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &client_ip_sources, None, @@ -487,7 +514,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_client_ip_from_the_connection_info_is_not_available() { - let core_tracker_services = initialize_tracker_not_on_reverse_proxy(); + let (core_tracker_services, http_core_tracker_services) = initialize_tracker_not_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -500,6 +527,7 @@ mod tests { &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &client_ip_sources, None, diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index 141cf4c45..d41a3742f 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -20,7 +20,7 @@ use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::ScrapeData; -use crate::packages; +use crate::packages::{self, http_tracker_core}; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; use crate::servers::http::v1::extractors::scrape_request::ExtractRequest; @@ -36,6 +36,7 @@ pub async fn handle_without_key( Arc, Arc, Arc>>, + Arc>>, )>, ExtractRequest(scrape_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, @@ -47,6 +48,7 @@ pub async fn handle_without_key( &state.1, &state.2, &state.3, + &state.4, &scrape_request, &client_ip_sources, None, @@ -66,6 +68,7 @@ pub async fn handle_with_key( Arc, Arc, Arc>>, + Arc>>, )>, ExtractRequest(scrape_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, @@ -78,6 +81,7 @@ pub async fn handle_with_key( &state.1, &state.2, &state.3, + &state.4, &scrape_request, &client_ip_sources, Some(key), @@ -91,6 +95,7 @@ async fn handle( scrape_handler: &Arc, authentication_service: &Arc, stats_event_sender: &Arc>>, + http_stats_event_sender: &Arc>>, scrape_request: &Scrape, client_ip_sources: &ClientIpSources, maybe_key: Option, @@ -100,6 +105,7 @@ async fn handle( scrape_handler, authentication_service, stats_event_sender, + http_stats_event_sender, scrape_request, client_ip_sources, maybe_key, @@ -124,6 +130,7 @@ async fn handle_scrape( scrape_handler: &Arc, authentication_service: &Arc, opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, scrape_request: &Scrape, client_ip_sources: &ClientIpSources, maybe_key: Option, @@ -150,9 +157,22 @@ async fn handle_scrape( }; if return_real_scrape_data { - Ok(services::scrape::invoke(scrape_handler, opt_stats_event_sender, &scrape_request.info_hashes, &peer_ip).await) + Ok(services::scrape::invoke( + scrape_handler, + opt_stats_event_sender, + opt_http_stats_event_sender, + &scrape_request.info_hashes, + &peer_ip, + ) + .await) } else { - Ok(services::scrape::fake(opt_stats_event_sender, &scrape_request.info_hashes, &peer_ip).await) + Ok(services::scrape::fake( + opt_stats_event_sender, + opt_http_stats_event_sender, + &scrape_request.info_hashes, + &peer_ip, + ) + .await) } } @@ -182,7 +202,7 @@ mod tests { use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; - use crate::packages; + use crate::packages::{self, http_tracker_core}; struct CoreTrackerServices { pub core_config: Arc, @@ -191,39 +211,52 @@ mod tests { pub authentication_service: Arc, } - fn initialize_private_tracker() -> CoreTrackerServices { + struct CoreHttpTrackerServices { + pub http_stats_event_sender: Arc>>, + } + + fn initialize_private_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_private()) } - fn initialize_listed_tracker() -> CoreTrackerServices { + fn initialize_listed_tracker() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_listed()) } - fn initialize_tracker_on_reverse_proxy() -> CoreTrackerServices { + fn initialize_tracker_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_with_reverse_proxy()) } - fn initialize_tracker_not_on_reverse_proxy() -> CoreTrackerServices { + fn initialize_tracker_not_on_reverse_proxy() -> (CoreTrackerServices, CoreHttpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_without_reverse_proxy()) } - fn initialize_core_tracker_services(config: &Configuration) -> CoreTrackerServices { + fn initialize_core_tracker_services(config: &Configuration) -> (CoreTrackerServices, CoreHttpTrackerServices) { let core_config = Arc::new(config.core.clone()); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone())); let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default()); let authentication_service = Arc::new(AuthenticationService::new(&config.core, &in_memory_key_repository)); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); - let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - CoreTrackerServices { - core_config, - scrape_handler, - stats_event_sender, - authentication_service, - } + // HTTP stats + let (http_stats_event_sender, _http_stats_repository) = + http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + + ( + CoreTrackerServices { + core_config, + scrape_handler, + stats_event_sender, + authentication_service, + }, + CoreHttpTrackerServices { http_stats_event_sender }, + ) } fn sample_scrape_request() -> Scrape { @@ -257,7 +290,7 @@ mod tests { #[tokio::test] async fn it_should_return_zeroed_swarm_metadata_when_the_authentication_key_is_missing() { - let core_tracker_services = initialize_private_tracker(); + let (core_tracker_services, core_http_tracker_services) = initialize_private_tracker(); let scrape_request = sample_scrape_request(); let maybe_key = None; @@ -267,6 +300,7 @@ mod tests { &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, &core_tracker_services.stats_event_sender, + &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), maybe_key, @@ -281,7 +315,7 @@ mod tests { #[tokio::test] async fn it_should_return_zeroed_swarm_metadata_when_the_authentication_key_is_invalid() { - let core_tracker_services = initialize_private_tracker(); + let (core_tracker_services, core_http_tracker_services) = initialize_private_tracker(); let scrape_request = sample_scrape_request(); let unregistered_key = authentication::Key::from_str("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(); @@ -292,6 +326,7 @@ mod tests { &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, &core_tracker_services.stats_event_sender, + &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), maybe_key, @@ -314,7 +349,7 @@ mod tests { #[tokio::test] async fn it_should_return_zeroed_swarm_metadata_when_the_torrent_is_not_whitelisted() { - let core_tracker_services = initialize_listed_tracker(); + let (core_tracker_services, core_http_tracker_services) = initialize_listed_tracker(); let scrape_request = sample_scrape_request(); @@ -323,6 +358,7 @@ mod tests { &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, &core_tracker_services.stats_event_sender, + &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), None, @@ -346,7 +382,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_right_most_x_forwarded_for_header_ip_is_not_available() { - let core_tracker_services = initialize_tracker_on_reverse_proxy(); + let (core_tracker_services, core_http_tracker_services) = initialize_tracker_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -358,6 +394,7 @@ mod tests { &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, &core_tracker_services.stats_event_sender, + &core_http_tracker_services.http_stats_event_sender, &sample_scrape_request(), &client_ip_sources, None, @@ -382,7 +419,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_client_ip_from_the_connection_info_is_not_available() { - let core_tracker_services = initialize_tracker_not_on_reverse_proxy(); + let (core_tracker_services, core_http_tracker_services) = initialize_tracker_not_on_reverse_proxy(); let client_ip_sources = ClientIpSources { right_most_x_forwarded_for: None, @@ -394,6 +431,7 @@ mod tests { &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, &core_tracker_services.stats_event_sender, + &core_http_tracker_services.http_stats_event_sender, &sample_scrape_request(), &client_ip_sources, None, diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index ed9aa05e6..7caccb673 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -44,6 +44,7 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.authentication_service.clone(), http_tracker_container.whitelist_authorization.clone(), http_tracker_container.stats_event_sender.clone(), + http_tracker_container.http_stats_event_sender.clone(), )), ) .route( @@ -54,6 +55,7 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.authentication_service.clone(), http_tracker_container.whitelist_authorization.clone(), http_tracker_container.stats_event_sender.clone(), + http_tracker_container.http_stats_event_sender.clone(), )), ) // Scrape request @@ -64,6 +66,7 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.scrape_handler.clone(), http_tracker_container.authentication_service.clone(), http_tracker_container.stats_event_sender.clone(), + http_tracker_container.http_stats_event_sender.clone(), )), ) .route( @@ -73,6 +76,7 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.scrape_handler.clone(), http_tracker_container.authentication_service.clone(), http_tracker_container.stats_event_sender.clone(), + http_tracker_container.http_stats_event_sender.clone(), )), ) // Add extension to get the client IP from the connection info diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 61bbd93c6..e7170c7e1 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -17,7 +17,7 @@ use packages::statistics::event::sender::Sender; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; -use crate::packages; +use crate::packages::{self, http_tracker_core}; /// The HTTP tracker `announce` service. /// @@ -32,6 +32,7 @@ use crate::packages; pub async fn invoke( announce_handler: Arc, opt_stats_event_sender: Arc>>, + opt_http_stats_event_sender: Arc>>, info_hash: InfoHash, peer: &mut peer::Peer, peers_wanted: &PeersWanted, @@ -52,6 +53,21 @@ pub async fn invoke( } } + if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() { + match original_peer_ip { + IpAddr::V4(_) => { + http_stats_event_sender + .send_event(http_tracker_core::statistics::event::Event::Tcp4Announce) + .await; + } + IpAddr::V6(_) => { + http_stats_event_sender + .send_event(http_tracker_core::statistics::event::Event::Tcp6Announce) + .await; + } + } + } + announce_data } @@ -77,26 +93,41 @@ mod tests { pub stats_event_sender: Arc>>, } - fn initialize_core_tracker_services() -> CoreTrackerServices { + struct CoreHttpTrackerServices { + pub http_stats_event_sender: Arc>>, + } + + fn initialize_core_tracker_services() -> (CoreTrackerServices, CoreHttpTrackerServices) { let config = configuration::ephemeral_public(); let core_config = Arc::new(config.core.clone()); let database = initialize_database(&config); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); + let announce_handler = Arc::new(AnnounceHandler::new( &config.core, &in_memory_torrent_repository, &db_torrent_repository, )); - CoreTrackerServices { - core_config, - announce_handler, - stats_event_sender, - } + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_event_sender = Arc::new(stats_event_sender); + + // HTTP stats + let (http_stats_event_sender, http_stats_repository) = + http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + let _http_stats_repository = Arc::new(http_stats_repository); + + ( + CoreTrackerServices { + core_config, + announce_handler, + stats_event_sender, + }, + CoreHttpTrackerServices { http_stats_event_sender }, + ) } fn sample_peer_using_ipv4() -> peer::Peer { @@ -129,7 +160,7 @@ mod tests { use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; - use crate::packages; + use crate::packages::{self, http_tracker_core}; mock! { StatsEventSender {} @@ -138,6 +169,13 @@ mod tests { } } + mock! { + HttpStatsEventSender {} + impl http_tracker_core::statistics::event::sender::Sender for HttpStatsEventSender { + fn send_event(&self, event: http_tracker_core::statistics::event::Event) -> BoxFuture<'static,Option > > > ; + } + } + mod with_tracker_in_any_mode { use std::future; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; @@ -156,10 +194,10 @@ mod tests { use torrust_tracker_test_helpers::configuration; use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; - use crate::packages; + use crate::packages::{self, http_tracker_core}; use crate::servers::http::v1::services::announce::invoke; use crate::servers::http::v1::services::announce::tests::{ - initialize_core_tracker_services, sample_peer, MockStatsEventSender, + initialize_core_tracker_services, sample_peer, MockHttpStatsEventSender, MockStatsEventSender, }; fn initialize_announce_handler() -> Arc { @@ -178,13 +216,14 @@ mod tests { #[tokio::test] async fn it_should_return_the_announce_data() { - let core_tracker_services = initialize_core_tracker_services(); + let (core_tracker_services, core_http_tracker_services) = initialize_core_tracker_services(); let mut peer = sample_peer(); let announce_data = invoke( core_tracker_services.announce_handler.clone(), core_tracker_services.stats_event_sender.clone(), + core_http_tracker_services.http_stats_event_sender.clone(), sample_info_hash(), &mut peer, &PeersWanted::All, @@ -215,6 +254,15 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp4Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let announce_handler = initialize_announce_handler(); let mut peer = sample_peer_using_ipv4(); @@ -222,6 +270,7 @@ mod tests { let _announce_data = invoke( announce_handler, stats_event_sender, + http_stats_event_sender, sample_info_hash(), &mut peer, &PeersWanted::All, @@ -260,6 +309,16 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + // Assert that the event sent is a TCP4 event + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp4Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let mut peer = peer_with_the_ipv4_loopback_ip(); let announce_handler = tracker_with_an_ipv6_external_ip(); @@ -267,6 +326,7 @@ mod tests { let _announce_data = invoke( announce_handler, stats_event_sender, + http_stats_event_sender, sample_info_hash(), &mut peer, &PeersWanted::All, @@ -286,6 +346,16 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + // Assert that the event sent is a TCP4 event + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp6Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let announce_handler = initialize_announce_handler(); let mut peer = sample_peer_using_ipv6(); @@ -293,6 +363,7 @@ mod tests { let _announce_data = invoke( announce_handler, stats_event_sender, + http_stats_event_sender, sample_info_hash(), &mut peer, &PeersWanted::All, diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index 1ac42ff10..e745609aa 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -16,7 +16,7 @@ use packages::statistics::event::sender::Sender; use packages::statistics::{self}; use torrust_tracker_primitives::core::ScrapeData; -use crate::packages; +use crate::packages::{self, http_tracker_core}; /// The HTTP tracker `scrape` service. /// @@ -31,12 +31,13 @@ use crate::packages; pub async fn invoke( scrape_handler: &Arc, opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, info_hashes: &Vec, original_peer_ip: &IpAddr, ) -> ScrapeData { let scrape_data = scrape_handler.scrape(info_hashes).await; - send_scrape_event(original_peer_ip, opt_stats_event_sender).await; + send_scrape_event(original_peer_ip, opt_stats_event_sender, opt_http_stats_event_sender).await; scrape_data } @@ -49,15 +50,20 @@ pub async fn invoke( /// > **NOTICE**: tracker statistics are not updated in this case. pub async fn fake( opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, info_hashes: &Vec, original_peer_ip: &IpAddr, ) -> ScrapeData { - send_scrape_event(original_peer_ip, opt_stats_event_sender).await; + send_scrape_event(original_peer_ip, opt_stats_event_sender, opt_http_stats_event_sender).await; ScrapeData::zeroed(info_hashes) } -async fn send_scrape_event(original_peer_ip: &IpAddr, opt_stats_event_sender: &Arc>>) { +async fn send_scrape_event( + original_peer_ip: &IpAddr, + opt_stats_event_sender: &Arc>>, + opt_http_stats_event_sender: &Arc>>, +) { if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { match original_peer_ip { IpAddr::V4(_) => { @@ -68,6 +74,21 @@ async fn send_scrape_event(original_peer_ip: &IpAddr, opt_stats_event_sender: &A } } } + + if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() { + match original_peer_ip { + IpAddr::V4(_) => { + http_stats_event_sender + .send_event(http_tracker_core::statistics::event::Event::Tcp4Scrape) + .await; + } + IpAddr::V6(_) => { + http_stats_event_sender + .send_event(http_tracker_core::statistics::event::Event::Tcp6Scrape) + .await; + } + } + } } #[cfg(test)] @@ -94,7 +115,7 @@ mod tests { use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; - use crate::packages; + use crate::packages::{self, http_tracker_core}; fn initialize_announce_and_scrape_handlers_for_public_tracker() -> (Arc, Arc) { let config = configuration::ephemeral_public(); @@ -147,6 +168,13 @@ mod tests { } } + mock! { + HttpStatsEventSender {} + impl http_tracker_core::statistics::event::sender::Sender for HttpStatsEventSender { + fn send_event(&self, event: http_tracker_core::statistics::event::Event) -> BoxFuture<'static,Option > > > ; + } + } + mod with_real_data { use std::future; @@ -159,11 +187,11 @@ mod tests { use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; - use crate::packages; + use crate::packages::{self, http_tracker_core}; use crate::servers::http::v1::services::scrape::invoke; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, initialize_scrape_handler, sample_info_hash, - sample_info_hashes, sample_peer, MockStatsEventSender, + sample_info_hashes, sample_peer, MockHttpStatsEventSender, MockStatsEventSender, }; #[tokio::test] @@ -171,6 +199,10 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (http_stats_event_sender, _http_stats_repository) = + packages::http_tracker_core::statistics::setup::factory(false); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + let (announce_handler, scrape_handler) = initialize_announce_and_scrape_handlers_for_public_tracker(); let info_hash = sample_info_hash(); @@ -181,7 +213,14 @@ mod tests { let original_peer_ip = peer.ip(); announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); - let scrape_data = invoke(&scrape_handler, &stats_event_sender, &info_hashes, &original_peer_ip).await; + let scrape_data = invoke( + &scrape_handler, + &stats_event_sender, + &http_stats_event_sender, + &info_hashes, + &original_peer_ip, + ) + .await; let mut expected_scrape_data = ScrapeData::empty(); expected_scrape_data.add_file( @@ -207,11 +246,27 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp4Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let scrape_handler = initialize_scrape_handler(); let peer_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)); - invoke(&scrape_handler, &stats_event_sender, &sample_info_hashes(), &peer_ip).await; + invoke( + &scrape_handler, + &stats_event_sender, + &http_stats_event_sender, + &sample_info_hashes(), + &peer_ip, + ) + .await; } #[tokio::test] @@ -225,11 +280,27 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp6Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let scrape_handler = initialize_scrape_handler(); let peer_ip = IpAddr::V6(Ipv6Addr::new(0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969)); - invoke(&scrape_handler, &stats_event_sender, &sample_info_hashes(), &peer_ip).await; + invoke( + &scrape_handler, + &stats_event_sender, + &http_stats_event_sender, + &sample_info_hashes(), + &peer_ip, + ) + .await; } } @@ -244,11 +315,11 @@ mod tests { use packages::statistics; use torrust_tracker_primitives::core::ScrapeData; - use crate::packages; + use crate::packages::{self, http_tracker_core}; use crate::servers::http::v1::services::scrape::fake; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, sample_info_hash, sample_info_hashes, sample_peer, - MockStatsEventSender, + MockHttpStatsEventSender, MockStatsEventSender, }; #[tokio::test] @@ -256,6 +327,10 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (http_stats_event_sender, _http_stats_repository) = + packages::http_tracker_core::statistics::setup::factory(false); + let http_stats_event_sender = Arc::new(http_stats_event_sender); + let (announce_handler, _scrape_handler) = initialize_announce_and_scrape_handlers_for_public_tracker(); let info_hash = sample_info_hash(); @@ -266,7 +341,7 @@ mod tests { let original_peer_ip = peer.ip(); announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); - let scrape_data = fake(&stats_event_sender, &info_hashes, &original_peer_ip).await; + let scrape_data = fake(&stats_event_sender, &http_stats_event_sender, &info_hashes, &original_peer_ip).await; let expected_scrape_data = ScrapeData::zeroed(&info_hashes); @@ -284,9 +359,18 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp4Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let peer_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)); - fake(&stats_event_sender, &sample_info_hashes(), &peer_ip).await; + fake(&stats_event_sender, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } #[tokio::test] @@ -300,9 +384,18 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); + http_stats_event_sender_mock + .expect_send_event() + .with(eq(http_tracker_core::statistics::event::Event::Tcp6Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let http_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(http_stats_event_sender_mock))); + let peer_ip = IpAddr::V6(Ipv6Addr::new(0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969)); - fake(&stats_event_sender, &sample_info_hashes(), &peer_ip).await; + fake(&stats_event_sender, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } } } diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 2828982f7..17013250a 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -62,6 +62,7 @@ impl Environment { scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), + http_stats_event_sender: app_container.http_stats_event_sender.clone(), authentication_service: app_container.authentication_service.clone(), }); From f33665dc60fd98aa7c2d0081c83456ca41d6b3d7 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 15:55:35 +0000 Subject: [PATCH 7/9] refactor: [#1228] start using the udp tracker stats Parallel change, step 2: 1. [x] Start using HTTP Tracker Core Stats 2. [x] Start using UDP Tracker Core Stats 3. [ ] Get metrics from HTTP and UDP Tracker Core Stats 4. [ ] Remove deprecate unified HTTP and UDP stats. --- src/container.rs | 2 + src/servers/udp/handlers.rs | 323 +++++++++++++++++++++++----- src/servers/udp/server/launcher.rs | 29 ++- src/servers/udp/server/processor.rs | 32 ++- tests/servers/udp/environment.rs | 1 + 5 files changed, 332 insertions(+), 55 deletions(-) diff --git a/src/container.rs b/src/container.rs index 71c60a517..7b44bc834 100644 --- a/src/container.rs +++ b/src/container.rs @@ -46,6 +46,7 @@ pub struct UdpTrackerContainer { pub scrape_handler: Arc, pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, + pub udp_stats_event_sender: Arc>>, pub ban_service: Arc>, } @@ -59,6 +60,7 @@ impl UdpTrackerContainer { scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), + udp_stats_event_sender: app_container.udp_stats_event_sender.clone(), ban_service: app_container.ban_service.clone(), } } diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 9f2562713..4c943516e 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -24,7 +24,7 @@ use zerocopy::network_endian::I32; use super::connection_cookie::{check, make}; use super::RawRequest; use crate::container::UdpTrackerContainer; -use crate::packages::statistics; +use crate::packages::{statistics, udp_tracker_core}; use crate::servers::udp::error::Error; use crate::servers::udp::{peer_builder, UDP_TRACKER_LOG_TARGET}; use crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS; @@ -99,6 +99,7 @@ pub(crate) async fn handle_packet( local_addr, request_id, &udp_tracker_container.stats_event_sender, + &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range.clone(), &e, Some(transaction_id), @@ -112,6 +113,7 @@ pub(crate) async fn handle_packet( local_addr, request_id, &udp_tracker_container.stats_event_sender, + &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range.clone(), &e, None, @@ -145,6 +147,7 @@ pub async fn handle_request( remote_addr, &connect_request, &udp_tracker_container.stats_event_sender, + &udp_tracker_container.udp_stats_event_sender, cookie_time_values.issue_time, ) .await), @@ -156,6 +159,7 @@ pub async fn handle_request( &udp_tracker_container.announce_handler, &udp_tracker_container.whitelist_authorization, &udp_tracker_container.stats_event_sender, + &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range, ) .await @@ -166,6 +170,7 @@ pub async fn handle_request( &scrape_request, &udp_tracker_container.scrape_handler, &udp_tracker_container.stats_event_sender, + &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range, ) .await @@ -179,11 +184,12 @@ pub async fn handle_request( /// # Errors /// /// This function does not ever return an error. -#[instrument(fields(transaction_id), skip(opt_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id), skip(opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_connect( remote_addr: SocketAddr, request: &ConnectRequest, opt_stats_event_sender: &Arc>>, + opt_udp_stats_event_sender: &Arc>>, cookie_issue_time: f64, ) -> Response { tracing::Span::current().record("transaction_id", request.transaction_id.0.to_string()); @@ -208,6 +214,21 @@ pub async fn handle_connect( } } + if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { + match remote_addr { + SocketAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Connect) + .await; + } + SocketAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Connect) + .await; + } + } + } + Response::from(response) } @@ -218,7 +239,7 @@ pub async fn handle_connect( /// /// If a error happens in the `handle_announce` function, it will just return the `ServerError`. #[allow(clippy::too_many_arguments)] -#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_handler, whitelist_authorization, opt_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_handler, whitelist_authorization, opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_announce( remote_addr: SocketAddr, request: &AnnounceRequest, @@ -226,6 +247,7 @@ pub async fn handle_announce( announce_handler: &Arc, whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, + opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { tracing::Span::current() @@ -270,6 +292,21 @@ pub async fn handle_announce( } } + if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { + match remote_client_ip { + IpAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Announce) + .await; + } + IpAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Announce) + .await; + } + } + } + #[allow(clippy::cast_possible_truncation)] if remote_addr.is_ipv4() { let announce_response = AnnounceResponse { @@ -330,12 +367,13 @@ pub async fn handle_announce( /// # Errors /// /// This function does not ever return an error. -#[instrument(fields(transaction_id, connection_id), skip(scrape_handler, opt_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id), skip(scrape_handler, opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_scrape( remote_addr: SocketAddr, request: &ScrapeRequest, scrape_handler: &Arc, opt_stats_event_sender: &Arc>>, + opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { tracing::Span::current() @@ -387,6 +425,21 @@ pub async fn handle_scrape( } } + if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { + match remote_addr { + SocketAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Scrape) + .await; + } + SocketAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Scrape) + .await; + } + } + } + let response = ScrapeResponse { transaction_id: request.transaction_id, torrent_stats, @@ -395,12 +448,14 @@ pub async fn handle_scrape( Ok(Response::from(response)) } -#[instrument(fields(transaction_id), skip(opt_stats_event_sender), ret(level = Level::TRACE))] +#[allow(clippy::too_many_arguments)] +#[instrument(fields(transaction_id), skip(opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] async fn handle_error( remote_addr: SocketAddr, local_addr: SocketAddr, request_id: Uuid, opt_stats_event_sender: &Arc>>, + opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, e: &Error, transaction_id: Option, @@ -447,6 +502,21 @@ async fn handle_error( } } } + + if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { + match remote_addr { + SocketAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Error) + .await; + } + SocketAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Error) + .await; + } + } + } } Response::from(ErrorResponse { @@ -488,7 +558,7 @@ mod tests { use torrust_tracker_test_helpers::configuration; use super::gen_remote_fingerprint; - use crate::packages::statistics; + use crate::packages::{statistics, udp_tracker_core}; use crate::{packages, CurrentClock}; struct CoreTrackerServices { @@ -501,31 +571,33 @@ mod tests { pub whitelist_authorization: Arc, } + struct CoreUdpTrackerServices { + pub udp_stats_event_sender: Arc>>, + } + fn default_testing_tracker_configuration() -> Configuration { configuration::ephemeral() } - fn initialize_core_tracker_services_for_default_tracker_configuration() -> CoreTrackerServices { + fn initialize_core_tracker_services_for_default_tracker_configuration() -> (CoreTrackerServices, CoreUdpTrackerServices) { initialize_core_tracker_services(&default_testing_tracker_configuration()) } - fn initialize_core_tracker_services_for_public_tracker() -> CoreTrackerServices { + fn initialize_core_tracker_services_for_public_tracker() -> (CoreTrackerServices, CoreUdpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_public()) } - fn initialize_core_tracker_services_for_listed_tracker() -> CoreTrackerServices { + fn initialize_core_tracker_services_for_listed_tracker() -> (CoreTrackerServices, CoreUdpTrackerServices) { initialize_core_tracker_services(&configuration::ephemeral_listed()) } - fn initialize_core_tracker_services(config: &Configuration) -> CoreTrackerServices { + fn initialize_core_tracker_services(config: &Configuration) -> (CoreTrackerServices, CoreUdpTrackerServices) { let core_config = Arc::new(config.core.clone()); let database = initialize_database(config); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone())); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); let announce_handler = Arc::new(AnnounceHandler::new( &config.core, &in_memory_torrent_repository, @@ -533,15 +605,24 @@ mod tests { )); let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - CoreTrackerServices { - core_config, - announce_handler, - scrape_handler, - in_memory_torrent_repository, - stats_event_sender, - in_memory_whitelist, - whitelist_authorization, - } + let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_event_sender = Arc::new(stats_event_sender); + + let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + + ( + CoreTrackerServices { + core_config, + announce_handler, + scrape_handler, + in_memory_torrent_repository, + stats_event_sender, + in_memory_whitelist, + whitelist_authorization, + }, + CoreUdpTrackerServices { udp_stats_event_sender }, + ) } fn sample_ipv4_remote_addr() -> SocketAddr { @@ -645,6 +726,13 @@ mod tests { } } + mock! { + UdpStatsEventSender {} + impl udp_tracker_core::statistics::event::sender::Sender for UdpStatsEventSender { + fn send_event(&self, event: udp_tracker_core::statistics::event::Event) -> BoxFuture<'static,Option > > > ; + } + } + mod connect_request { use std::future; @@ -655,12 +743,12 @@ mod tests { use packages::statistics; use super::{sample_ipv4_socket_address, sample_ipv6_remote_addr}; - use crate::packages; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_connect; use crate::servers::udp::handlers::tests::{ sample_ipv4_remote_addr, sample_ipv4_remote_addr_fingerprint, sample_ipv6_remote_addr_fingerprint, sample_issue_time, - MockStatsEventSender, + MockStatsEventSender, MockUdpStatsEventSender, }; fn sample_connect_request() -> ConnectRequest { @@ -674,11 +762,21 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let request = ConnectRequest { transaction_id: TransactionId(0i32.into()), }; - let response = handle_connect(sample_ipv4_remote_addr(), &request, &stats_event_sender, sample_issue_time()).await; + let response = handle_connect( + sample_ipv4_remote_addr(), + &request, + &stats_event_sender, + &udp_stats_event_sender, + sample_issue_time(), + ) + .await; assert_eq!( response, @@ -694,11 +792,21 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let request = ConnectRequest { transaction_id: TransactionId(0i32.into()), }; - let response = handle_connect(sample_ipv4_remote_addr(), &request, &stats_event_sender, sample_issue_time()).await; + let response = handle_connect( + sample_ipv4_remote_addr(), + &request, + &stats_event_sender, + &udp_stats_event_sender, + sample_issue_time(), + ) + .await; assert_eq!( response, @@ -714,11 +822,21 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let request = ConnectRequest { transaction_id: TransactionId(0i32.into()), }; - let response = handle_connect(sample_ipv6_remote_addr(), &request, &stats_event_sender, sample_issue_time()).await; + let response = handle_connect( + sample_ipv6_remote_addr(), + &request, + &stats_event_sender, + &udp_stats_event_sender, + sample_issue_time(), + ) + .await; assert_eq!( response, @@ -740,12 +858,22 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp4Connect)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + let client_socket_address = sample_ipv4_socket_address(); handle_connect( client_socket_address, &sample_connect_request(), &stats_event_sender, + &udp_stats_event_sender, sample_issue_time(), ) .await; @@ -762,10 +890,20 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp6Connect)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + handle_connect( sample_ipv6_remote_addr(), &sample_connect_request(), &stats_event_sender, + &udp_stats_event_sender, sample_issue_time(), ) .await; @@ -861,19 +999,19 @@ mod tests { use mockall::predicate::eq; use torrust_tracker_configuration::Core; - use crate::packages::{self, statistics}; + use crate::packages::{self, statistics, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ gen_remote_fingerprint, initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv4_socket_address, - sample_issue_time, MockStatsEventSender, TorrentPeerBuilder, + sample_issue_time, MockStatsEventSender, MockUdpStatsEventSender, TorrentPeerBuilder, }; use crate::servers::udp::handlers::{handle_announce, AnnounceResponseFixedData}; #[tokio::test] async fn an_announced_peer_should_be_added_to_the_tracker() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let client_ip = Ipv4Addr::new(126, 0, 0, 1); let client_port = 8080; @@ -897,6 +1035,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -916,7 +1055,7 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); @@ -931,6 +1070,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -957,7 +1097,7 @@ mod tests { // From the BEP 15 (https://www.bittorrent.org/beps/bep_0015.html): // "Do note that most trackers will only honor the IP address field under limited circumstances." - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); @@ -984,6 +1124,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1020,6 +1161,10 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = + packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); let request = AnnounceRequestBuilder::default() .with_connection_id(make(gen_remote_fingerprint(&remote_addr), sample_issue_time()).unwrap()) @@ -1032,6 +1177,7 @@ mod tests { &announce_handler, &whitelist_authorization, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1040,7 +1186,7 @@ mod tests { #[tokio::test] async fn when_the_announce_request_comes_from_a_client_using_ipv4_the_response_should_not_include_peers_using_ipv6() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, _core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); add_a_torrent_peer_using_ipv6(&core_tracker_services.in_memory_torrent_repository); @@ -1071,7 +1217,17 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let core_tracker_services = initialize_core_tracker_services_for_default_tracker_configuration(); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp4Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + + let (core_tracker_services, _core_udp_tracker_services) = + initialize_core_tracker_services_for_default_tracker_configuration(); handle_announce( sample_ipv4_socket_address(), @@ -1080,6 +1236,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1102,7 +1259,8 @@ mod tests { #[tokio::test] async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration_if_defined() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = + initialize_core_tracker_services_for_public_tracker(); let client_ip = Ipv4Addr::new(127, 0, 0, 1); let client_port = 8080; @@ -1126,6 +1284,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1163,19 +1322,19 @@ mod tests { use mockall::predicate::eq; use torrust_tracker_configuration::Core; - use crate::packages::{self, statistics}; + use crate::packages::{self, statistics, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ gen_remote_fingerprint, initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv6_remote_addr, - sample_issue_time, MockStatsEventSender, TorrentPeerBuilder, + sample_issue_time, MockStatsEventSender, MockUdpStatsEventSender, TorrentPeerBuilder, }; use crate::servers::udp::handlers::{handle_announce, AnnounceResponseFixedData}; #[tokio::test] async fn an_announced_peer_should_be_added_to_the_tracker() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); @@ -1200,6 +1359,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1219,7 +1379,7 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); @@ -1237,6 +1397,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1263,7 +1424,7 @@ mod tests { // From the BEP 15 (https://www.bittorrent.org/beps/bep_0015.html): // "Do note that most trackers will only honor the IP address field under limited circumstances." - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); @@ -1290,6 +1451,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1326,6 +1488,10 @@ mod tests { let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = + packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); let client_port = 8080; @@ -1341,6 +1507,7 @@ mod tests { &announce_handler, &whitelist_authorization, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1349,7 +1516,7 @@ mod tests { #[tokio::test] async fn when_the_announce_request_comes_from_a_client_using_ipv6_the_response_should_not_include_peers_using_ipv4() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, _core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); add_a_torrent_peer_using_ipv4(&core_tracker_services.in_memory_torrent_repository); @@ -1380,7 +1547,17 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let core_tracker_services = initialize_core_tracker_services_for_default_tracker_configuration(); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp6Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + + let (core_tracker_services, _core_udp_tracker_services) = + initialize_core_tracker_services_for_default_tracker_configuration(); let remote_addr = sample_ipv6_remote_addr(); @@ -1395,6 +1572,7 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1416,13 +1594,13 @@ mod tests { use mockall::predicate::eq; use packages::statistics; - use crate::packages; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_announce; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ gen_remote_fingerprint, sample_cookie_valid_range, sample_issue_time, MockStatsEventSender, - TrackerConfigurationBuilder, + MockUdpStatsEventSender, TrackerConfigurationBuilder, }; #[tokio::test] @@ -1445,6 +1623,15 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp6Announce)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + let announce_handler = Arc::new(AnnounceHandler::new( &config.core, &in_memory_torrent_repository, @@ -1480,6 +1667,7 @@ mod tests { &announce_handler, &whitelist_authorization, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1533,7 +1721,7 @@ mod tests { #[tokio::test] async fn should_return_no_stats_when_the_tracker_does_not_have_any_torrent() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let remote_addr = sample_ipv4_remote_addr(); @@ -1551,6 +1739,7 @@ mod tests { &request, &core_tracker_services.scrape_handler, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1600,6 +1789,9 @@ mod tests { let (stats_event_sender, _stats_repository) = statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); + let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); + let udp_stats_event_sender = Arc::new(udp_stats_event_sender); + let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); @@ -1612,6 +1804,7 @@ mod tests { &request, &scrape_handler, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1633,7 +1826,7 @@ mod tests { #[tokio::test] async fn should_return_torrent_statistics_when_the_tracker_has_the_requested_torrent() { - let core_tracker_services = initialize_core_tracker_services_for_public_tracker(); + let (core_tracker_services, _core_udp_tracker_services) = initialize_core_tracker_services_for_public_tracker(); let torrent_stats = match_scrape_response( add_a_sample_seeder_and_scrape( @@ -1666,7 +1859,7 @@ mod tests { #[tokio::test] async fn should_return_the_torrent_statistics_when_the_requested_torrent_is_whitelisted() { - let core_tracker_services = initialize_core_tracker_services_for_listed_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_listed_tracker(); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); @@ -1688,6 +1881,7 @@ mod tests { &request, &core_tracker_services.scrape_handler, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1706,7 +1900,7 @@ mod tests { #[tokio::test] async fn should_return_zeroed_statistics_when_the_requested_torrent_is_not_whitelisted() { - let core_tracker_services = initialize_core_tracker_services_for_listed_tracker(); + let (core_tracker_services, core_udp_tracker_services) = initialize_core_tracker_services_for_listed_tracker(); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); @@ -1726,6 +1920,7 @@ mod tests { &request, &core_tracker_services.scrape_handler, &core_tracker_services.stats_event_sender, + &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1758,11 +1953,11 @@ mod tests { use packages::statistics; use super::sample_scrape_request; - use crate::packages; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv4_remote_addr, MockStatsEventSender, + sample_ipv4_remote_addr, MockStatsEventSender, MockUdpStatsEventSender, }; #[tokio::test] @@ -1776,15 +1971,26 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp4Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + let remote_addr = sample_ipv4_remote_addr(); - let core_tracker_services = initialize_core_tracker_services_for_default_tracker_configuration(); + let (core_tracker_services, _core_udp_tracker_services) = + initialize_core_tracker_services_for_default_tracker_configuration(); handle_scrape( remote_addr, &sample_scrape_request(&remote_addr), &core_tracker_services.scrape_handler, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await @@ -1800,11 +2006,11 @@ mod tests { use packages::statistics; use super::sample_scrape_request; - use crate::packages; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv6_remote_addr, MockStatsEventSender, + sample_ipv6_remote_addr, MockStatsEventSender, MockUdpStatsEventSender, }; #[tokio::test] @@ -1818,15 +2024,26 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); + let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); + udp_stats_event_sender_mock + .expect_send_event() + .with(eq(udp_tracker_core::statistics::event::Event::Udp6Scrape)) + .times(1) + .returning(|_| Box::pin(future::ready(Some(Ok(()))))); + let udp_stats_event_sender: Arc>> = + Arc::new(Some(Box::new(udp_stats_event_sender_mock))); + let remote_addr = sample_ipv6_remote_addr(); - let core_tracker_services = initialize_core_tracker_services_for_default_tracker_configuration(); + let (core_tracker_services, _core_udp_tracker_services) = + initialize_core_tracker_services_for_default_tracker_configuration(); handle_scrape( remote_addr, &sample_scrape_request(&remote_addr), &core_tracker_services.scrape_handler, &stats_event_sender, + &udp_stats_event_sender, sample_cookie_valid_range(), ) .await diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index 24872771a..863f82e18 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -14,7 +14,7 @@ use tracing::instrument; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; use crate::container::UdpTrackerContainer; -use crate::packages; +use crate::packages::{self, udp_tracker_core}; use crate::servers::logging::STARTED_ON; use crate::servers::registar::ServiceHealthCheckJob; use crate::servers::signals::{shutdown_signal_with_message, Halted}; @@ -174,6 +174,21 @@ impl Launcher { } } + if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { + match req.from.ip() { + IpAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Request) + .await; + } + IpAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Request) + .await; + } + } + } + if udp_tracker_container.ban_service.read().await.is_banned(&req.from.ip()) { tracing::debug!(target: UDP_TRACKER_LOG_TARGET, local_addr, "Udp::run_udp_server::loop continue: (banned ip)"); @@ -183,6 +198,12 @@ impl Launcher { .await; } + if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::UdpRequestBanned) + .await; + } + continue; } @@ -215,6 +236,12 @@ impl Launcher { .send_event(statistics::event::Event::UdpRequestAborted) .await; } + + if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::UdpRequestAborted) + .await; + } } } else { tokio::task::yield_now().await; diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index 8a1ca64e3..bbf64dfb9 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -11,7 +11,7 @@ use tracing::{instrument, Level}; use super::bound_socket::BoundSocket; use crate::container::UdpTrackerContainer; -use crate::packages; +use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::handlers::CookieTimeValues; use crate::servers::udp::{handlers, RawRequest}; @@ -68,6 +68,15 @@ impl Processor { Response::Error(_e) => UdpResponseKind::Error, }; + let udp_response_kind = match &response { + Response::Connect(_) => udp_tracker_core::statistics::event::UdpResponseKind::Connect, + Response::AnnounceIpv4(_) | Response::AnnounceIpv6(_) => { + udp_tracker_core::statistics::event::UdpResponseKind::Announce + } + Response::Scrape(_) => udp_tracker_core::statistics::event::UdpResponseKind::Scrape, + Response::Error(_e) => udp_tracker_core::statistics::event::UdpResponseKind::Error, + }; + let mut writer = Cursor::new(Vec::with_capacity(200)); match response.write_bytes(&mut writer) { @@ -103,6 +112,27 @@ impl Processor { } } } + + if let Some(udp_stats_event_sender) = self.udp_tracker_container.udp_stats_event_sender.as_deref() { + match target.ip() { + IpAddr::V4(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp4Response { + kind: udp_response_kind, + req_processing_time, + }) + .await; + } + IpAddr::V6(_) => { + udp_stats_event_sender + .send_event(udp_tracker_core::statistics::event::Event::Udp6Response { + kind: udp_response_kind, + req_processing_time, + }) + .await; + } + } + } } Err(error) => tracing::warn!(%bytes_count, %error, ?payload, "failed to send"), }; diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index 8e2e31f07..c8ecac1fb 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -62,6 +62,7 @@ impl Environment { scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), + udp_stats_event_sender: app_container.udp_stats_event_sender.clone(), ban_service: app_container.ban_service.clone(), }); From 55769383f5b05bf10048de0f346ea04a2f5748aa Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 16:20:04 +0000 Subject: [PATCH 8/9] refactor: [#1228] get metrics from HTTP and UDP Tracker Core Stats Stats have been splited into HTTP and UDP stats. Parallel change, step 3: 1. [x] Start using HTTP Tracker Core Stats 2. [x] Start using UDP Tracker Core Stats 3. [x] Get metrics from HTTP and UDP Tracker Core Stats 4. [ ] Remove deprecated unified HTTP and UDP stats. --- src/container.rs | 8 +- src/packages/mod.rs | 1 + src/packages/tracker_api_core/mod.rs | 1 + .../tracker_api_core/statistics/metrics.rs | 87 ++++++++++++ .../tracker_api_core/statistics/mod.rs | 2 + .../tracker_api_core/statistics/services.rs | 127 ++++++++++++++++++ src/servers/apis/v1/context/stats/handlers.rs | 14 +- .../apis/v1/context/stats/resources.rs | 6 +- .../apis/v1/context/stats/responses.rs | 2 +- src/servers/apis/v1/context/stats/routes.rs | 3 +- tests/servers/api/environment.rs | 4 +- 11 files changed, 239 insertions(+), 16 deletions(-) create mode 100644 src/packages/tracker_api_core/mod.rs create mode 100644 src/packages/tracker_api_core/statistics/metrics.rs create mode 100644 src/packages/tracker_api_core/statistics/mod.rs create mode 100644 src/packages/tracker_api_core/statistics/services.rs diff --git a/src/container.rs b/src/container.rs index 7b44bc834..ccd85c7b1 100644 --- a/src/container.rs +++ b/src/container.rs @@ -100,8 +100,8 @@ pub struct HttpApiContainer { pub keys_handler: Arc, pub whitelist_manager: Arc, pub ban_service: Arc>, - pub stats_event_sender: Arc>>, - pub stats_repository: Arc, + pub http_stats_repository: Arc, + pub udp_stats_repository: Arc, } impl HttpApiContainer { @@ -114,8 +114,8 @@ impl HttpApiContainer { keys_handler: app_container.keys_handler.clone(), whitelist_manager: app_container.whitelist_manager.clone(), ban_service: app_container.ban_service.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), - stats_repository: app_container.stats_repository.clone(), + http_stats_repository: app_container.http_stats_repository.clone(), + udp_stats_repository: app_container.udp_stats_repository.clone(), } } } diff --git a/src/packages/mod.rs b/src/packages/mod.rs index 9e0bbec90..dcf4cf428 100644 --- a/src/packages/mod.rs +++ b/src/packages/mod.rs @@ -3,4 +3,5 @@ //! It will be moved to the directory `packages`. pub mod http_tracker_core; pub mod statistics; +pub mod tracker_api_core; pub mod udp_tracker_core; diff --git a/src/packages/tracker_api_core/mod.rs b/src/packages/tracker_api_core/mod.rs new file mode 100644 index 000000000..3449ec7b4 --- /dev/null +++ b/src/packages/tracker_api_core/mod.rs @@ -0,0 +1 @@ +pub mod statistics; diff --git a/src/packages/tracker_api_core/statistics/metrics.rs b/src/packages/tracker_api_core/statistics/metrics.rs new file mode 100644 index 000000000..40262efd6 --- /dev/null +++ b/src/packages/tracker_api_core/statistics/metrics.rs @@ -0,0 +1,87 @@ +/// Metrics collected by the tracker. +/// +/// - Number of connections handled +/// - Number of `announce` requests handled +/// - Number of `scrape` request handled +/// +/// These metrics are collected for each connection type: UDP and HTTP +/// and also for each IP version used by the peers: IPv4 and IPv6. +#[derive(Debug, PartialEq, Default)] +pub struct Metrics { + /// Total number of TCP (HTTP tracker) connections from IPv4 peers. + /// Since the HTTP tracker spec does not require a handshake, this metric + /// increases for every HTTP request. + pub tcp4_connections_handled: u64, + + /// Total number of TCP (HTTP tracker) `announce` requests from IPv4 peers. + pub tcp4_announces_handled: u64, + + /// Total number of TCP (HTTP tracker) `scrape` requests from IPv4 peers. + pub tcp4_scrapes_handled: u64, + + /// Total number of TCP (HTTP tracker) connections from IPv6 peers. + pub tcp6_connections_handled: u64, + + /// Total number of TCP (HTTP tracker) `announce` requests from IPv6 peers. + pub tcp6_announces_handled: u64, + + /// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers. + pub tcp6_scrapes_handled: u64, + + // UDP + /// Total number of UDP (UDP tracker) requests aborted. + pub udp_requests_aborted: u64, + + /// Total number of UDP (UDP tracker) requests banned. + pub udp_requests_banned: u64, + + /// Total number of banned IPs. + pub udp_banned_ips_total: u64, + + /// Average rounded time spent processing UDP connect requests. + pub udp_avg_connect_processing_time_ns: u64, + + /// Average rounded time spent processing UDP announce requests. + pub udp_avg_announce_processing_time_ns: u64, + + /// Average rounded time spent processing UDP scrape requests. + pub udp_avg_scrape_processing_time_ns: u64, + + // UDPv4 + /// Total number of UDP (UDP tracker) requests from IPv4 peers. + pub udp4_requests: u64, + + /// Total number of UDP (UDP tracker) connections from IPv4 peers. + pub udp4_connections_handled: u64, + + /// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers. + pub udp4_announces_handled: u64, + + /// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers. + pub udp4_scrapes_handled: u64, + + /// Total number of UDP (UDP tracker) responses from IPv4 peers. + pub udp4_responses: u64, + + /// Total number of UDP (UDP tracker) `error` requests from IPv4 peers. + pub udp4_errors_handled: u64, + + // UDPv6 + /// Total number of UDP (UDP tracker) requests from IPv6 peers. + pub udp6_requests: u64, + + /// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers. + pub udp6_connections_handled: u64, + + /// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers. + pub udp6_announces_handled: u64, + + /// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers. + pub udp6_scrapes_handled: u64, + + /// Total number of UDP (UDP tracker) responses from IPv6 peers. + pub udp6_responses: u64, + + /// Total number of UDP (UDP tracker) `error` requests from IPv6 peers. + pub udp6_errors_handled: u64, +} diff --git a/src/packages/tracker_api_core/statistics/mod.rs b/src/packages/tracker_api_core/statistics/mod.rs new file mode 100644 index 000000000..a3c8a4b0e --- /dev/null +++ b/src/packages/tracker_api_core/statistics/mod.rs @@ -0,0 +1,2 @@ +pub mod metrics; +pub mod services; diff --git a/src/packages/tracker_api_core/statistics/services.rs b/src/packages/tracker_api_core/statistics/services.rs new file mode 100644 index 000000000..bb8e71ab8 --- /dev/null +++ b/src/packages/tracker_api_core/statistics/services.rs @@ -0,0 +1,127 @@ +use std::sync::Arc; + +use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; +use packages::tracker_api_core::statistics::metrics::Metrics; +use tokio::sync::RwLock; +use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + +use crate::packages::{self, http_tracker_core, udp_tracker_core}; +use crate::servers::udp::server::banning::BanService; + +/// All the metrics collected by the tracker. +#[derive(Debug, PartialEq)] +pub struct TrackerMetrics { + /// Domain level metrics. + /// + /// General metrics for all torrents (number of seeders, leechers, etcetera) + pub torrents_metrics: TorrentsMetrics, + + /// Application level metrics. Usage statistics/metrics. + /// + /// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera) + pub protocol_metrics: Metrics, +} + +/// It returns all the [`TrackerMetrics`] +pub async fn get_metrics( + in_memory_torrent_repository: Arc, + ban_service: Arc>, + http_stats_repository: Arc, + udp_stats_repository: Arc, +) -> TrackerMetrics { + let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics(); + let udp_banned_ips_total = ban_service.read().await.get_banned_ips_total(); + let http_stats = http_stats_repository.get_stats().await; + let udp_stats = udp_stats_repository.get_stats().await; + + TrackerMetrics { + torrents_metrics, + protocol_metrics: Metrics { + // TCPv4 + tcp4_connections_handled: http_stats.tcp4_connections_handled, + tcp4_announces_handled: http_stats.tcp4_announces_handled, + tcp4_scrapes_handled: http_stats.tcp4_scrapes_handled, + // TCPv6 + tcp6_connections_handled: http_stats.tcp6_connections_handled, + tcp6_announces_handled: http_stats.tcp6_announces_handled, + tcp6_scrapes_handled: http_stats.tcp6_scrapes_handled, + // UDP + udp_requests_aborted: udp_stats.udp_requests_aborted, + udp_requests_banned: udp_stats.udp_requests_banned, + udp_banned_ips_total: udp_banned_ips_total as u64, + udp_avg_connect_processing_time_ns: udp_stats.udp_avg_connect_processing_time_ns, + udp_avg_announce_processing_time_ns: udp_stats.udp_avg_announce_processing_time_ns, + udp_avg_scrape_processing_time_ns: udp_stats.udp_avg_scrape_processing_time_ns, + // UDPv4 + udp4_requests: udp_stats.udp4_requests, + udp4_connections_handled: udp_stats.udp4_connections_handled, + udp4_announces_handled: udp_stats.udp4_announces_handled, + udp4_scrapes_handled: udp_stats.udp4_scrapes_handled, + udp4_responses: udp_stats.udp4_responses, + udp4_errors_handled: udp_stats.udp4_errors_handled, + // UDPv6 + udp6_requests: udp_stats.udp6_requests, + udp6_connections_handled: udp_stats.udp6_connections_handled, + udp6_announces_handled: udp_stats.udp6_announces_handled, + udp6_scrapes_handled: udp_stats.udp6_scrapes_handled, + udp6_responses: udp_stats.udp6_responses, + udp6_errors_handled: udp_stats.udp6_errors_handled, + }, + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; + use bittorrent_tracker_core::{self}; + use tokio::sync::RwLock; + use torrust_tracker_configuration::Configuration; + use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + use torrust_tracker_test_helpers::configuration; + + use crate::packages::tracker_api_core::statistics::metrics::Metrics; + use crate::packages::tracker_api_core::statistics::services::{get_metrics, TrackerMetrics}; + use crate::packages::{http_tracker_core, udp_tracker_core}; + use crate::servers::udp::server::banning::BanService; + use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; + + pub fn tracker_configuration() -> Configuration { + configuration::ephemeral() + } + + #[tokio::test] + async fn the_statistics_service_should_return_the_tracker_metrics() { + let config = tracker_configuration(); + + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); + + // HTTP stats + let (_http_stats_event_sender, http_stats_repository) = + http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let http_stats_repository = Arc::new(http_stats_repository); + + // UDP stats + let (_udp_stats_event_sender, udp_stats_repository) = + udp_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let udp_stats_repository = Arc::new(udp_stats_repository); + + let tracker_metrics = get_metrics( + in_memory_torrent_repository.clone(), + ban_service.clone(), + http_stats_repository.clone(), + udp_stats_repository.clone(), + ) + .await; + + assert_eq!( + tracker_metrics, + TrackerMetrics { + torrents_metrics: TorrentsMetrics::default(), + protocol_metrics: Metrics::default(), + } + ); + } +} diff --git a/src/servers/apis/v1/context/stats/handlers.rs b/src/servers/apis/v1/context/stats/handlers.rs index ffd4f1787..820f39909 100644 --- a/src/servers/apis/v1/context/stats/handlers.rs +++ b/src/servers/apis/v1/context/stats/handlers.rs @@ -6,13 +6,12 @@ use axum::extract::State; use axum::response::Response; use axum_extra::extract::Query; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; -use packages::statistics::repository::Repository; use serde::Deserialize; use tokio::sync::RwLock; use super::responses::{metrics_response, stats_response}; -use crate::packages; -use crate::packages::statistics::services::get_metrics; +use crate::packages::tracker_api_core::statistics::services::get_metrics; +use crate::packages::{http_tracker_core, udp_tracker_core}; use crate::servers::udp::server::banning::BanService; #[derive(Deserialize, Debug, Default)] @@ -41,10 +40,15 @@ pub struct QueryParams { /// for more information about this endpoint. #[allow(clippy::type_complexity)] pub async fn get_stats_handler( - State(state): State<(Arc, Arc>, Arc)>, + State(state): State<( + Arc, + Arc>, + Arc, + Arc, + )>, params: Query, ) -> Response { - let metrics = get_metrics(state.0.clone(), state.1.clone(), state.2.clone()).await; + let metrics = get_metrics(state.0.clone(), state.1.clone(), state.2.clone(), state.3.clone()).await; match params.0.format { Some(format) => match format { diff --git a/src/servers/apis/v1/context/stats/resources.rs b/src/servers/apis/v1/context/stats/resources.rs index 5900e293a..8477ca5cb 100644 --- a/src/servers/apis/v1/context/stats/resources.rs +++ b/src/servers/apis/v1/context/stats/resources.rs @@ -2,7 +2,7 @@ //! API context. use serde::{Deserialize, Serialize}; -use crate::packages::statistics::services::TrackerMetrics; +use crate::packages::tracker_api_core::statistics::services::TrackerMetrics; /// It contains all the statistics generated by the tracker. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -118,11 +118,11 @@ impl From for Stats { #[cfg(test)] mod tests { - use packages::statistics::metrics::Metrics; + use packages::tracker_api_core::statistics::metrics::Metrics; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use super::Stats; - use crate::packages::statistics::services::TrackerMetrics; + use crate::packages::tracker_api_core::statistics::services::TrackerMetrics; use crate::packages::{self}; #[test] diff --git a/src/servers/apis/v1/context/stats/responses.rs b/src/servers/apis/v1/context/stats/responses.rs index e3b45a66b..5a71c4235 100644 --- a/src/servers/apis/v1/context/stats/responses.rs +++ b/src/servers/apis/v1/context/stats/responses.rs @@ -3,7 +3,7 @@ use axum::response::{IntoResponse, Json, Response}; use super::resources::Stats; -use crate::packages::statistics::services::TrackerMetrics; +use crate::packages::tracker_api_core::statistics::services::TrackerMetrics; /// `200` response that contains the [`Stats`] resource as json. #[must_use] diff --git a/src/servers/apis/v1/context/stats/routes.rs b/src/servers/apis/v1/context/stats/routes.rs index 4c80f110d..e660005ec 100644 --- a/src/servers/apis/v1/context/stats/routes.rs +++ b/src/servers/apis/v1/context/stats/routes.rs @@ -18,7 +18,8 @@ pub fn add(prefix: &str, router: Router, http_api_container: &Arc { keys_handler: app_container.keys_handler.clone(), whitelist_manager: app_container.whitelist_manager.clone(), ban_service: app_container.ban_service.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), - stats_repository: app_container.stats_repository.clone(), + http_stats_repository: app_container.http_stats_repository.clone(), + udp_stats_repository: app_container.udp_stats_repository.clone(), }); Self { From fd8b57a6792977e823f38f2431ef7ad83794196d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 31 Jan 2025 17:02:52 +0000 Subject: [PATCH 9/9] refactor: [#1228] remove deprecated unified HTTP and UDP stats Stats have been split into HTTP and UDP stats. Parallel change, step 4: 1. [x] Start using HTTP Tracker Core Stats 2. [x] Start using UDP Tracker Core Stats 3. [x] Get metrics from HTTP and UDP Tracker Core Stats 4. [x] Remove deprecated unified HTTP and UDP stats. --- src/bootstrap/app.rs | 9 +- src/container.rs | 10 +- .../http_tracker_core/statistics/services.rs | 10 +- src/packages/mod.rs | 1 - src/packages/statistics/event/handler.rs | 262 ------------------ src/packages/statistics/event/listener.rs | 11 - src/packages/statistics/event/mod.rs | 51 ---- src/packages/statistics/event/sender.rs | 29 -- src/packages/statistics/keeper.rs | 77 ----- src/packages/statistics/metrics.rs | 87 ------ src/packages/statistics/mod.rs | 6 - src/packages/statistics/repository.rs | 209 -------------- src/packages/statistics/services.rs | 154 ---------- src/packages/statistics/setup.rs | 54 ---- .../udp_tracker_core/statistics/services.rs | 9 +- src/servers/http/v1/handlers/announce.rs | 25 +- src/servers/http/v1/handlers/scrape.rs | 32 +-- src/servers/http/v1/routes.rs | 4 - src/servers/http/v1/services/announce.rs | 73 +---- src/servers/http/v1/services/scrape.rs | 116 +------- src/servers/udp/handlers.rs | 215 ++------------ src/servers/udp/server/launcher.rs | 26 +- src/servers/udp/server/processor.rs | 32 +-- tests/servers/http/environment.rs | 12 +- tests/servers/http/v1/contract.rs | 16 +- tests/servers/udp/contract.rs | 4 +- tests/servers/udp/environment.rs | 12 +- 27 files changed, 78 insertions(+), 1468 deletions(-) delete mode 100644 src/packages/statistics/event/handler.rs delete mode 100644 src/packages/statistics/event/listener.rs delete mode 100644 src/packages/statistics/event/mod.rs delete mode 100644 src/packages/statistics/event/sender.rs delete mode 100644 src/packages/statistics/keeper.rs delete mode 100644 src/packages/statistics/metrics.rs delete mode 100644 src/packages/statistics/mod.rs delete mode 100644 src/packages/statistics/repository.rs delete mode 100644 src/packages/statistics/services.rs delete mode 100644 src/packages/statistics/setup.rs diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index 550eb44f3..93bbfe290 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -26,7 +26,6 @@ use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentT use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use bittorrent_tracker_core::whitelist::setup::initialize_whitelist_manager; -use packages::statistics; use tokio::sync::RwLock; use torrust_tracker_clock::static_time; use torrust_tracker_configuration::validator::Validator; @@ -34,13 +33,13 @@ use torrust_tracker_configuration::Configuration; use tracing::instrument; use super::config::initialize_configuration; +use crate::bootstrap; use crate::container::AppContainer; use crate::packages::{http_tracker_core, udp_tracker_core}; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; use crate::shared::crypto::ephemeral_instance_keys; use crate::shared::crypto::keys::{self, Keeper as _}; -use crate::{bootstrap, packages}; /// It loads the configuration from the environment and builds app container. /// @@ -92,10 +91,6 @@ pub fn initialize_global_services(configuration: &Configuration) { pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let core_config = Arc::new(configuration.core.clone()); - let (stats_event_sender, stats_repository) = statistics::setup::factory(configuration.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); - let stats_repository = Arc::new(stats_repository); - // HTTP stats let (http_stats_event_sender, http_stats_repository) = http_tracker_core::statistics::setup::factory(configuration.core.tracker_usage_statistics); @@ -148,10 +143,8 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { authentication_service, whitelist_authorization, ban_service, - stats_event_sender, http_stats_event_sender, udp_stats_event_sender, - stats_repository, http_stats_repository, udp_stats_repository, whitelist_manager, diff --git a/src/container.rs b/src/container.rs index ccd85c7b1..51c55e533 100644 --- a/src/container.rs +++ b/src/container.rs @@ -10,12 +10,10 @@ use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepo use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist; use bittorrent_tracker_core::whitelist::manager::WhitelistManager; -use packages::statistics::event::sender::Sender; -use packages::statistics::repository::Repository; use tokio::sync::RwLock; use torrust_tracker_configuration::{Core, HttpApi, HttpTracker, UdpTracker}; -use crate::packages::{self, http_tracker_core, udp_tracker_core}; +use crate::packages::{http_tracker_core, udp_tracker_core}; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { @@ -27,10 +25,8 @@ pub struct AppContainer { pub authentication_service: Arc, pub whitelist_authorization: Arc, pub ban_service: Arc>, - pub stats_event_sender: Arc>>, pub http_stats_event_sender: Arc>>, pub udp_stats_event_sender: Arc>>, - pub stats_repository: Arc, pub http_stats_repository: Arc, pub udp_stats_repository: Arc, pub whitelist_manager: Arc, @@ -45,7 +41,6 @@ pub struct UdpTrackerContainer { pub announce_handler: Arc, pub scrape_handler: Arc, pub whitelist_authorization: Arc, - pub stats_event_sender: Arc>>, pub udp_stats_event_sender: Arc>>, pub ban_service: Arc>, } @@ -59,7 +54,6 @@ impl UdpTrackerContainer { announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), udp_stats_event_sender: app_container.udp_stats_event_sender.clone(), ban_service: app_container.ban_service.clone(), } @@ -72,7 +66,6 @@ pub struct HttpTrackerContainer { pub announce_handler: Arc, pub scrape_handler: Arc, pub whitelist_authorization: Arc, - pub stats_event_sender: Arc>>, pub http_stats_event_sender: Arc>>, pub authentication_service: Arc, } @@ -86,7 +79,6 @@ impl HttpTrackerContainer { announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), http_stats_event_sender: app_container.http_stats_event_sender.clone(), authentication_service: app_container.authentication_service.clone(), } diff --git a/src/packages/http_tracker_core/statistics/services.rs b/src/packages/http_tracker_core/statistics/services.rs index 11e3a70c4..51065bf63 100644 --- a/src/packages/http_tracker_core/statistics/services.rs +++ b/src/packages/http_tracker_core/statistics/services.rs @@ -76,8 +76,8 @@ mod tests { use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_test_helpers::configuration; - use crate::packages::http_tracker_core::statistics; use crate::packages::http_tracker_core::statistics::services::{get_metrics, TrackerMetrics}; + use crate::packages::http_tracker_core::{self, statistics}; pub fn tracker_configuration() -> Configuration { configuration::ephemeral() @@ -88,10 +88,12 @@ mod tests { let config = tracker_configuration(); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_repository = Arc::new(stats_repository); - let tracker_metrics = get_metrics(in_memory_torrent_repository.clone(), stats_repository.clone()).await; + let (_http_stats_event_sender, http_stats_repository) = + http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let http_stats_repository = Arc::new(http_stats_repository); + + let tracker_metrics = get_metrics(in_memory_torrent_repository.clone(), http_stats_repository.clone()).await; assert_eq!( tracker_metrics, diff --git a/src/packages/mod.rs b/src/packages/mod.rs index dcf4cf428..453c3d533 100644 --- a/src/packages/mod.rs +++ b/src/packages/mod.rs @@ -2,6 +2,5 @@ //! //! It will be moved to the directory `packages`. pub mod http_tracker_core; -pub mod statistics; pub mod tracker_api_core; pub mod udp_tracker_core; diff --git a/src/packages/statistics/event/handler.rs b/src/packages/statistics/event/handler.rs deleted file mode 100644 index 99339041a..000000000 --- a/src/packages/statistics/event/handler.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::packages::statistics::event::{Event, UdpResponseKind}; -use crate::packages::statistics::repository::Repository; - -pub async fn handle_event(event: Event, stats_repository: &Repository) { - match event { - // TCP4 - Event::Tcp4Announce => { - stats_repository.increase_tcp4_announces().await; - stats_repository.increase_tcp4_connections().await; - } - Event::Tcp4Scrape => { - stats_repository.increase_tcp4_scrapes().await; - stats_repository.increase_tcp4_connections().await; - } - - // TCP6 - Event::Tcp6Announce => { - stats_repository.increase_tcp6_announces().await; - stats_repository.increase_tcp6_connections().await; - } - Event::Tcp6Scrape => { - stats_repository.increase_tcp6_scrapes().await; - stats_repository.increase_tcp6_connections().await; - } - - // UDP - Event::UdpRequestAborted => { - stats_repository.increase_udp_requests_aborted().await; - } - Event::UdpRequestBanned => { - stats_repository.increase_udp_requests_banned().await; - } - - // UDP4 - Event::Udp4Request => { - stats_repository.increase_udp4_requests().await; - } - Event::Udp4Connect => { - stats_repository.increase_udp4_connections().await; - } - Event::Udp4Announce => { - stats_repository.increase_udp4_announces().await; - } - Event::Udp4Scrape => { - stats_repository.increase_udp4_scrapes().await; - } - Event::Udp4Response { - kind, - req_processing_time, - } => { - stats_repository.increase_udp4_responses().await; - - match kind { - UdpResponseKind::Connect => { - stats_repository - .recalculate_udp_avg_connect_processing_time_ns(req_processing_time) - .await; - } - UdpResponseKind::Announce => { - stats_repository - .recalculate_udp_avg_announce_processing_time_ns(req_processing_time) - .await; - } - UdpResponseKind::Scrape => { - stats_repository - .recalculate_udp_avg_scrape_processing_time_ns(req_processing_time) - .await; - } - UdpResponseKind::Error => {} - } - } - Event::Udp4Error => { - stats_repository.increase_udp4_errors().await; - } - - // UDP6 - Event::Udp6Request => { - stats_repository.increase_udp6_requests().await; - } - Event::Udp6Connect => { - stats_repository.increase_udp6_connections().await; - } - Event::Udp6Announce => { - stats_repository.increase_udp6_announces().await; - } - Event::Udp6Scrape => { - stats_repository.increase_udp6_scrapes().await; - } - Event::Udp6Response { - kind: _, - req_processing_time: _, - } => { - stats_repository.increase_udp6_responses().await; - } - Event::Udp6Error => { - stats_repository.increase_udp6_errors().await; - } - } - - tracing::debug!("stats: {:?}", stats_repository.get_stats().await); -} - -#[cfg(test)] -mod tests { - use crate::packages::statistics::event::handler::handle_event; - use crate::packages::statistics::event::Event; - use crate::packages::statistics::repository::Repository; - - #[tokio::test] - async fn should_increase_the_tcp4_announces_counter_when_it_receives_a_tcp4_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp4Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp4_announces_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp4_connections_counter_when_it_receives_a_tcp4_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp4Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp4_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp4_scrapes_counter_when_it_receives_a_tcp4_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp4Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp4_scrapes_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp4_connections_counter_when_it_receives_a_tcp4_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp4Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp4_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp6_announces_counter_when_it_receives_a_tcp6_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp6Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp6_announces_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp6_connections_counter_when_it_receives_a_tcp6_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp6Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp6_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp6_scrapes_counter_when_it_receives_a_tcp6_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp6Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp6_scrapes_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_tcp6_connections_counter_when_it_receives_a_tcp6_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Tcp6Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.tcp6_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp4_connections_counter_when_it_receives_a_udp4_connect_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp4Connect, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp4_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp4_announces_counter_when_it_receives_a_udp4_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp4Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp4_announces_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp4_scrapes_counter_when_it_receives_a_udp4_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp4Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp4_scrapes_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp6_connections_counter_when_it_receives_a_udp6_connect_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp6Connect, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp6_connections_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp6_announces_counter_when_it_receives_a_udp6_announce_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp6Announce, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp6_announces_handled, 1); - } - - #[tokio::test] - async fn should_increase_the_udp6_scrapes_counter_when_it_receives_a_udp6_scrape_event() { - let stats_repository = Repository::new(); - - handle_event(Event::Udp6Scrape, &stats_repository).await; - - let stats = stats_repository.get_stats().await; - - assert_eq!(stats.udp6_scrapes_handled, 1); - } -} diff --git a/src/packages/statistics/event/listener.rs b/src/packages/statistics/event/listener.rs deleted file mode 100644 index 009784fba..000000000 --- a/src/packages/statistics/event/listener.rs +++ /dev/null @@ -1,11 +0,0 @@ -use tokio::sync::mpsc; - -use super::handler::handle_event; -use super::Event; -use crate::packages::statistics::repository::Repository; - -pub async fn dispatch_events(mut receiver: mpsc::Receiver, stats_repository: Repository) { - while let Some(event) = receiver.recv().await { - handle_event(event, &stats_repository).await; - } -} diff --git a/src/packages/statistics/event/mod.rs b/src/packages/statistics/event/mod.rs deleted file mode 100644 index 905aa0372..000000000 --- a/src/packages/statistics/event/mod.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::time::Duration; - -pub mod handler; -pub mod listener; -pub mod sender; - -/// An statistics event. It is used to collect tracker metrics. -/// -/// - `Tcp` prefix means the event was triggered by the HTTP tracker -/// - `Udp` prefix means the event was triggered by the UDP tracker -/// - `4` or `6` prefixes means the IP version used by the peer -/// - Finally the event suffix is the type of request: `announce`, `scrape` or `connection` -/// -/// > NOTE: HTTP trackers do not use `connection` requests. -#[derive(Debug, PartialEq, Eq)] -pub enum Event { - // code-review: consider one single event for request type with data: Event::Announce { scheme: HTTPorUDP, ip_version: V4orV6 } - // Attributes are enums too. - Tcp4Announce, - Tcp4Scrape, - Tcp6Announce, - Tcp6Scrape, - UdpRequestAborted, - UdpRequestBanned, - Udp4Request, - Udp4Connect, - Udp4Announce, - Udp4Scrape, - Udp4Response { - kind: UdpResponseKind, - req_processing_time: Duration, - }, - Udp4Error, - Udp6Request, - Udp6Connect, - Udp6Announce, - Udp6Scrape, - Udp6Response { - kind: UdpResponseKind, - req_processing_time: Duration, - }, - Udp6Error, -} - -#[derive(Debug, PartialEq, Eq)] -pub enum UdpResponseKind { - Connect, - Announce, - Scrape, - Error, -} diff --git a/src/packages/statistics/event/sender.rs b/src/packages/statistics/event/sender.rs deleted file mode 100644 index b9b989053..000000000 --- a/src/packages/statistics/event/sender.rs +++ /dev/null @@ -1,29 +0,0 @@ -use futures::future::BoxFuture; -use futures::FutureExt; -#[cfg(test)] -use mockall::{automock, predicate::str}; -use tokio::sync::mpsc; -use tokio::sync::mpsc::error::SendError; - -use super::Event; - -/// A trait to allow sending statistics events -#[cfg_attr(test, automock)] -pub trait Sender: Sync + Send { - fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>>; -} - -/// An [`statistics::EventSender`](crate::packages::statistics::event::sender::Sender) implementation. -/// -/// It uses a channel sender to send the statistic events. The channel is created by a -/// [`statistics::Keeper`](crate::packages::statistics::keeper::Keeper) -#[allow(clippy::module_name_repetitions)] -pub struct ChannelSender { - pub(crate) sender: mpsc::Sender, -} - -impl Sender for ChannelSender { - fn send_event(&self, event: Event) -> BoxFuture<'_, Option>>> { - async move { Some(self.sender.send(event).await) }.boxed() - } -} diff --git a/src/packages/statistics/keeper.rs b/src/packages/statistics/keeper.rs deleted file mode 100644 index 493e61cb2..000000000 --- a/src/packages/statistics/keeper.rs +++ /dev/null @@ -1,77 +0,0 @@ -use tokio::sync::mpsc; - -use super::event::listener::dispatch_events; -use super::event::sender::{ChannelSender, Sender}; -use super::event::Event; -use super::repository::Repository; - -const CHANNEL_BUFFER_SIZE: usize = 65_535; - -/// The service responsible for keeping tracker metrics (listening to statistics events and handle them). -/// -/// It actively listen to new statistics events. When it receives a new event -/// it accordingly increases the counters. -pub struct Keeper { - pub repository: Repository, -} - -impl Default for Keeper { - fn default() -> Self { - Self::new() - } -} - -impl Keeper { - #[must_use] - pub fn new() -> Self { - Self { - repository: Repository::new(), - } - } - - #[must_use] - pub fn new_active_instance() -> (Box, Repository) { - let mut stats_tracker = Self::new(); - - let stats_event_sender = stats_tracker.run_event_listener(); - - (stats_event_sender, stats_tracker.repository) - } - - pub fn run_event_listener(&mut self) -> Box { - let (sender, receiver) = mpsc::channel::(CHANNEL_BUFFER_SIZE); - - let stats_repository = self.repository.clone(); - - tokio::spawn(async move { dispatch_events(receiver, stats_repository).await }); - - Box::new(ChannelSender { sender }) - } -} - -#[cfg(test)] -mod tests { - use crate::packages::statistics::event::Event; - use crate::packages::statistics::keeper::Keeper; - use crate::packages::statistics::metrics::Metrics; - - #[tokio::test] - async fn should_contain_the_tracker_statistics() { - let stats_tracker = Keeper::new(); - - let stats = stats_tracker.repository.get_stats().await; - - assert_eq!(stats.tcp4_announces_handled, Metrics::default().tcp4_announces_handled); - } - - #[tokio::test] - async fn should_create_an_event_sender_to_send_statistical_events() { - let mut stats_tracker = Keeper::new(); - - let event_sender = stats_tracker.run_event_listener(); - - let result = event_sender.send_event(Event::Udp4Connect).await; - - assert!(result.is_some()); - } -} diff --git a/src/packages/statistics/metrics.rs b/src/packages/statistics/metrics.rs deleted file mode 100644 index 40262efd6..000000000 --- a/src/packages/statistics/metrics.rs +++ /dev/null @@ -1,87 +0,0 @@ -/// Metrics collected by the tracker. -/// -/// - Number of connections handled -/// - Number of `announce` requests handled -/// - Number of `scrape` request handled -/// -/// These metrics are collected for each connection type: UDP and HTTP -/// and also for each IP version used by the peers: IPv4 and IPv6. -#[derive(Debug, PartialEq, Default)] -pub struct Metrics { - /// Total number of TCP (HTTP tracker) connections from IPv4 peers. - /// Since the HTTP tracker spec does not require a handshake, this metric - /// increases for every HTTP request. - pub tcp4_connections_handled: u64, - - /// Total number of TCP (HTTP tracker) `announce` requests from IPv4 peers. - pub tcp4_announces_handled: u64, - - /// Total number of TCP (HTTP tracker) `scrape` requests from IPv4 peers. - pub tcp4_scrapes_handled: u64, - - /// Total number of TCP (HTTP tracker) connections from IPv6 peers. - pub tcp6_connections_handled: u64, - - /// Total number of TCP (HTTP tracker) `announce` requests from IPv6 peers. - pub tcp6_announces_handled: u64, - - /// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers. - pub tcp6_scrapes_handled: u64, - - // UDP - /// Total number of UDP (UDP tracker) requests aborted. - pub udp_requests_aborted: u64, - - /// Total number of UDP (UDP tracker) requests banned. - pub udp_requests_banned: u64, - - /// Total number of banned IPs. - pub udp_banned_ips_total: u64, - - /// Average rounded time spent processing UDP connect requests. - pub udp_avg_connect_processing_time_ns: u64, - - /// Average rounded time spent processing UDP announce requests. - pub udp_avg_announce_processing_time_ns: u64, - - /// Average rounded time spent processing UDP scrape requests. - pub udp_avg_scrape_processing_time_ns: u64, - - // UDPv4 - /// Total number of UDP (UDP tracker) requests from IPv4 peers. - pub udp4_requests: u64, - - /// Total number of UDP (UDP tracker) connections from IPv4 peers. - pub udp4_connections_handled: u64, - - /// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers. - pub udp4_announces_handled: u64, - - /// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers. - pub udp4_scrapes_handled: u64, - - /// Total number of UDP (UDP tracker) responses from IPv4 peers. - pub udp4_responses: u64, - - /// Total number of UDP (UDP tracker) `error` requests from IPv4 peers. - pub udp4_errors_handled: u64, - - // UDPv6 - /// Total number of UDP (UDP tracker) requests from IPv6 peers. - pub udp6_requests: u64, - - /// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers. - pub udp6_connections_handled: u64, - - /// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers. - pub udp6_announces_handled: u64, - - /// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers. - pub udp6_scrapes_handled: u64, - - /// Total number of UDP (UDP tracker) responses from IPv6 peers. - pub udp6_responses: u64, - - /// Total number of UDP (UDP tracker) `error` requests from IPv6 peers. - pub udp6_errors_handled: u64, -} diff --git a/src/packages/statistics/mod.rs b/src/packages/statistics/mod.rs deleted file mode 100644 index 939a41061..000000000 --- a/src/packages/statistics/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod event; -pub mod keeper; -pub mod metrics; -pub mod repository; -pub mod services; -pub mod setup; diff --git a/src/packages/statistics/repository.rs b/src/packages/statistics/repository.rs deleted file mode 100644 index ec5100073..000000000 --- a/src/packages/statistics/repository.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::sync::Arc; -use std::time::Duration; - -use tokio::sync::{RwLock, RwLockReadGuard}; - -use super::metrics::Metrics; - -/// A repository for the tracker metrics. -#[derive(Clone)] -pub struct Repository { - pub stats: Arc>, -} - -impl Default for Repository { - fn default() -> Self { - Self::new() - } -} - -impl Repository { - #[must_use] - pub fn new() -> Self { - Self { - stats: Arc::new(RwLock::new(Metrics::default())), - } - } - - pub async fn get_stats(&self) -> RwLockReadGuard<'_, Metrics> { - self.stats.read().await - } - - pub async fn increase_tcp4_announces(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp4_announces_handled += 1; - drop(stats_lock); - } - - pub async fn increase_tcp4_connections(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp4_connections_handled += 1; - drop(stats_lock); - } - - pub async fn increase_tcp4_scrapes(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp4_scrapes_handled += 1; - drop(stats_lock); - } - - pub async fn increase_tcp6_announces(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp6_announces_handled += 1; - drop(stats_lock); - } - - pub async fn increase_tcp6_connections(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp6_connections_handled += 1; - drop(stats_lock); - } - - pub async fn increase_tcp6_scrapes(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.tcp6_scrapes_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp_requests_aborted(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp_requests_aborted += 1; - drop(stats_lock); - } - - pub async fn increase_udp_requests_banned(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp_requests_banned += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_requests(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_requests += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_connections(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_connections_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_announces(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_announces_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_scrapes(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_scrapes_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_responses(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_responses += 1; - drop(stats_lock); - } - - pub async fn increase_udp4_errors(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp4_errors_handled += 1; - drop(stats_lock); - } - - #[allow(clippy::cast_precision_loss)] - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - pub async fn recalculate_udp_avg_connect_processing_time_ns(&self, req_processing_time: Duration) { - let mut stats_lock = self.stats.write().await; - - let req_processing_time = req_processing_time.as_nanos() as f64; - let udp_connections_handled = (stats_lock.udp4_connections_handled + stats_lock.udp6_connections_handled) as f64; - - let previous_avg = stats_lock.udp_avg_connect_processing_time_ns; - - // Moving average: https://en.wikipedia.org/wiki/Moving_average - let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_connections_handled; - - stats_lock.udp_avg_connect_processing_time_ns = new_avg.ceil() as u64; - - drop(stats_lock); - } - - #[allow(clippy::cast_precision_loss)] - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - pub async fn recalculate_udp_avg_announce_processing_time_ns(&self, req_processing_time: Duration) { - let mut stats_lock = self.stats.write().await; - - let req_processing_time = req_processing_time.as_nanos() as f64; - - let udp_announces_handled = (stats_lock.udp4_announces_handled + stats_lock.udp6_announces_handled) as f64; - - let previous_avg = stats_lock.udp_avg_announce_processing_time_ns; - - // Moving average: https://en.wikipedia.org/wiki/Moving_average - let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_announces_handled; - - stats_lock.udp_avg_announce_processing_time_ns = new_avg.ceil() as u64; - - drop(stats_lock); - } - - #[allow(clippy::cast_precision_loss)] - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - pub async fn recalculate_udp_avg_scrape_processing_time_ns(&self, req_processing_time: Duration) { - let mut stats_lock = self.stats.write().await; - - let req_processing_time = req_processing_time.as_nanos() as f64; - let udp_scrapes_handled = (stats_lock.udp4_scrapes_handled + stats_lock.udp6_scrapes_handled) as f64; - - let previous_avg = stats_lock.udp_avg_scrape_processing_time_ns; - - // Moving average: https://en.wikipedia.org/wiki/Moving_average - let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_scrapes_handled; - - stats_lock.udp_avg_scrape_processing_time_ns = new_avg.ceil() as u64; - - drop(stats_lock); - } - - pub async fn increase_udp6_requests(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_requests += 1; - drop(stats_lock); - } - - pub async fn increase_udp6_connections(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_connections_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp6_announces(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_announces_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp6_scrapes(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_scrapes_handled += 1; - drop(stats_lock); - } - - pub async fn increase_udp6_responses(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_responses += 1; - drop(stats_lock); - } - - pub async fn increase_udp6_errors(&self) { - let mut stats_lock = self.stats.write().await; - stats_lock.udp6_errors_handled += 1; - drop(stats_lock); - } -} diff --git a/src/packages/statistics/services.rs b/src/packages/statistics/services.rs deleted file mode 100644 index 444ba533c..000000000 --- a/src/packages/statistics/services.rs +++ /dev/null @@ -1,154 +0,0 @@ -//! Statistics services. -//! -//! It includes: -//! -//! - A [`factory`](crate::packages::statistics::setup::factory) function to build the structs needed to collect the tracker metrics. -//! - A [`get_metrics`] service to get the tracker [`metrics`](crate::packages::statistics::metrics::Metrics). -//! -//! Tracker metrics are collected using a Publisher-Subscribe pattern. -//! -//! The factory function builds two structs: -//! -//! - An statistics event [`Sender`](crate::packages::statistics::event::sender::Sender) -//! - An statistics [`Repository`] -//! -//! ```text -//! let (stats_event_sender, stats_repository) = factory(tracker_usage_statistics); -//! ``` -//! -//! The statistics repository is responsible for storing the metrics in memory. -//! The statistics event sender allows sending events related to metrics. -//! There is an event listener that is receiving all the events and processing them with an event handler. -//! Then, the event handler updates the metrics depending on the received event. -//! -//! For example, if you send the event [`Event::Udp4Connect`](crate::packages::statistics::event::Event::Udp4Connect): -//! -//! ```text -//! let result = event_sender.send_event(Event::Udp4Connect).await; -//! ``` -//! -//! Eventually the counter for UDP connections from IPv4 peers will be increased. -//! -//! ```rust,no_run -//! pub struct Metrics { -//! // ... -//! pub udp4_connections_handled: u64, // This will be incremented -//! // ... -//! } -//! ``` -use std::sync::Arc; - -use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; -use packages::statistics::metrics::Metrics; -use packages::statistics::repository::Repository; -use tokio::sync::RwLock; -use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; - -use crate::packages; -use crate::servers::udp::server::banning::BanService; - -/// All the metrics collected by the tracker. -#[derive(Debug, PartialEq)] -pub struct TrackerMetrics { - /// Domain level metrics. - /// - /// General metrics for all torrents (number of seeders, leechers, etcetera) - pub torrents_metrics: TorrentsMetrics, - - /// Application level metrics. Usage statistics/metrics. - /// - /// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera) - pub protocol_metrics: Metrics, -} - -/// It returns all the [`TrackerMetrics`] -pub async fn get_metrics( - in_memory_torrent_repository: Arc, - ban_service: Arc>, - stats_repository: Arc, -) -> TrackerMetrics { - let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics(); - let stats = stats_repository.get_stats().await; - let udp_banned_ips_total = ban_service.read().await.get_banned_ips_total(); - - TrackerMetrics { - torrents_metrics, - protocol_metrics: Metrics { - // TCPv4 - tcp4_connections_handled: stats.tcp4_connections_handled, - tcp4_announces_handled: stats.tcp4_announces_handled, - tcp4_scrapes_handled: stats.tcp4_scrapes_handled, - // TCPv6 - tcp6_connections_handled: stats.tcp6_connections_handled, - tcp6_announces_handled: stats.tcp6_announces_handled, - tcp6_scrapes_handled: stats.tcp6_scrapes_handled, - // UDP - udp_requests_aborted: stats.udp_requests_aborted, - udp_requests_banned: stats.udp_requests_banned, - udp_banned_ips_total: udp_banned_ips_total as u64, - udp_avg_connect_processing_time_ns: stats.udp_avg_connect_processing_time_ns, - udp_avg_announce_processing_time_ns: stats.udp_avg_announce_processing_time_ns, - udp_avg_scrape_processing_time_ns: stats.udp_avg_scrape_processing_time_ns, - // UDPv4 - udp4_requests: stats.udp4_requests, - udp4_connections_handled: stats.udp4_connections_handled, - udp4_announces_handled: stats.udp4_announces_handled, - udp4_scrapes_handled: stats.udp4_scrapes_handled, - udp4_responses: stats.udp4_responses, - udp4_errors_handled: stats.udp4_errors_handled, - // UDPv6 - udp6_requests: stats.udp6_requests, - udp6_connections_handled: stats.udp6_connections_handled, - udp6_announces_handled: stats.udp6_announces_handled, - udp6_scrapes_handled: stats.udp6_scrapes_handled, - udp6_responses: stats.udp6_responses, - udp6_errors_handled: stats.udp6_errors_handled, - }, - } -} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use bittorrent_tracker_core::{self}; - use tokio::sync::RwLock; - use torrust_tracker_configuration::Configuration; - use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; - use torrust_tracker_test_helpers::configuration; - - use crate::packages::statistics; - use crate::packages::statistics::services::{get_metrics, TrackerMetrics}; - use crate::servers::udp::server::banning::BanService; - use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; - - pub fn tracker_configuration() -> Configuration { - configuration::ephemeral() - } - - #[tokio::test] - async fn the_statistics_service_should_return_the_tracker_metrics() { - let config = tracker_configuration(); - - let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_repository = Arc::new(stats_repository); - let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); - - let tracker_metrics = get_metrics( - in_memory_torrent_repository.clone(), - ban_service.clone(), - stats_repository.clone(), - ) - .await; - - assert_eq!( - tracker_metrics, - TrackerMetrics { - torrents_metrics: TorrentsMetrics::default(), - protocol_metrics: statistics::metrics::Metrics::default(), - } - ); - } -} diff --git a/src/packages/statistics/setup.rs b/src/packages/statistics/setup.rs deleted file mode 100644 index 2a187dcf0..000000000 --- a/src/packages/statistics/setup.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Setup for the tracker statistics. -//! -//! The [`factory`] function builds the structs needed for handling the tracker metrics. -use crate::packages::statistics; - -/// It builds the structs needed for handling the tracker metrics. -/// -/// It returns: -/// -/// - An statistics event [`Sender`](crate::packages::statistics::event::sender::Sender) that allows you to send events related to statistics. -/// - An statistics [`Repository`](crate::packages::statistics::repository::Repository) which is an in-memory repository for the tracker metrics. -/// -/// When the input argument `tracker_usage_statistics`is false the setup does not run the event listeners, consequently the statistics -/// events are sent are received but not dispatched to the handler. -#[must_use] -pub fn factory( - tracker_usage_statistics: bool, -) -> ( - Option>, - statistics::repository::Repository, -) { - let mut stats_event_sender = None; - - let mut stats_tracker = statistics::keeper::Keeper::new(); - - if tracker_usage_statistics { - stats_event_sender = Some(stats_tracker.run_event_listener()); - } - - (stats_event_sender, stats_tracker.repository) -} - -#[cfg(test)] -mod test { - use super::factory; - - #[tokio::test] - async fn should_not_send_any_event_when_statistics_are_disabled() { - let tracker_usage_statistics = false; - - let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); - - assert!(stats_event_sender.is_none()); - } - - #[tokio::test] - async fn should_send_events_when_statistics_are_enabled() { - let tracker_usage_statistics = true; - - let (stats_event_sender, _stats_repository) = factory(tracker_usage_statistics); - - assert!(stats_event_sender.is_some()); - } -} diff --git a/src/packages/udp_tracker_core/statistics/services.rs b/src/packages/udp_tracker_core/statistics/services.rs index 85ca08e54..80e1d8fb5 100644 --- a/src/packages/udp_tracker_core/statistics/services.rs +++ b/src/packages/udp_tracker_core/statistics/services.rs @@ -110,6 +110,7 @@ mod tests { use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_test_helpers::configuration; + use crate::packages::udp_tracker_core; use crate::packages::udp_tracker_core::statistics; use crate::packages::udp_tracker_core::statistics::services::{get_metrics, TrackerMetrics}; use crate::servers::udp::server::banning::BanService; @@ -124,14 +125,16 @@ mod tests { let config = tracker_configuration(); let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); - let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_repository = Arc::new(stats_repository); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); + let (_udp_stats_event_sender, udp_stats_repository) = + udp_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); + let udp_stats_repository = Arc::new(udp_stats_repository); + let tracker_metrics = get_metrics( in_memory_torrent_repository.clone(), ban_service.clone(), - stats_repository.clone(), + udp_stats_repository.clone(), ) .await; diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 594a11ea1..a6671e14a 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -21,7 +21,6 @@ use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; use bittorrent_tracker_core::whitelist; use hyper::StatusCode; -use packages::statistics::event::sender::Sender; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::AnnounceData; @@ -34,7 +33,7 @@ use crate::servers::http::v1::extractors::authentication_key::Extract as Extract use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; use crate::servers::http::v1::handlers::common::auth; use crate::servers::http::v1::services::{self}; -use crate::{packages, CurrentClock}; +use crate::CurrentClock; /// It handles the `announce` request when the HTTP tracker does not require /// authentication (no PATH `key` parameter required). @@ -46,7 +45,6 @@ pub async fn handle_without_key( Arc, Arc, Arc, - Arc>>, Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, @@ -60,7 +58,6 @@ pub async fn handle_without_key( &state.2, &state.3, &state.4, - &state.5, &announce_request, &client_ip_sources, None, @@ -78,7 +75,6 @@ pub async fn handle_with_key( Arc, Arc, Arc, - Arc>>, Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, @@ -93,7 +89,6 @@ pub async fn handle_with_key( &state.2, &state.3, &state.4, - &state.5, &announce_request, &client_ip_sources, Some(key), @@ -111,7 +106,6 @@ async fn handle( announce_handler: &Arc, authentication_service: &Arc, whitelist_authorization: &Arc, - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -122,7 +116,6 @@ async fn handle( announce_handler, authentication_service, whitelist_authorization, - opt_stats_event_sender, opt_http_stats_event_sender, announce_request, client_ip_sources, @@ -148,7 +141,6 @@ async fn handle_announce( announce_handler: &Arc, authentication_service: &Arc, whitelist_authorization: &Arc, - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -188,7 +180,6 @@ async fn handle_announce( let announce_data = services::announce::invoke( announce_handler.clone(), - opt_stats_event_sender.clone(), opt_http_stats_event_sender.clone(), announce_request.info_hash, &mut peer, @@ -269,17 +260,14 @@ mod tests { use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; - use packages::statistics; - use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; - use crate::packages::{self, http_tracker_core}; + use crate::packages::http_tracker_core; struct CoreTrackerServices { pub core_config: Arc, pub announce_handler: Arc, - pub stats_event_sender: Arc>>, pub whitelist_authorization: Arc, pub authentication_service: Arc, } @@ -319,9 +307,6 @@ mod tests { &db_torrent_repository, )); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); - // HTTP stats let (http_stats_event_sender, http_stats_repository) = http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); @@ -332,7 +317,6 @@ mod tests { CoreTrackerServices { core_config, announce_handler, - stats_event_sender, whitelist_authorization, authentication_service, }, @@ -389,7 +373,6 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), @@ -417,7 +400,6 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), @@ -447,7 +429,6 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &http_core_tracker_services.http_stats_event_sender, &announce_request, &sample_client_ip_sources(), @@ -488,7 +469,6 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &client_ip_sources, @@ -526,7 +506,6 @@ mod tests { &core_tracker_services.announce_handler, &core_tracker_services.authentication_service, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &http_core_tracker_services.http_stats_event_sender, &sample_announce_request(), &client_ip_sources, diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index d41a3742f..09af385fb 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -16,11 +16,10 @@ use bittorrent_tracker_core::authentication::service::AuthenticationService; use bittorrent_tracker_core::authentication::Key; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use hyper::StatusCode; -use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::core::ScrapeData; -use crate::packages::{self, http_tracker_core}; +use crate::packages::http_tracker_core; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; use crate::servers::http::v1::extractors::scrape_request::ExtractRequest; @@ -35,7 +34,6 @@ pub async fn handle_without_key( Arc, Arc, Arc, - Arc>>, Arc>>, )>, ExtractRequest(scrape_request): ExtractRequest, @@ -48,7 +46,6 @@ pub async fn handle_without_key( &state.1, &state.2, &state.3, - &state.4, &scrape_request, &client_ip_sources, None, @@ -67,7 +64,6 @@ pub async fn handle_with_key( Arc, Arc, Arc, - Arc>>, Arc>>, )>, ExtractRequest(scrape_request): ExtractRequest, @@ -81,7 +77,6 @@ pub async fn handle_with_key( &state.1, &state.2, &state.3, - &state.4, &scrape_request, &client_ip_sources, Some(key), @@ -94,7 +89,6 @@ async fn handle( core_config: &Arc, scrape_handler: &Arc, authentication_service: &Arc, - stats_event_sender: &Arc>>, http_stats_event_sender: &Arc>>, scrape_request: &Scrape, client_ip_sources: &ClientIpSources, @@ -104,7 +98,6 @@ async fn handle( core_config, scrape_handler, authentication_service, - stats_event_sender, http_stats_event_sender, scrape_request, client_ip_sources, @@ -129,7 +122,6 @@ async fn handle_scrape( core_config: &Arc, scrape_handler: &Arc, authentication_service: &Arc, - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, scrape_request: &Scrape, client_ip_sources: &ClientIpSources, @@ -159,20 +151,13 @@ async fn handle_scrape( if return_real_scrape_data { Ok(services::scrape::invoke( scrape_handler, - opt_stats_event_sender, opt_http_stats_event_sender, &scrape_request.info_hashes, &peer_ip, ) .await) } else { - Ok(services::scrape::fake( - opt_stats_event_sender, - opt_http_stats_event_sender, - &scrape_request.info_hashes, - &peer_ip, - ) - .await) + Ok(services::scrape::fake(opt_http_stats_event_sender, &scrape_request.info_hashes, &peer_ip).await) } } @@ -198,16 +183,14 @@ mod tests { use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; - use packages::statistics; use torrust_tracker_configuration::{Configuration, Core}; use torrust_tracker_test_helpers::configuration; - use crate::packages::{self, http_tracker_core}; + use crate::packages::http_tracker_core; struct CoreTrackerServices { pub core_config: Arc, pub scrape_handler: Arc, - pub stats_event_sender: Arc>>, pub authentication_service: Arc, } @@ -240,9 +223,6 @@ mod tests { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); - // HTTP stats let (http_stats_event_sender, _http_stats_repository) = http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); @@ -252,7 +232,6 @@ mod tests { CoreTrackerServices { core_config, scrape_handler, - stats_event_sender, authentication_service, }, CoreHttpTrackerServices { http_stats_event_sender }, @@ -299,7 +278,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, - &core_tracker_services.stats_event_sender, &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), @@ -325,7 +303,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, - &core_tracker_services.stats_event_sender, &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), @@ -357,7 +334,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, - &core_tracker_services.stats_event_sender, &core_http_tracker_services.http_stats_event_sender, &scrape_request, &sample_client_ip_sources(), @@ -393,7 +369,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, - &core_tracker_services.stats_event_sender, &core_http_tracker_services.http_stats_event_sender, &sample_scrape_request(), &client_ip_sources, @@ -430,7 +405,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.scrape_handler, &core_tracker_services.authentication_service, - &core_tracker_services.stats_event_sender, &core_http_tracker_services.http_stats_event_sender, &sample_scrape_request(), &client_ip_sources, diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index 7caccb673..73f4e5f29 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -43,7 +43,6 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.announce_handler.clone(), http_tracker_container.authentication_service.clone(), http_tracker_container.whitelist_authorization.clone(), - http_tracker_container.stats_event_sender.clone(), http_tracker_container.http_stats_event_sender.clone(), )), ) @@ -54,7 +53,6 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.announce_handler.clone(), http_tracker_container.authentication_service.clone(), http_tracker_container.whitelist_authorization.clone(), - http_tracker_container.stats_event_sender.clone(), http_tracker_container.http_stats_event_sender.clone(), )), ) @@ -65,7 +63,6 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.core_config.clone(), http_tracker_container.scrape_handler.clone(), http_tracker_container.authentication_service.clone(), - http_tracker_container.stats_event_sender.clone(), http_tracker_container.http_stats_event_sender.clone(), )), ) @@ -75,7 +72,6 @@ pub fn router(http_tracker_container: Arc, server_socket_a http_tracker_container.core_config.clone(), http_tracker_container.scrape_handler.clone(), http_tracker_container.authentication_service.clone(), - http_tracker_container.stats_event_sender.clone(), http_tracker_container.http_stats_event_sender.clone(), )), ) diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index e7170c7e1..bc21657af 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -5,19 +5,17 @@ //! It delegates the `announce` logic to the [`AnnounceHandler`] and it returns //! the [`AnnounceData`]. //! -//! It also sends an [`statistics::event::Event`] +//! It also sends an [`http_tracker_core::statistics::event::Event`] //! because events are specific for the HTTP tracker. use std::net::IpAddr; use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; -use packages::statistics; -use packages::statistics::event::sender::Sender; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; -use crate::packages::{self, http_tracker_core}; +use crate::packages::http_tracker_core; /// The HTTP tracker `announce` service. /// @@ -31,7 +29,6 @@ use crate::packages::{self, http_tracker_core}; /// > each `announce` request. pub async fn invoke( announce_handler: Arc, - opt_stats_event_sender: Arc>>, opt_http_stats_event_sender: Arc>>, info_hash: InfoHash, peer: &mut peer::Peer, @@ -42,17 +39,6 @@ pub async fn invoke( // The tracker could change the original peer ip let announce_data = announce_handler.announce(&info_hash, peer, &original_peer_ip, peers_wanted); - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match original_peer_ip { - IpAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Tcp4Announce).await; - } - IpAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Tcp6Announce).await; - } - } - } - if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() { match original_peer_ip { IpAddr::V4(_) => { @@ -81,8 +67,6 @@ mod tests { use bittorrent_tracker_core::databases::setup::initialize_database; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; - use packages::statistics; - use packages::statistics::event::sender::Sender; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; @@ -90,7 +74,6 @@ mod tests { struct CoreTrackerServices { pub core_config: Arc, pub announce_handler: Arc, - pub stats_event_sender: Arc>>, } struct CoreHttpTrackerServices { @@ -111,9 +94,6 @@ mod tests { &db_torrent_repository, )); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); - // HTTP stats let (http_stats_event_sender, http_stats_repository) = http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics); @@ -124,7 +104,6 @@ mod tests { CoreTrackerServices { core_config, announce_handler, - stats_event_sender, }, CoreHttpTrackerServices { http_stats_event_sender }, ) @@ -157,17 +136,9 @@ mod tests { use futures::future::BoxFuture; use mockall::mock; - use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; - use crate::packages::{self, http_tracker_core}; - - mock! { - StatsEventSender {} - impl Sender for StatsEventSender { - fn send_event(&self, event: Event) -> BoxFuture<'static,Option > > > ; - } - } + use crate::packages::http_tracker_core; mock! { HttpStatsEventSender {} @@ -187,17 +158,16 @@ mod tests { use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use mockall::predicate::eq; - use packages::statistics; use torrust_tracker_primitives::core::AnnounceData; use torrust_tracker_primitives::peer; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use torrust_tracker_test_helpers::configuration; use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; - use crate::packages::{self, http_tracker_core}; + use crate::packages::http_tracker_core; use crate::servers::http::v1::services::announce::invoke; use crate::servers::http::v1::services::announce::tests::{ - initialize_core_tracker_services, sample_peer, MockHttpStatsEventSender, MockStatsEventSender, + initialize_core_tracker_services, sample_peer, MockHttpStatsEventSender, }; fn initialize_announce_handler() -> Arc { @@ -222,7 +192,6 @@ mod tests { let announce_data = invoke( core_tracker_services.announce_handler.clone(), - core_tracker_services.stats_event_sender.clone(), core_http_tracker_services.http_stats_event_sender.clone(), sample_info_hash(), &mut peer, @@ -245,15 +214,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_tcp_4_announce_event_when_the_peer_uses_ipv4() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp4Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -269,7 +229,6 @@ mod tests { let _announce_data = invoke( announce_handler, - stats_event_sender, http_stats_event_sender, sample_info_hash(), &mut peer, @@ -299,16 +258,6 @@ mod tests { { // Tracker changes the peer IP to the tracker external IP when the peer is using the loopback IP. - // Assert that the event sent is a TCP4 event - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp4Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - // Assert that the event sent is a TCP4 event let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock @@ -325,7 +274,6 @@ mod tests { let _announce_data = invoke( announce_handler, - stats_event_sender, http_stats_event_sender, sample_info_hash(), &mut peer, @@ -337,16 +285,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_tcp_6_announce_event_when_the_peer_uses_ipv6_even_if_the_tracker_changes_the_peer_ip_to_ipv4() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp6Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - - // Assert that the event sent is a TCP4 event let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -362,7 +300,6 @@ mod tests { let _announce_data = invoke( announce_handler, - stats_event_sender, http_stats_event_sender, sample_info_hash(), &mut peer, diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index e745609aa..5325b188b 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -5,18 +5,16 @@ //! It delegates the `scrape` logic to the [`ScrapeHandler`] and it returns the //! [`ScrapeData`]. //! -//! It also sends an [`statistics::event::Event`] +//! It also sends an [`http_tracker_core::statistics::event::Event`] //! because events are specific for the HTTP tracker. use std::net::IpAddr; use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; -use packages::statistics::event::sender::Sender; -use packages::statistics::{self}; use torrust_tracker_primitives::core::ScrapeData; -use crate::packages::{self, http_tracker_core}; +use crate::packages::http_tracker_core; /// The HTTP tracker `scrape` service. /// @@ -30,14 +28,13 @@ use crate::packages::{self, http_tracker_core}; /// > each `scrape` request. pub async fn invoke( scrape_handler: &Arc, - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, info_hashes: &Vec, original_peer_ip: &IpAddr, ) -> ScrapeData { let scrape_data = scrape_handler.scrape(info_hashes).await; - send_scrape_event(original_peer_ip, opt_stats_event_sender, opt_http_stats_event_sender).await; + send_scrape_event(original_peer_ip, opt_http_stats_event_sender).await; scrape_data } @@ -49,32 +46,19 @@ pub async fn invoke( /// /// > **NOTICE**: tracker statistics are not updated in this case. pub async fn fake( - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, info_hashes: &Vec, original_peer_ip: &IpAddr, ) -> ScrapeData { - send_scrape_event(original_peer_ip, opt_stats_event_sender, opt_http_stats_event_sender).await; + send_scrape_event(original_peer_ip, opt_http_stats_event_sender).await; ScrapeData::zeroed(info_hashes) } async fn send_scrape_event( original_peer_ip: &IpAddr, - opt_stats_event_sender: &Arc>>, opt_http_stats_event_sender: &Arc>>, ) { - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match original_peer_ip { - IpAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Tcp4Scrape).await; - } - IpAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Tcp6Scrape).await; - } - } - } - if let Some(http_stats_event_sender) = opt_http_stats_event_sender.as_deref() { match original_peer_ip { IpAddr::V4(_) => { @@ -109,13 +93,11 @@ mod tests { use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use futures::future::BoxFuture; use mockall::mock; - use packages::statistics::event::sender::Sender; - use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; - use crate::packages::{self, http_tracker_core}; + use crate::packages::http_tracker_core; fn initialize_announce_and_scrape_handlers_for_public_tracker() -> (Arc, Arc) { let config = configuration::ephemeral_public(); @@ -161,13 +143,6 @@ mod tests { Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)) } - mock! { - StatsEventSender {} - impl Sender for StatsEventSender { - fn send_event(&self, event: Event) -> BoxFuture<'static,Option > > > ; - } - } - mock! { HttpStatsEventSender {} impl http_tracker_core::statistics::event::sender::Sender for HttpStatsEventSender { @@ -183,7 +158,6 @@ mod tests { use bittorrent_tracker_core::announce_handler::PeersWanted; use mockall::predicate::eq; - use packages::statistics; use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; @@ -191,14 +165,11 @@ mod tests { use crate::servers::http::v1::services::scrape::invoke; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, initialize_scrape_handler, sample_info_hash, - sample_info_hashes, sample_peer, MockHttpStatsEventSender, MockStatsEventSender, + sample_info_hashes, sample_peer, MockHttpStatsEventSender, }; #[tokio::test] async fn it_should_return_the_scrape_data_for_a_torrent() { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (http_stats_event_sender, _http_stats_repository) = packages::http_tracker_core::statistics::setup::factory(false); let http_stats_event_sender = Arc::new(http_stats_event_sender); @@ -213,14 +184,7 @@ mod tests { let original_peer_ip = peer.ip(); announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); - let scrape_data = invoke( - &scrape_handler, - &stats_event_sender, - &http_stats_event_sender, - &info_hashes, - &original_peer_ip, - ) - .await; + let scrape_data = invoke(&scrape_handler, &http_stats_event_sender, &info_hashes, &original_peer_ip).await; let mut expected_scrape_data = ScrapeData::empty(); expected_scrape_data.add_file( @@ -237,15 +201,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_tcp_4_scrape_event_when_the_peer_uses_ipv4() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp4Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -259,27 +214,11 @@ mod tests { let peer_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)); - invoke( - &scrape_handler, - &stats_event_sender, - &http_stats_event_sender, - &sample_info_hashes(), - &peer_ip, - ) - .await; + invoke(&scrape_handler, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } #[tokio::test] async fn it_should_send_the_tcp_6_scrape_event_when_the_peer_uses_ipv6() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp6Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -293,14 +232,7 @@ mod tests { let peer_ip = IpAddr::V6(Ipv6Addr::new(0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969)); - invoke( - &scrape_handler, - &stats_event_sender, - &http_stats_event_sender, - &sample_info_hashes(), - &peer_ip, - ) - .await; + invoke(&scrape_handler, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } } @@ -312,21 +244,17 @@ mod tests { use bittorrent_tracker_core::announce_handler::PeersWanted; use mockall::predicate::eq; - use packages::statistics; use torrust_tracker_primitives::core::ScrapeData; use crate::packages::{self, http_tracker_core}; use crate::servers::http::v1::services::scrape::fake; use crate::servers::http::v1::services::scrape::tests::{ initialize_announce_and_scrape_handlers_for_public_tracker, sample_info_hash, sample_info_hashes, sample_peer, - MockHttpStatsEventSender, MockStatsEventSender, + MockHttpStatsEventSender, }; #[tokio::test] async fn it_should_always_return_the_zeroed_scrape_data_for_a_torrent() { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (http_stats_event_sender, _http_stats_repository) = packages::http_tracker_core::statistics::setup::factory(false); let http_stats_event_sender = Arc::new(http_stats_event_sender); @@ -341,7 +269,7 @@ mod tests { let original_peer_ip = peer.ip(); announce_handler.announce(&info_hash, &mut peer, &original_peer_ip, &PeersWanted::All); - let scrape_data = fake(&stats_event_sender, &http_stats_event_sender, &info_hashes, &original_peer_ip).await; + let scrape_data = fake(&http_stats_event_sender, &info_hashes, &original_peer_ip).await; let expected_scrape_data = ScrapeData::zeroed(&info_hashes); @@ -350,15 +278,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_tcp_4_scrape_event_when_the_peer_uses_ipv4() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp4Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -370,20 +289,11 @@ mod tests { let peer_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)); - fake(&stats_event_sender, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; + fake(&http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } #[tokio::test] async fn it_should_send_the_tcp_6_scrape_event_when_the_peer_uses_ipv6() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Tcp6Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut http_stats_event_sender_mock = MockHttpStatsEventSender::new(); http_stats_event_sender_mock .expect_send_event() @@ -395,7 +305,7 @@ mod tests { let peer_ip = IpAddr::V6(Ipv6Addr::new(0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969, 0x6969)); - fake(&stats_event_sender, &http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; + fake(&http_stats_event_sender, &sample_info_hashes(), &peer_ip).await; } } } diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 4c943516e..59833b715 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -14,7 +14,6 @@ use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::announce_handler::{AnnounceHandler, PeersWanted}; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use bittorrent_tracker_core::whitelist; -use packages::statistics::event::sender::Sender; use torrust_tracker_clock::clock::Time as _; use torrust_tracker_configuration::Core; use tracing::{instrument, Level}; @@ -24,11 +23,11 @@ use zerocopy::network_endian::I32; use super::connection_cookie::{check, make}; use super::RawRequest; use crate::container::UdpTrackerContainer; -use crate::packages::{statistics, udp_tracker_core}; +use crate::packages::udp_tracker_core; use crate::servers::udp::error::Error; use crate::servers::udp::{peer_builder, UDP_TRACKER_LOG_TARGET}; use crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS; -use crate::{packages, CurrentClock}; +use crate::CurrentClock; #[derive(Debug, Clone, PartialEq)] pub(super) struct CookieTimeValues { @@ -98,7 +97,6 @@ pub(crate) async fn handle_packet( udp_request.from, local_addr, request_id, - &udp_tracker_container.stats_event_sender, &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range.clone(), &e, @@ -112,7 +110,6 @@ pub(crate) async fn handle_packet( udp_request.from, local_addr, request_id, - &udp_tracker_container.stats_event_sender, &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range.clone(), &e, @@ -146,7 +143,6 @@ pub async fn handle_request( Request::Connect(connect_request) => Ok(handle_connect( remote_addr, &connect_request, - &udp_tracker_container.stats_event_sender, &udp_tracker_container.udp_stats_event_sender, cookie_time_values.issue_time, ) @@ -158,7 +154,6 @@ pub async fn handle_request( &udp_tracker_container.core_config, &udp_tracker_container.announce_handler, &udp_tracker_container.whitelist_authorization, - &udp_tracker_container.stats_event_sender, &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range, ) @@ -169,7 +164,6 @@ pub async fn handle_request( remote_addr, &scrape_request, &udp_tracker_container.scrape_handler, - &udp_tracker_container.stats_event_sender, &udp_tracker_container.udp_stats_event_sender, cookie_time_values.valid_range, ) @@ -184,11 +178,10 @@ pub async fn handle_request( /// # Errors /// /// This function does not ever return an error. -#[instrument(fields(transaction_id), skip(opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id), skip(opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_connect( remote_addr: SocketAddr, request: &ConnectRequest, - opt_stats_event_sender: &Arc>>, opt_udp_stats_event_sender: &Arc>>, cookie_issue_time: f64, ) -> Response { @@ -203,17 +196,6 @@ pub async fn handle_connect( connection_id, }; - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match remote_addr { - SocketAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp4Connect).await; - } - SocketAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp6Connect).await; - } - } - } - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { match remote_addr { SocketAddr::V4(_) => { @@ -239,14 +221,13 @@ pub async fn handle_connect( /// /// If a error happens in the `handle_announce` function, it will just return the `ServerError`. #[allow(clippy::too_many_arguments)] -#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_handler, whitelist_authorization, opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id, info_hash), skip(announce_handler, whitelist_authorization, opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_announce( remote_addr: SocketAddr, request: &AnnounceRequest, core_config: &Arc, announce_handler: &Arc, whitelist_authorization: &Arc, - opt_stats_event_sender: &Arc>>, opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -281,17 +262,6 @@ pub async fn handle_announce( let response = announce_handler.announce(&info_hash, &mut peer, &remote_client_ip, &peers_wanted); - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match remote_client_ip { - IpAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp4Announce).await; - } - IpAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp6Announce).await; - } - } - } - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { match remote_client_ip { IpAddr::V4(_) => { @@ -367,12 +337,11 @@ pub async fn handle_announce( /// # Errors /// /// This function does not ever return an error. -#[instrument(fields(transaction_id, connection_id), skip(scrape_handler, opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id), skip(scrape_handler, opt_udp_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_scrape( remote_addr: SocketAddr, request: &ScrapeRequest, scrape_handler: &Arc, - opt_stats_event_sender: &Arc>>, opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -414,17 +383,6 @@ pub async fn handle_scrape( torrent_stats.push(scrape_entry); } - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match remote_addr { - SocketAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp4Scrape).await; - } - SocketAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp6Scrape).await; - } - } - } - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { match remote_addr { SocketAddr::V4(_) => { @@ -449,12 +407,11 @@ pub async fn handle_scrape( } #[allow(clippy::too_many_arguments)] -#[instrument(fields(transaction_id), skip(opt_stats_event_sender, opt_udp_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id), skip(opt_udp_stats_event_sender), ret(level = Level::TRACE))] async fn handle_error( remote_addr: SocketAddr, local_addr: SocketAddr, request_id: Uuid, - opt_stats_event_sender: &Arc>>, opt_udp_stats_event_sender: &Arc>>, cookie_valid_range: Range, e: &Error, @@ -492,17 +449,6 @@ async fn handle_error( }; if e.1.is_some() { - if let Some(stats_event_sender) = opt_stats_event_sender.as_deref() { - match remote_addr { - SocketAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp4Error).await; - } - SocketAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp6Error).await; - } - } - } - if let Some(udp_stats_event_sender) = opt_udp_stats_event_sender.as_deref() { match remote_addr { SocketAddr::V4(_) => { @@ -549,8 +495,6 @@ mod tests { use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use futures::future::BoxFuture; use mockall::mock; - use packages::statistics::event::sender::Sender; - use packages::statistics::event::Event; use tokio::sync::mpsc::error::SendError; use torrust_tracker_clock::clock::Time; use torrust_tracker_configuration::{Configuration, Core}; @@ -558,7 +502,7 @@ mod tests { use torrust_tracker_test_helpers::configuration; use super::gen_remote_fingerprint; - use crate::packages::{statistics, udp_tracker_core}; + use crate::packages::udp_tracker_core; use crate::{packages, CurrentClock}; struct CoreTrackerServices { @@ -566,7 +510,6 @@ mod tests { pub announce_handler: Arc, pub scrape_handler: Arc, pub in_memory_torrent_repository: Arc, - pub stats_event_sender: Arc>>, pub in_memory_whitelist: Arc, pub whitelist_authorization: Arc, } @@ -605,9 +548,6 @@ mod tests { )); let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -617,7 +557,6 @@ mod tests { announce_handler, scrape_handler, in_memory_torrent_repository, - stats_event_sender, in_memory_whitelist, whitelist_authorization, }, @@ -719,13 +658,6 @@ mod tests { } } - mock! { - StatsEventSender {} - impl Sender for StatsEventSender { - fn send_event(&self, event: Event) -> BoxFuture<'static,Option > > > ; - } - } - mock! { UdpStatsEventSender {} impl udp_tracker_core::statistics::event::sender::Sender for UdpStatsEventSender { @@ -740,7 +672,6 @@ mod tests { use aquatic_udp_protocol::{ConnectRequest, ConnectResponse, Response, TransactionId}; use mockall::predicate::eq; - use packages::statistics; use super::{sample_ipv4_socket_address, sample_ipv6_remote_addr}; use crate::packages::{self, udp_tracker_core}; @@ -748,7 +679,7 @@ mod tests { use crate::servers::udp::handlers::handle_connect; use crate::servers::udp::handlers::tests::{ sample_ipv4_remote_addr, sample_ipv4_remote_addr_fingerprint, sample_ipv6_remote_addr_fingerprint, sample_issue_time, - MockStatsEventSender, MockUdpStatsEventSender, + MockUdpStatsEventSender, }; fn sample_connect_request() -> ConnectRequest { @@ -759,9 +690,6 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_the_same_transaction_id_as_the_connect_request() { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -772,7 +700,6 @@ mod tests { let response = handle_connect( sample_ipv4_remote_addr(), &request, - &stats_event_sender, &udp_stats_event_sender, sample_issue_time(), ) @@ -789,9 +716,6 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_a_new_connection_id() { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -802,7 +726,6 @@ mod tests { let response = handle_connect( sample_ipv4_remote_addr(), &request, - &stats_event_sender, &udp_stats_event_sender, sample_issue_time(), ) @@ -819,9 +742,6 @@ mod tests { #[tokio::test] async fn a_connect_response_should_contain_a_new_connection_id_ipv6() { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -832,7 +752,6 @@ mod tests { let response = handle_connect( sample_ipv6_remote_addr(), &request, - &stats_event_sender, &udp_stats_event_sender, sample_issue_time(), ) @@ -849,15 +768,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_upd4_connect_event_when_a_client_tries_to_connect_using_a_ip4_socket_address() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp4Connect)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -872,7 +782,6 @@ mod tests { handle_connect( client_socket_address, &sample_connect_request(), - &stats_event_sender, &udp_stats_event_sender, sample_issue_time(), ) @@ -881,15 +790,6 @@ mod tests { #[tokio::test] async fn it_should_send_the_upd6_connect_event_when_a_client_tries_to_connect_using_a_ip6_socket_address() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp6Connect)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -902,7 +802,6 @@ mod tests { handle_connect( sample_ipv6_remote_addr(), &sample_connect_request(), - &stats_event_sender, &udp_stats_event_sender, sample_issue_time(), ) @@ -999,13 +898,13 @@ mod tests { use mockall::predicate::eq; use torrust_tracker_configuration::Core; - use crate::packages::{self, statistics, udp_tracker_core}; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ gen_remote_fingerprint, initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv4_socket_address, - sample_issue_time, MockStatsEventSender, MockUdpStatsEventSender, TorrentPeerBuilder, + sample_issue_time, MockUdpStatsEventSender, TorrentPeerBuilder, }; use crate::servers::udp::handlers::{handle_announce, AnnounceResponseFixedData}; @@ -1034,7 +933,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1069,7 +967,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1123,7 +1020,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1158,9 +1054,6 @@ mod tests { announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -1176,7 +1069,6 @@ mod tests { &core_config, &announce_handler, &whitelist_authorization, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1208,15 +1100,6 @@ mod tests { #[tokio::test] async fn should_send_the_upd4_announce_event() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp4Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -1235,7 +1118,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1283,7 +1165,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1322,13 +1203,13 @@ mod tests { use mockall::predicate::eq; use torrust_tracker_configuration::Core; - use crate::packages::{self, statistics, udp_tracker_core}; + use crate::packages::{self, udp_tracker_core}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ gen_remote_fingerprint, initialize_core_tracker_services_for_default_tracker_configuration, initialize_core_tracker_services_for_public_tracker, sample_cookie_valid_range, sample_ipv6_remote_addr, - sample_issue_time, MockStatsEventSender, MockUdpStatsEventSender, TorrentPeerBuilder, + sample_issue_time, MockUdpStatsEventSender, TorrentPeerBuilder, }; use crate::servers::udp::handlers::{handle_announce, AnnounceResponseFixedData}; @@ -1358,7 +1239,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1396,7 +1276,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1450,7 +1329,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1485,9 +1363,6 @@ mod tests { announce_handler: Arc, whitelist_authorization: Arc, ) -> Response { - let (stats_event_sender, _stats_repository) = packages::statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -1506,7 +1381,6 @@ mod tests { &core_config, &announce_handler, &whitelist_authorization, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1538,15 +1412,6 @@ mod tests { #[tokio::test] async fn should_send_the_upd6_announce_event() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp6Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -1571,7 +1436,6 @@ mod tests { &core_tracker_services.core_config, &core_tracker_services.announce_handler, &core_tracker_services.whitelist_authorization, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1592,15 +1456,14 @@ mod tests { use bittorrent_tracker_core::whitelist::authorization::WhitelistAuthorization; use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist; use mockall::predicate::eq; - use packages::statistics; - use crate::packages::{self, udp_tracker_core}; + use crate::packages::udp_tracker_core; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::handle_announce; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ - gen_remote_fingerprint, sample_cookie_valid_range, sample_issue_time, MockStatsEventSender, - MockUdpStatsEventSender, TrackerConfigurationBuilder, + gen_remote_fingerprint, sample_cookie_valid_range, sample_issue_time, MockUdpStatsEventSender, + TrackerConfigurationBuilder, }; #[tokio::test] @@ -1614,15 +1477,6 @@ mod tests { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp6Announce)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -1666,7 +1520,6 @@ mod tests { &core_config, &announce_handler, &whitelist_authorization, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1700,7 +1553,6 @@ mod tests { }; use bittorrent_tracker_core::scrape_handler::ScrapeHandler; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; - use packages::statistics; use super::{gen_remote_fingerprint, TorrentPeerBuilder}; use crate::packages; @@ -1738,7 +1590,6 @@ mod tests { remote_addr, &request, &core_tracker_services.scrape_handler, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1786,9 +1637,6 @@ mod tests { in_memory_torrent_repository: Arc, scrape_handler: Arc, ) -> Response { - let (stats_event_sender, _stats_repository) = statistics::setup::factory(false); - let stats_event_sender = Arc::new(stats_event_sender); - let (udp_stats_event_sender, _udp_stats_repository) = packages::udp_tracker_core::statistics::setup::factory(false); let udp_stats_event_sender = Arc::new(udp_stats_event_sender); @@ -1803,7 +1651,6 @@ mod tests { remote_addr, &request, &scrape_handler, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1880,7 +1727,6 @@ mod tests { remote_addr, &request, &core_tracker_services.scrape_handler, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1919,7 +1765,6 @@ mod tests { remote_addr, &request, &core_tracker_services.scrape_handler, - &core_tracker_services.stats_event_sender, &core_udp_tracker_services.udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -1950,27 +1795,17 @@ mod tests { use std::sync::Arc; use mockall::predicate::eq; - use packages::statistics; use super::sample_scrape_request; - use crate::packages::{self, udp_tracker_core}; + use crate::packages::udp_tracker_core; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv4_remote_addr, MockStatsEventSender, MockUdpStatsEventSender, + sample_ipv4_remote_addr, MockUdpStatsEventSender, }; #[tokio::test] async fn should_send_the_upd4_scrape_event() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp4Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -1989,7 +1824,6 @@ mod tests { remote_addr, &sample_scrape_request(&remote_addr), &core_tracker_services.scrape_handler, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) @@ -2003,27 +1837,17 @@ mod tests { use std::sync::Arc; use mockall::predicate::eq; - use packages::statistics; use super::sample_scrape_request; - use crate::packages::{self, udp_tracker_core}; + use crate::packages::udp_tracker_core; use crate::servers::udp::handlers::handle_scrape; use crate::servers::udp::handlers::tests::{ initialize_core_tracker_services_for_default_tracker_configuration, sample_cookie_valid_range, - sample_ipv6_remote_addr, MockStatsEventSender, MockUdpStatsEventSender, + sample_ipv6_remote_addr, MockUdpStatsEventSender, }; #[tokio::test] async fn should_send_the_upd6_scrape_event() { - let mut stats_event_sender_mock = MockStatsEventSender::new(); - stats_event_sender_mock - .expect_send_event() - .with(eq(statistics::event::Event::Udp6Scrape)) - .times(1) - .returning(|_| Box::pin(future::ready(Some(Ok(()))))); - let stats_event_sender: Arc>> = - Arc::new(Some(Box::new(stats_event_sender_mock))); - let mut udp_stats_event_sender_mock = MockUdpStatsEventSender::new(); udp_stats_event_sender_mock .expect_send_event() @@ -2042,7 +1866,6 @@ mod tests { remote_addr, &sample_scrape_request(&remote_addr), &core_tracker_services.scrape_handler, - &stats_event_sender, &udp_stats_event_sender, sample_cookie_valid_range(), ) diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index 863f82e18..e640749c6 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -5,7 +5,6 @@ use std::time::Duration; use bittorrent_tracker_client::udp::client::check; use derive_more::Constructor; use futures_util::StreamExt; -use packages::statistics; use tokio::select; use tokio::sync::oneshot; use tokio::time::interval; @@ -14,7 +13,7 @@ use tracing::instrument; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; use crate::container::UdpTrackerContainer; -use crate::packages::{self, udp_tracker_core}; +use crate::packages::udp_tracker_core; use crate::servers::logging::STARTED_ON; use crate::servers::registar::ServiceHealthCheckJob; use crate::servers::signals::{shutdown_signal_with_message, Halted}; @@ -163,17 +162,6 @@ impl Launcher { } }; - if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { - match req.from.ip() { - IpAddr::V4(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp4Request).await; - } - IpAddr::V6(_) => { - stats_event_sender.send_event(statistics::event::Event::Udp6Request).await; - } - } - } - if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { match req.from.ip() { IpAddr::V4(_) => { @@ -192,12 +180,6 @@ impl Launcher { if udp_tracker_container.ban_service.read().await.is_banned(&req.from.ip()) { tracing::debug!(target: UDP_TRACKER_LOG_TARGET, local_addr, "Udp::run_udp_server::loop continue: (banned ip)"); - if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { - stats_event_sender - .send_event(statistics::event::Event::UdpRequestBanned) - .await; - } - if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { udp_stats_event_sender .send_event(udp_tracker_core::statistics::event::Event::UdpRequestBanned) @@ -231,12 +213,6 @@ impl Launcher { if old_request_aborted { // Evicted task from active requests buffer was aborted. - if let Some(stats_event_sender) = udp_tracker_container.stats_event_sender.as_deref() { - stats_event_sender - .send_event(statistics::event::Event::UdpRequestAborted) - .await; - } - if let Some(udp_stats_event_sender) = udp_tracker_container.udp_stats_event_sender.as_deref() { udp_stats_event_sender .send_event(udp_tracker_core::statistics::event::Event::UdpRequestAborted) diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index bbf64dfb9..dc55833c2 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -4,14 +4,12 @@ use std::sync::Arc; use std::time::Duration; use aquatic_udp_protocol::Response; -use packages::statistics; -use packages::statistics::event::UdpResponseKind; use tokio::time::Instant; use tracing::{instrument, Level}; use super::bound_socket::BoundSocket; use crate::container::UdpTrackerContainer; -use crate::packages::{self, udp_tracker_core}; +use crate::packages::udp_tracker_core; use crate::servers::udp::handlers::CookieTimeValues; use crate::servers::udp::{handlers, RawRequest}; @@ -61,13 +59,6 @@ impl Processor { Response::Error(e) => format!("Error: {e:?}"), }; - let response_kind = match &response { - Response::Connect(_) => UdpResponseKind::Connect, - Response::AnnounceIpv4(_) | Response::AnnounceIpv6(_) => UdpResponseKind::Announce, - Response::Scrape(_) => UdpResponseKind::Scrape, - Response::Error(_e) => UdpResponseKind::Error, - }; - let udp_response_kind = match &response { Response::Connect(_) => udp_tracker_core::statistics::event::UdpResponseKind::Connect, Response::AnnounceIpv4(_) | Response::AnnounceIpv6(_) => { @@ -92,27 +83,6 @@ impl Processor { tracing::debug!(%bytes_count, %sent_bytes, "sent {response_type}"); } - if let Some(stats_event_sender) = self.udp_tracker_container.stats_event_sender.as_deref() { - match target.ip() { - IpAddr::V4(_) => { - stats_event_sender - .send_event(statistics::event::Event::Udp4Response { - kind: response_kind, - req_processing_time, - }) - .await; - } - IpAddr::V6(_) => { - stats_event_sender - .send_event(statistics::event::Event::Udp6Response { - kind: response_kind, - req_processing_time, - }) - .await; - } - } - } - if let Some(udp_stats_event_sender) = self.udp_tracker_container.udp_stats_event_sender.as_deref() { match target.ip() { IpAddr::V4(_) => { diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 17013250a..97ca13e95 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -6,12 +6,11 @@ use bittorrent_tracker_core::databases::Database; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; use bittorrent_tracker_core::whitelist::manager::WhitelistManager; use futures::executor::block_on; -use packages::statistics::repository::Repository; use torrust_tracker_configuration::Configuration; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::container::HttpTrackerContainer; -use torrust_tracker_lib::packages; +use torrust_tracker_lib::packages::http_tracker_core; use torrust_tracker_lib::servers::http::server::{HttpServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_primitives::peer; @@ -22,7 +21,7 @@ pub struct Environment { pub database: Arc>, pub in_memory_torrent_repository: Arc, pub keys_handler: Arc, - pub stats_repository: Arc, + pub http_stats_repository: Arc, pub whitelist_manager: Arc, pub registar: Registar, @@ -61,7 +60,6 @@ impl Environment { announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), http_stats_event_sender: app_container.http_stats_event_sender.clone(), authentication_service: app_container.authentication_service.clone(), }); @@ -72,7 +70,7 @@ impl Environment { database: app_container.database.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), keys_handler: app_container.keys_handler.clone(), - stats_repository: app_container.stats_repository.clone(), + http_stats_repository: app_container.http_stats_repository.clone(), whitelist_manager: app_container.whitelist_manager.clone(), registar: Registar::default(), @@ -88,7 +86,7 @@ impl Environment { database: self.database.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), keys_handler: self.keys_handler.clone(), - stats_repository: self.stats_repository.clone(), + http_stats_repository: self.http_stats_repository.clone(), whitelist_manager: self.whitelist_manager.clone(), registar: self.registar.clone(), @@ -113,7 +111,7 @@ impl Environment { database: self.database, in_memory_torrent_repository: self.in_memory_torrent_repository, keys_handler: self.keys_handler, - stats_repository: self.stats_repository, + http_stats_repository: self.http_stats_repository, whitelist_manager: self.whitelist_manager, registar: Registar::default(), diff --git a/tests/servers/http/v1/contract.rs b/tests/servers/http/v1/contract.rs index be603161a..48c98fa02 100644 --- a/tests/servers/http/v1/contract.rs +++ b/tests/servers/http/v1/contract.rs @@ -680,7 +680,7 @@ mod for_all_config_modes { .announce(&QueryBuilder::default().query()) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp4_connections_handled, 1); @@ -706,7 +706,7 @@ mod for_all_config_modes { .announce(&QueryBuilder::default().query()) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp6_connections_handled, 1); @@ -731,7 +731,7 @@ mod for_all_config_modes { ) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp6_connections_handled, 0); @@ -750,7 +750,7 @@ mod for_all_config_modes { .announce(&QueryBuilder::default().query()) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp4_announces_handled, 1); @@ -776,7 +776,7 @@ mod for_all_config_modes { .announce(&QueryBuilder::default().query()) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp6_announces_handled, 1); @@ -801,7 +801,7 @@ mod for_all_config_modes { ) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp6_announces_handled, 0); @@ -1173,7 +1173,7 @@ mod for_all_config_modes { ) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp4_scrapes_handled, 1); @@ -1205,7 +1205,7 @@ mod for_all_config_modes { ) .await; - let stats = env.stats_repository.get_stats().await; + let stats = env.http_stats_repository.get_stats().await; assert_eq!(stats.tcp6_scrapes_handled, 1); diff --git a/tests/servers/udp/contract.rs b/tests/servers/udp/contract.rs index d38356ef4..f6e0589f8 100644 --- a/tests/servers/udp/contract.rs +++ b/tests/servers/udp/contract.rs @@ -270,7 +270,7 @@ mod receiving_an_announce_request { info_hash, ); - let udp_requests_banned_before = env.stats_repository.get_stats().await.udp_requests_banned; + let udp_requests_banned_before = env.udp_stats_repository.get_stats().await.udp_requests_banned; // This should return a timeout error match client.send(announce_request.into()).await { @@ -280,7 +280,7 @@ mod receiving_an_announce_request { assert!(client.receive().await.is_err()); - let udp_requests_banned_after = env.stats_repository.get_stats().await.udp_requests_banned; + let udp_requests_banned_after = env.udp_stats_repository.get_stats().await.udp_requests_banned; let udp_banned_ips_total_after = ban_service.read().await.get_banned_ips_total(); // UDP counter for banned requests should be increased by 1 diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index c8ecac1fb..24ce7bab2 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -4,11 +4,10 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; use bittorrent_tracker_core::databases::Database; use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository; -use packages::statistics::repository::Repository; use torrust_tracker_configuration::{Configuration, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::container::UdpTrackerContainer; -use torrust_tracker_lib::packages; +use torrust_tracker_lib::packages::udp_tracker_core; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_lib::servers::udp::server::spawner::Spawner; use torrust_tracker_lib::servers::udp::server::states::{Running, Stopped}; @@ -23,7 +22,7 @@ where pub database: Arc>, pub in_memory_torrent_repository: Arc, - pub stats_repository: Arc, + pub udp_stats_repository: Arc, pub registar: Registar, pub server: Server, @@ -61,7 +60,6 @@ impl Environment { announce_handler: app_container.announce_handler.clone(), scrape_handler: app_container.scrape_handler.clone(), whitelist_authorization: app_container.whitelist_authorization.clone(), - stats_event_sender: app_container.stats_event_sender.clone(), udp_stats_event_sender: app_container.udp_stats_event_sender.clone(), ban_service: app_container.ban_service.clone(), }); @@ -71,7 +69,7 @@ impl Environment { database: app_container.database.clone(), in_memory_torrent_repository: app_container.in_memory_torrent_repository.clone(), - stats_repository: app_container.stats_repository.clone(), + udp_stats_repository: app_container.udp_stats_repository.clone(), registar: Registar::default(), server, @@ -87,7 +85,7 @@ impl Environment { database: self.database.clone(), in_memory_torrent_repository: self.in_memory_torrent_repository.clone(), - stats_repository: self.stats_repository.clone(), + udp_stats_repository: self.udp_stats_repository.clone(), registar: self.registar.clone(), server: self @@ -117,7 +115,7 @@ impl Environment { database: self.database, in_memory_torrent_repository: self.in_memory_torrent_repository, - stats_repository: self.stats_repository, + udp_stats_repository: self.udp_stats_repository, registar: Registar::default(), server: stopped.expect("it stop the udp tracker service"),