Skip to content

Commit 5576938

Browse files
committed
refactor: [torrust#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.
1 parent f33665d commit 5576938

File tree

11 files changed

+239
-16
lines changed

11 files changed

+239
-16
lines changed

src/container.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ pub struct HttpApiContainer {
100100
pub keys_handler: Arc<KeysHandler>,
101101
pub whitelist_manager: Arc<WhitelistManager>,
102102
pub ban_service: Arc<RwLock<BanService>>,
103-
pub stats_event_sender: Arc<Option<Box<dyn Sender>>>,
104-
pub stats_repository: Arc<Repository>,
103+
pub http_stats_repository: Arc<http_tracker_core::statistics::repository::Repository>,
104+
pub udp_stats_repository: Arc<udp_tracker_core::statistics::repository::Repository>,
105105
}
106106

107107
impl HttpApiContainer {
@@ -114,8 +114,8 @@ impl HttpApiContainer {
114114
keys_handler: app_container.keys_handler.clone(),
115115
whitelist_manager: app_container.whitelist_manager.clone(),
116116
ban_service: app_container.ban_service.clone(),
117-
stats_event_sender: app_container.stats_event_sender.clone(),
118-
stats_repository: app_container.stats_repository.clone(),
117+
http_stats_repository: app_container.http_stats_repository.clone(),
118+
udp_stats_repository: app_container.udp_stats_repository.clone(),
119119
}
120120
}
121121
}

src/packages/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
//! It will be moved to the directory `packages`.
44
pub mod http_tracker_core;
55
pub mod statistics;
6+
pub mod tracker_api_core;
67
pub mod udp_tracker_core;

