forked from torrust/torrust-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservices.rs
More file actions
147 lines (132 loc) · 5.63 KB
/
services.rs
File metadata and controls
147 lines (132 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! 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::statistics::metrics::Metrics).
//!
//! Tracker metrics are collected using a Publisher-Subscribe pattern.
//!
//! The factory function builds two structs:
//!
//! - An statistics event [`Sender`](crate::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::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 bittorrent_udp_tracker_core::services::banning::BanService;
use tokio::sync::RwLock;
use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics;
use crate::statistics::metrics::Metrics;
use crate::statistics::repository::Repository;
/// 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<InMemoryTorrentRepository>,
ban_service: Arc<RwLock<BanService>>,
stats_repository: Arc<Repository>,
) -> 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 bittorrent_udp_tracker_core::services::banning::BanService;
use bittorrent_udp_tracker_core::MAX_CONNECTION_ID_ERRORS_PER_IP;
use tokio::sync::RwLock;
use torrust_tracker_configuration::Configuration;
use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics;
use torrust_tracker_test_helpers::configuration;
use crate::statistics;
use crate::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 ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP)));
let (_udp_server_stats_event_sender, udp_server_stats_repository) =
statistics::setup::factory(config.core.tracker_usage_statistics);
let udp_server_stats_repository = Arc::new(udp_server_stats_repository);
let tracker_metrics = get_metrics(
in_memory_torrent_repository.clone(),
ban_service.clone(),
udp_server_stats_repository.clone(),
)
.await;
assert_eq!(
tracker_metrics,
TrackerMetrics {
torrents_metrics: TorrentsMetrics::default(),
protocol_metrics: statistics::metrics::Metrics::default(),
}
);
}
}