Skip to content

Commit 3bade2c

Browse files
committed
Merge #1545: Overhaul stats: Allow removing peerless torrents without affecting global torrent downloads metric
92242f8 fix: [#1543] Remove peerless torrents when it's enabled in the tracker policy (Jose Celano) 43c7179 refactor: [#1543] rename Metrics to ProtocolMetrics (Jose Celano) b0e7443 fix: [#1543] return always in API the downloads number from tracker-core (Jose Celano) 8d3a6fe refactor: [#1543] extract methods (Jose Celano) 02c33f6 fix: [#1543] the downloads counter values returned in the API (Jose Celano) 762bf69 refactor: [#1543] Optimization: Don't load number of downloads from DB if not needed (Jose Celano) e107614 chore: [#1543] remove comment on tracker-core handle_announcement (Jose Celano) 3d6fc65 refactor: [#1543] rename AggregateSwarmMetadata to AggregateActiveSwarmMetadata (Jose Celano) Pull request description: ### Subtasks - [x] Rename AggregateSwarmMetadata to AggregateActiveSwarmMetadata. Aggregate values are only for active swarms. For example, it does not count downloads for torrents that are not currently active. - [x] Little optimisation. Avoid loading the number of downloads for a torrent from the DB if it's not needed. - [x] Fix the downloads counter values returned in the API. - [x] Remove peerless torrents when it's enabled in the tracker policy. It was not allowed because it affected the global number of downloads exposed via the API. That problem has been solved in the PR. After merging this PR, the tracker will save memory because peerless torrents will be removed from memory (when that policy is enabled) even when stats is enabled. ACKs for top commit: josecelano: ACK 92242f8 Tree-SHA512: 3b6d639c01dfd90c974769c7b76930b7e94dec746691fbb070cb94c76f97c74e8f30c8a4736ce9023fae404e1322435e184bf5b6932342eeabe2f323c60f55f9
2 parents 4b4f310 + 92242f8 commit 3bade2c

File tree

28 files changed

+231
-141
lines changed

28 files changed

+231
-141
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/axum-rest-tracker-api-server/src/v1/context/stats/handlers.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,20 @@ pub async fn get_stats_handler(
4242
State(state): State<(
4343
Arc<InMemoryTorrentRepository>,
4444
Arc<RwLock<BanService>>,
45+
Arc<bittorrent_tracker_core::statistics::repository::Repository>,
4546
Arc<bittorrent_http_tracker_core::statistics::repository::Repository>,
4647
Arc<torrust_udp_tracker_server::statistics::repository::Repository>,
4748
)>,
4849
params: Query<QueryParams>,
4950
) -> Response {
50-
let metrics = get_metrics(state.0.clone(), state.1.clone(), state.2.clone(), state.3.clone()).await;
51+
let metrics = get_metrics(
52+
state.0.clone(),
53+
state.1.clone(),
54+
state.2.clone(),
55+
state.3.clone(),
56+
state.4.clone(),
57+
)
58+
.await;
5159

5260
match params.0.format {
5361
Some(format) => match format {

packages/axum-rest-tracker-api-server/src/v1/context/stats/resources.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ impl From<TrackerLabeledMetrics> for LabeledStats {
134134

135135
#[cfg(test)]
136136
mod tests {
137-
use torrust_rest_tracker_api_core::statistics::metrics::Metrics;
137+
use torrust_rest_tracker_api_core::statistics::metrics::{ProtocolMetrics, TorrentsMetrics};
138138
use torrust_rest_tracker_api_core::statistics::services::TrackerMetrics;
139-
use torrust_tracker_primitives::swarm_metadata::AggregateSwarmMetadata;
140139

141140
use super::Stats;
142141

@@ -145,13 +144,13 @@ mod tests {
145144
fn stats_resource_should_be_converted_from_tracker_metrics() {
146145
assert_eq!(
147146
Stats::from(TrackerMetrics {
148-
torrents_metrics: AggregateSwarmMetadata {
147+
torrents_metrics: TorrentsMetrics {
149148
total_complete: 1,
150149
total_downloaded: 2,
151150
total_incomplete: 3,
152151
total_torrents: 4
153152
},
154-
protocol_metrics: Metrics {
153+
protocol_metrics: ProtocolMetrics {
155154
// TCP
156155
tcp4_connections_handled: 5,
157156
tcp4_announces_handled: 6,

packages/axum-rest-tracker-api-server/src/v1/context/stats/routes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn add(prefix: &str, router: Router, http_api_container: &Arc<TrackerHttpApi
1919
get(get_stats_handler).with_state((
2020
http_api_container.tracker_core_container.in_memory_torrent_repository.clone(),
2121
http_api_container.ban_service.clone(),
22+
http_api_container.tracker_core_container.stats_repository.clone(),
2223
http_api_container.http_stats_repository.clone(),
2324
http_api_container.udp_server_stats_repository.clone(),
2425
)),

packages/http-tracker-core/src/statistics/services.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
use std::sync::Arc;
2424

2525
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
26-
use torrust_tracker_primitives::swarm_metadata::AggregateSwarmMetadata;
26+
use torrust_tracker_primitives::swarm_metadata::AggregateActiveSwarmMetadata;
2727

2828
use crate::statistics::metrics::Metrics;
2929
use crate::statistics::repository::Repository;
@@ -34,7 +34,7 @@ pub struct TrackerMetrics {
3434
/// Domain level metrics.
3535
///
3636
/// General metrics for all torrents (number of seeders, leechers, etcetera)
37-
pub torrents_metrics: AggregateSwarmMetadata,
37+
pub torrents_metrics: AggregateActiveSwarmMetadata,
3838

3939
/// Application level metrics. Usage statistics/metrics.
4040
///
@@ -72,7 +72,7 @@ mod tests {
7272
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
7373
use bittorrent_tracker_core::{self};
7474
use torrust_tracker_configuration::Configuration;
75-
use torrust_tracker_primitives::swarm_metadata::AggregateSwarmMetadata;
75+
use torrust_tracker_primitives::swarm_metadata::AggregateActiveSwarmMetadata;
7676
use torrust_tracker_test_helpers::configuration;
7777

7878
use crate::event::bus::EventBus;
@@ -109,7 +109,7 @@ mod tests {
109109
assert_eq!(
110110
tracker_metrics,
111111
TrackerMetrics {
112-
torrents_metrics: AggregateSwarmMetadata::default(),
112+
torrents_metrics: AggregateActiveSwarmMetadata::default(),
113113
protocol_metrics: describe_metrics(),
114114
}
115115
);

packages/primitives/src/swarm_metadata.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,23 @@ impl SwarmMetadata {
4646

4747
/// Structure that holds aggregate swarm metadata.
4848
///
49-
/// Metrics are aggregate values for all torrents.
49+
/// Metrics are aggregate values for all active torrents/swarms.
5050
#[derive(Copy, Clone, Debug, PartialEq, Default)]
51-
pub struct AggregateSwarmMetadata {
52-
/// Total number of peers that have ever completed downloading for all
53-
/// torrents.
51+
pub struct AggregateActiveSwarmMetadata {
52+
/// Total number of peers that have ever completed downloading.
5453
pub total_downloaded: u64,
5554

56-
/// Total number of seeders for all torrents.
55+
/// Total number of seeders.
5756
pub total_complete: u64,
5857

59-
/// Total number of leechers for all torrents.
58+
/// Total number of leechers.
6059
pub total_incomplete: u64,
6160

6261
/// Total number of torrents.
6362
pub total_torrents: u64,
6463
}
6564

66-
impl AddAssign for AggregateSwarmMetadata {
65+
impl AddAssign for AggregateActiveSwarmMetadata {
6766
fn add_assign(&mut self, rhs: Self) {
6867
self.total_complete += rhs.total_complete;
6968
self.total_downloaded += rhs.total_downloaded;

packages/rest-tracker-api-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ torrust-tracker-torrent-repository = { version = "3.0.0-develop", path = "../tor
2525
torrust-udp-tracker-server = { version = "3.0.0-develop", path = "../udp-tracker-server" }
2626

2727
[dev-dependencies]
28+
torrust-tracker-events = { version = "3.0.0-develop", path = "../events" }
2829
torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "../test-helpers" }

packages/rest-tracker-api-core/src/statistics/metrics.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,33 @@
1-
/// Metrics collected by the tracker.
1+
use torrust_tracker_primitives::swarm_metadata::AggregateActiveSwarmMetadata;
2+
3+
/// Metrics collected by the tracker at the swarm layer.
4+
#[derive(Copy, Clone, Debug, PartialEq, Default)]
5+
pub struct TorrentsMetrics {
6+
/// Total number of peers that have ever completed downloading.
7+
pub total_downloaded: u64,
8+
9+
/// Total number of seeders.
10+
pub total_complete: u64,
11+
12+
/// Total number of leechers.
13+
pub total_incomplete: u64,
14+
15+
/// Total number of torrents.
16+
pub total_torrents: u64,
17+
}
18+
19+
impl From<AggregateActiveSwarmMetadata> for TorrentsMetrics {
20+
fn from(value: AggregateActiveSwarmMetadata) -> Self {
21+
Self {
22+
total_downloaded: value.total_downloaded,
23+
total_complete: value.total_complete,
24+
total_incomplete: value.total_incomplete,
25+
total_torrents: value.total_torrents,
26+
}
27+
}
28+
}
29+
30+
/// Metrics collected by the tracker at the delivery layer.
231
///
332
/// - Number of connections handled
433
/// - Number of `announce` requests handled
@@ -7,7 +36,7 @@
736
/// These metrics are collected for each connection type: UDP and HTTP
837
/// and also for each IP version used by the peers: IPv4 and IPv6.
938
#[derive(Debug, PartialEq, Default)]
10-
pub struct Metrics {
39+
pub struct ProtocolMetrics {
1140
/// Total number of TCP (HTTP tracker) connections from IPv4 peers.
1241
/// Since the HTTP tracker spec does not require a handshake, this metric
1342
/// increases for every HTTP request.

packages/rest-tracker-api-core/src/statistics/services.rs

Lines changed: 73 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,58 @@ use bittorrent_udp_tracker_core::services::banning::BanService;
55
use bittorrent_udp_tracker_core::{self};
66
use tokio::sync::RwLock;
77
use torrust_tracker_metrics::metric_collection::MetricCollection;
8-
use torrust_tracker_primitives::swarm_metadata::AggregateSwarmMetadata;
98
use torrust_udp_tracker_server::statistics as udp_server_statistics;
109

11-
use crate::statistics::metrics::Metrics;
10+
use super::metrics::TorrentsMetrics;
11+
use crate::statistics::metrics::ProtocolMetrics;
1212

1313
/// All the metrics collected by the tracker.
1414
#[derive(Debug, PartialEq)]
1515
pub struct TrackerMetrics {
1616
/// Domain level metrics.
1717
///
1818
/// General metrics for all torrents (number of seeders, leechers, etcetera)
19-
pub torrents_metrics: AggregateSwarmMetadata,
19+
pub torrents_metrics: TorrentsMetrics,
2020

2121
/// Application level metrics. Usage statistics/metrics.
2222
///
2323
/// Metrics about how the tracker is been used (number of udp announce requests, number of http scrape requests, etcetera)
24-
pub protocol_metrics: Metrics,
24+
pub protocol_metrics: ProtocolMetrics,
2525
}
2626

2727
/// It returns all the [`TrackerMetrics`]
28-
#[allow(deprecated)]
2928
pub async fn get_metrics(
3029
in_memory_torrent_repository: Arc<InMemoryTorrentRepository>,
3130
ban_service: Arc<RwLock<BanService>>,
31+
tracker_core_stats_repository: Arc<bittorrent_tracker_core::statistics::repository::Repository>,
3232
http_stats_repository: Arc<bittorrent_http_tracker_core::statistics::repository::Repository>,
3333
udp_server_stats_repository: Arc<udp_server_statistics::repository::Repository>,
3434
) -> TrackerMetrics {
35-
let torrents_metrics = in_memory_torrent_repository.get_aggregate_swarm_metadata().await;
35+
TrackerMetrics {
36+
torrents_metrics: get_torrents_metrics(in_memory_torrent_repository, tracker_core_stats_repository).await,
37+
protocol_metrics: get_protocol_metrics(ban_service, http_stats_repository, udp_server_stats_repository).await,
38+
}
39+
}
40+
41+
async fn get_torrents_metrics(
42+
in_memory_torrent_repository: Arc<InMemoryTorrentRepository>,
43+
44+
tracker_core_stats_repository: Arc<bittorrent_tracker_core::statistics::repository::Repository>,
45+
) -> TorrentsMetrics {
46+
let aggregate_active_swarm_metadata = in_memory_torrent_repository.get_aggregate_swarm_metadata().await;
47+
48+
let mut torrents_metrics: TorrentsMetrics = aggregate_active_swarm_metadata.into();
49+
torrents_metrics.total_downloaded = tracker_core_stats_repository.get_torrents_downloads_total().await;
50+
51+
torrents_metrics
52+
}
53+
54+
#[allow(deprecated)]
55+
async fn get_protocol_metrics(
56+
ban_service: Arc<RwLock<BanService>>,
57+
http_stats_repository: Arc<bittorrent_http_tracker_core::statistics::repository::Repository>,
58+
udp_server_stats_repository: Arc<udp_server_statistics::repository::Repository>,
59+
) -> ProtocolMetrics {
3660
let udp_banned_ips_total = ban_service.read().await.get_banned_ips_total();
3761
let http_stats = http_stats_repository.get_stats().await;
3862
let udp_server_stats = udp_server_stats_repository.get_stats().await;
@@ -42,39 +66,36 @@ pub async fn get_metrics(
4266
// tracker, but we keep them for now. In new major versions we should remove
4367
// them.
4468

45-
TrackerMetrics {
46-
torrents_metrics,
47-
protocol_metrics: Metrics {
48-
// TCPv4
49-
tcp4_connections_handled: http_stats.tcp4_announces_handled + http_stats.tcp4_scrapes_handled,
50-
tcp4_announces_handled: http_stats.tcp4_announces_handled,
51-
tcp4_scrapes_handled: http_stats.tcp4_scrapes_handled,
52-
// TCPv6
53-
tcp6_connections_handled: http_stats.tcp6_announces_handled + http_stats.tcp6_scrapes_handled,
54-
tcp6_announces_handled: http_stats.tcp6_announces_handled,
55-
tcp6_scrapes_handled: http_stats.tcp6_scrapes_handled,
56-
// UDP
57-
udp_requests_aborted: udp_server_stats.udp_requests_aborted,
58-
udp_requests_banned: udp_server_stats.udp_requests_banned,
59-
udp_banned_ips_total: udp_banned_ips_total as u64,
60-
udp_avg_connect_processing_time_ns: udp_server_stats.udp_avg_connect_processing_time_ns,
61-
udp_avg_announce_processing_time_ns: udp_server_stats.udp_avg_announce_processing_time_ns,
62-
udp_avg_scrape_processing_time_ns: udp_server_stats.udp_avg_scrape_processing_time_ns,
63-
// UDPv4
64-
udp4_requests: udp_server_stats.udp4_requests,
65-
udp4_connections_handled: udp_server_stats.udp4_connections_handled,
66-
udp4_announces_handled: udp_server_stats.udp4_announces_handled,
67-
udp4_scrapes_handled: udp_server_stats.udp4_scrapes_handled,
68-
udp4_responses: udp_server_stats.udp4_responses,
69-
udp4_errors_handled: udp_server_stats.udp4_errors_handled,
70-
// UDPv6
71-
udp6_requests: udp_server_stats.udp6_requests,
72-
udp6_connections_handled: udp_server_stats.udp6_connections_handled,
73-
udp6_announces_handled: udp_server_stats.udp6_announces_handled,
74-
udp6_scrapes_handled: udp_server_stats.udp6_scrapes_handled,
75-
udp6_responses: udp_server_stats.udp6_responses,
76-
udp6_errors_handled: udp_server_stats.udp6_errors_handled,
77-
},
69+
ProtocolMetrics {
70+
// TCPv4
71+
tcp4_connections_handled: http_stats.tcp4_announces_handled + http_stats.tcp4_scrapes_handled,
72+
tcp4_announces_handled: http_stats.tcp4_announces_handled,
73+
tcp4_scrapes_handled: http_stats.tcp4_scrapes_handled,
74+
// TCPv6
75+
tcp6_connections_handled: http_stats.tcp6_announces_handled + http_stats.tcp6_scrapes_handled,
76+
tcp6_announces_handled: http_stats.tcp6_announces_handled,
77+
tcp6_scrapes_handled: http_stats.tcp6_scrapes_handled,
78+
// UDP
79+
udp_requests_aborted: udp_server_stats.udp_requests_aborted,
80+
udp_requests_banned: udp_server_stats.udp_requests_banned,
81+
udp_banned_ips_total: udp_banned_ips_total as u64,
82+
udp_avg_connect_processing_time_ns: udp_server_stats.udp_avg_connect_processing_time_ns,
83+
udp_avg_announce_processing_time_ns: udp_server_stats.udp_avg_announce_processing_time_ns,
84+
udp_avg_scrape_processing_time_ns: udp_server_stats.udp_avg_scrape_processing_time_ns,
85+
// UDPv4
86+
udp4_requests: udp_server_stats.udp4_requests,
87+
udp4_connections_handled: udp_server_stats.udp4_connections_handled,
88+
udp4_announces_handled: udp_server_stats.udp4_announces_handled,
89+
udp4_scrapes_handled: udp_server_stats.udp4_scrapes_handled,
90+
udp4_responses: udp_server_stats.udp4_responses,
91+
udp4_errors_handled: udp_server_stats.udp4_errors_handled,
92+
// UDPv6
93+
udp6_requests: udp_server_stats.udp6_requests,
94+
udp6_connections_handled: udp_server_stats.udp6_connections_handled,
95+
udp6_announces_handled: udp_server_stats.udp6_announces_handled,
96+
udp6_scrapes_handled: udp_server_stats.udp6_scrapes_handled,
97+
udp6_responses: udp_server_stats.udp6_responses,
98+
udp6_errors_handled: udp_server_stats.udp6_errors_handled,
7899
}
79100
}
80101

@@ -89,7 +110,6 @@ pub struct TrackerLabeledMetrics {
89110
///
90111
/// Will panic if the metrics cannot be merged. This could happen if the
91112
/// packages are producing duplicate metric names, for example.
92-
#[allow(deprecated)]
93113
pub async fn get_labeled_metrics(
94114
in_memory_torrent_repository: Arc<InMemoryTorrentRepository>,
95115
ban_service: Arc<RwLock<BanService>>,
@@ -138,16 +158,17 @@ mod tests {
138158
use bittorrent_http_tracker_core::event::sender::Broadcaster;
139159
use bittorrent_http_tracker_core::statistics::event::listener::run_event_listener;
140160
use bittorrent_http_tracker_core::statistics::repository::Repository;
141-
use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepository;
161+
use bittorrent_tracker_core::container::TrackerCoreContainer;
142162
use bittorrent_tracker_core::{self};
143163
use bittorrent_udp_tracker_core::services::banning::BanService;
144164
use bittorrent_udp_tracker_core::MAX_CONNECTION_ID_ERRORS_PER_IP;
145165
use tokio::sync::RwLock;
146166
use torrust_tracker_configuration::Configuration;
147-
use torrust_tracker_primitives::swarm_metadata::AggregateSwarmMetadata;
167+
use torrust_tracker_events::bus::SenderStatus;
148168
use torrust_tracker_test_helpers::configuration;
169+
use torrust_tracker_torrent_repository::container::TorrentRepositoryContainer;
149170

150-
use crate::statistics::metrics::Metrics;
171+
use crate::statistics::metrics::{ProtocolMetrics, TorrentsMetrics};
151172
use crate::statistics::services::{get_metrics, TrackerMetrics};
152173

153174
pub fn tracker_configuration() -> Configuration {
@@ -157,8 +178,12 @@ mod tests {
157178
#[tokio::test]
158179
async fn the_statistics_service_should_return_the_tracker_metrics() {
159180
let config = tracker_configuration();
181+
let core_config = Arc::new(config.core.clone());
182+
183+
let torrent_repository_container = Arc::new(TorrentRepositoryContainer::initialize(SenderStatus::Enabled));
184+
185+
let tracker_core_container = TrackerCoreContainer::initialize_from(&core_config, &torrent_repository_container.clone());
160186

161-
let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default());
162187
let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP)));
163188

164189
// HTTP core stats
@@ -177,8 +202,9 @@ mod tests {
177202
let udp_server_stats_repository = Arc::new(torrust_udp_tracker_server::statistics::repository::Repository::new());
178203

179204
let tracker_metrics = get_metrics(
180-
in_memory_torrent_repository.clone(),
205+
tracker_core_container.in_memory_torrent_repository.clone(),
181206
ban_service.clone(),
207+
tracker_core_container.stats_repository.clone(),
182208
http_stats_repository.clone(),
183209
udp_server_stats_repository.clone(),
184210
)
@@ -187,8 +213,8 @@ mod tests {
187213
assert_eq!(
188214
tracker_metrics,
189215
TrackerMetrics {
190-
torrents_metrics: AggregateSwarmMetadata::default(),
191-
protocol_metrics: Metrics::default(),
216+
torrents_metrics: TorrentsMetrics::default(),
217+
protocol_metrics: ProtocolMetrics::default(),
192218
}
193219
);
194220
}

0 commit comments

Comments
 (0)