src/packages/tracker_api_core/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod statistics;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/// Metrics collected by the tracker.
2+
///
3+
/// - Number of connections handled
4+
/// - Number of `announce` requests handled
5+
/// - Number of `scrape` request handled
6+
///
7+
/// These metrics are collected for each connection type: UDP and HTTP
8+
/// and also for each IP version used by the peers: IPv4 and IPv6.
9+
#[derive(Debug, PartialEq, Default)]
10+
pub struct Metrics {
11+
/// Total number of TCP (HTTP tracker) connections from IPv4 peers.
12+
/// Since the HTTP tracker spec does not require a handshake, this metric
13+
/// increases for every HTTP request.
14+
pub tcp4_connections_handled: u64,
15+
16+
/// Total number of TCP (HTTP tracker) `announce` requests from IPv4 peers.
17+
pub tcp4_announces_handled: u64,
18+
19+
/// Total number of TCP (HTTP tracker) `scrape` requests from IPv4 peers.
20+
pub tcp4_scrapes_handled: u64,
21+
22+
/// Total number of TCP (HTTP tracker) connections from IPv6 peers.
23+
pub tcp6_connections_handled: u64,
24+
25+
/// Total number of TCP (HTTP tracker) `announce` requests from IPv6 peers.
26+
pub tcp6_announces_handled: u64,
27+
28+
/// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers.
29+
pub tcp6_scrapes_handled: u64,
30+
31+
// UDP
32+
/// Total number of UDP (UDP tracker) requests aborted.
33+
pub udp_requests_aborted: u64,
34+
35+
/// Total number of UDP (UDP tracker) requests banned.
36+
pub udp_requests_banned: u64,
37+
38+
/// Total number of banned IPs.
39+
pub udp_banned_ips_total: u64,
40+
41+
/// Average rounded time spent processing UDP connect requests.
42+
pub udp_avg_connect_processing_time_ns: u64,
43+
44+
/// Average rounded time spent processing UDP announce requests.
45+
pub udp_avg_announce_processing_time_ns: u64,
46+
47+
/// Average rounded time spent processing UDP scrape requests.
48+
pub udp_avg_scrape_processing_time_ns: u64,
49+
50+
// UDPv4
51+
/// Total number of UDP (UDP tracker) requests from IPv4 peers.
52+
pub udp4_requests: u64,
53+
54+
/// Total number of UDP (UDP tracker) connections from IPv4 peers.
55+
pub udp4_connections_handled: u64,
56+
57+
/// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers.
58+
pub udp4_announces_handled: u64,
59+
60+
/// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers.
61+
pub udp4_scrapes_handled: u64,
62+
63+
/// Total number of UDP (UDP tracker) responses from IPv4 peers.
64+
pub udp4_responses: u64,
65+
66+
/// Total number of UDP (UDP tracker) `error` requests from IPv4 peers.
67+
pub udp4_errors_handled: u64,
68+
69+
// UDPv6
70+
/// Total number of UDP (UDP tracker) requests from IPv6 peers.
71+
pub udp6_requests: u64,
72+
73+
/// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers.
74+
pub udp6_connections_handled: u64,
75+
76+
/// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers.
77+
pub udp6_announces_handled: u64,
78+
79+
/// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers.
80+
pub udp6_scrapes_handled: u64,
81+
82+
/// Total number of UDP (UDP tracker) responses from IPv6 peers.
83+
pub udp6_responses: u64,
84+
85+
/// Total number of UDP (UDP tracker) `error` requests from IPv6 peers.
86+
pub udp6_errors_handled: u64,
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod metrics;
2+
pub mod services;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use std::sync::Arc;
2+
3+
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
4+
use packages::tracker_api_core::statistics::metrics::Metrics;
5+
use tokio::sync::RwLock;
6+
use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics;
7+
8+
use crate::packages::{self, http_tracker_core, udp_tracker_core};
9+
use crate::servers::udp::server::banning::BanService;
10+
11+
/// All the metrics collected by the tracker.
12+
#[derive(Debug, PartialEq)]
13+
pub struct TrackerMetrics {
14+
/// Domain level metrics.
15+
///
16+
/// General metrics for all torrents (number of seeders, leechers, etcetera)
17+
pub torrents_metrics: TorrentsMetrics,
18+
19+
/// Application level metrics. Usage statistics/metrics.
20+
///
21+
/// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera)
22+
pub protocol_metrics: Metrics,
23+
}
24+
25+
/// It returns all the [`TrackerMetrics`]
26+
pub async fn get_metrics(
27+
in_memory_torrent_repository: Arc<InMemoryTorrentRepository>,
28+
ban_service: Arc<RwLock<BanService>>,
29+
http_stats_repository: Arc<http_tracker_core::statistics::repository::Repository>,
30+
udp_stats_repository: Arc<udp_tracker_core::statistics::repository::Repository>,
31+
) -> TrackerMetrics {
32+
let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics();
33+
let udp_banned_ips_total = ban_service.read().await.get_banned_ips_total();
34+
let http_stats = http_stats_repository.get_stats().await;
35+
let udp_stats = udp_stats_repository.get_stats().await;
36+
37+
TrackerMetrics {
38+
torrents_metrics,
39+
protocol_metrics: Metrics {
40+
// TCPv4
41+
tcp4_connections_handled: http_stats.tcp4_connections_handled,
42+
tcp4_announces_handled: http_stats.tcp4_announces_handled,
43+
tcp4_scrapes_handled: http_stats.tcp4_scrapes_handled,
44+
// TCPv6
45+
tcp6_connections_handled: http_stats.tcp6_connections_handled,
46+
tcp6_announces_handled: http_stats.tcp6_announces_handled,
47+
tcp6_scrapes_handled: http_stats.tcp6_scrapes_handled,
48+
// UDP
49+
udp_requests_aborted: udp_stats.udp_requests_aborted,
50+
udp_requests_banned: udp_stats.udp_requests_banned,
51+
udp_banned_ips_total: udp_banned_ips_total as u64,
52+
udp_avg_connect_processing_time_ns: udp_stats.udp_avg_connect_processing_time_ns,
53+
udp_avg_announce_processing_time_ns: udp_stats.udp_avg_announce_processing_time_ns,
54+
udp_avg_scrape_processing_time_ns: udp_stats.udp_avg_scrape_processing_time_ns,
55+
// UDPv4
56+
udp4_requests: udp_stats.udp4_requests,
57+
udp4_connections_handled: udp_stats.udp4_connections_handled,
58+
udp4_announces_handled: udp_stats.udp4_announces_handled,
59+
udp4_scrapes_handled: udp_stats.udp4_scrapes_handled,
60+
udp4_responses: udp_stats.udp4_responses,
61+
udp4_errors_handled: udp_stats.udp4_errors_handled,
62+
// UDPv6
63+
udp6_requests: udp_stats.udp6_requests,
64+
udp6_connections_handled: udp_stats.udp6_connections_handled,
65+
udp6_announces_handled: udp_stats.udp6_announces_handled,
66+
udp6_scrapes_handled: udp_stats.udp6_scrapes_handled,
67+
udp6_responses: udp_stats.udp6_responses,
68+
udp6_errors_handled: udp_stats.udp6_errors_handled,
69+
},
70+
}
71+
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use std::sync::Arc;
76+
77+
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
78+
use bittorrent_tracker_core::{self};
79+
use tokio::sync::RwLock;
80+
use torrust_tracker_configuration::Configuration;
81+
use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics;
82+
use torrust_tracker_test_helpers::configuration;
83+
84+
use crate::packages::tracker_api_core::statistics::metrics::Metrics;
85+
use crate::packages::tracker_api_core::statistics::services::{get_metrics, TrackerMetrics};
86+
use crate::packages::{http_tracker_core, udp_tracker_core};
87+
use crate::servers::udp::server::banning::BanService;
88+
use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP;
89+
90+
pub fn tracker_configuration() -> Configuration {
91+
configuration::ephemeral()
92+
}
93+
94+
#[tokio::test]
95+
async fn the_statistics_service_should_return_the_tracker_metrics() {
96+
let config = tracker_configuration();
97+
98+
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
99+
let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP)));
100+
101+
// HTTP stats
102+
let (_http_stats_event_sender, http_stats_repository) =
103+
http_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics);
104+
let http_stats_repository = Arc::new(http_stats_repository);
105+
106+
// UDP stats
107+
let (_udp_stats_event_sender, udp_stats_repository) =
108+
udp_tracker_core::statistics::setup::factory(config.core.tracker_usage_statistics);
109+
let udp_stats_repository = Arc::new(udp_stats_repository);
110+
111+
let tracker_metrics = get_metrics(
112+
in_memory_torrent_repository.clone(),
113+
ban_service.clone(),
114+
http_stats_repository.clone(),
115+
udp_stats_repository.clone(),
116+
)
117+
.await;
118+
119+
assert_eq!(
120+
tracker_metrics,
121+
TrackerMetrics {
122+
torrents_metrics: TorrentsMetrics::default(),
123+
protocol_metrics: Metrics::default(),
124+
}
125+
);
126+
}
127+
}

src/servers/apis/v1/context/stats/handlers.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ use axum::extract::State;
66
use axum::response::Response;
77
use axum_extra::extract::Query;
88
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
9-
use packages::statistics::repository::Repository;
109
use serde::Deserialize;
1110
use tokio::sync::RwLock;
1211

1312
use super::responses::{metrics_response, stats_response};
14-
use crate::packages;
15-
use crate::packages::statistics::services::get_metrics;
13+
use crate::packages::tracker_api_core::statistics::services::get_metrics;
14+
use crate::packages::{http_tracker_core, udp_tracker_core};
1615
use crate::servers::udp::server::banning::BanService;
1716

1817
#[derive(Deserialize, Debug, Default)]
@@ -41,10 +40,15 @@ pub struct QueryParams {
4140
/// for more information about this endpoint.
4241
#[allow(clippy::type_complexity)]
4342
pub async fn get_stats_handler(
44-
State(state): State<(Arc<InMemoryTorrentRepository>, Arc<RwLock<BanService>>, Arc<Repository>)>,
43+
State(state): State<(
44+
Arc<InMemoryTorrentRepository>,
45+
Arc<RwLock<BanService>>,
46+
Arc<http_tracker_core::statistics::repository::Repository>,
47+
Arc<udp_tracker_core::statistics::repository::Repository>,
48+
)>,
4549
params: Query<QueryParams>,
4650
) -> Response {
47-
let metrics = get_metrics(state.0.clone(), state.1.clone(), state.2.clone()).await;
51+
let metrics = get_metrics(state.0.clone(), state.1.clone(), state.2.clone(), state.3.clone()).await;
4852

4953
match params.0.format {
5054
Some(format) => match format {

src/servers/apis/v1/context/stats/resources.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! API context.
33
use serde::{Deserialize, Serialize};
44

5-
use crate::packages::statistics::services::TrackerMetrics;
5+
use crate::packages::tracker_api_core::statistics::services::TrackerMetrics;
66

77
/// It contains all the statistics generated by the tracker.
88
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
@@ -118,11 +118,11 @@ impl From<TrackerMetrics> for Stats {
118118

119119
#[cfg(test)]
120120
mod tests {
121-
use packages::statistics::metrics::Metrics;
121+
use packages::tracker_api_core::statistics::metrics::Metrics;
122122
use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics;
123123

124124
use super::Stats;
125-
use crate::packages::statistics::services::TrackerMetrics;
125+
use crate::packages::tracker_api_core::statistics::services::TrackerMetrics;
126126
use crate::packages::{self};
127127

128128
#[test]

src/servers/apis/v1/context/stats/responses.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use axum::response::{IntoResponse, Json, Response};
44

55
use super::resources::Stats;
6-
use crate::packages::statistics::services::TrackerMetrics;
6+
use crate::packages::tracker_api_core::statistics::services::TrackerMetrics;
77

88
/// `200` response that contains the [`Stats`] resource as json.
99
#[must_use]

src/servers/apis/v1/context/stats/routes.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ pub fn add(prefix: &str, router: Router, http_api_container: &Arc<HttpApiContain
1818
get(get_stats_handler).with_state((
1919
http_api_container.in_memory_torrent_repository.clone(),
2020
http_api_container.ban_service.clone(),
21-
http_api_container.stats_repository.clone(),
21+
http_api_container.http_stats_repository.clone(),
22+
http_api_container.udp_stats_repository.clone(),
2223
)),
2324
)
2425
}

tests/servers/api/environment.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ impl Environment<Stopped> {
6161
keys_handler: app_container.keys_handler.clone(),
6262
whitelist_manager: app_container.whitelist_manager.clone(),
6363
ban_service: app_container.ban_service.clone(),
64-
stats_event_sender: app_container.stats_event_sender.clone(),
65-
stats_repository: app_container.stats_repository.clone(),
64+
http_stats_repository: app_container.http_stats_repository.clone(),
65+
udp_stats_repository: app_container.udp_stats_repository.clone(),
6666
});
6767

6868
Self {

0 commit comments

Comments
 (0)